summaryrefslogtreecommitdiffstats
path: root/src/bdd/llb
diff options
context:
space:
mode:
Diffstat (limited to 'src/bdd/llb')
-rw-r--r--src/bdd/llb/llb.c52
-rw-r--r--src/bdd/llb/llb.h96
-rw-r--r--src/bdd/llb/llb1Cluster.c356
-rw-r--r--src/bdd/llb/llb1Constr.c313
-rw-r--r--src/bdd/llb/llb1Core.c222
-rw-r--r--src/bdd/llb/llb1Group.c474
-rw-r--r--src/bdd/llb/llb1Hint.c226
-rw-r--r--src/bdd/llb/llb1Man.c218
-rw-r--r--src/bdd/llb/llb1Matrix.c430
-rw-r--r--src/bdd/llb/llb1Pivot.c254
-rw-r--r--src/bdd/llb/llb1Reach.c904
-rw-r--r--src/bdd/llb/llb1Sched.c257
-rw-r--r--src/bdd/llb/llb2Bad.c138
-rw-r--r--src/bdd/llb/llb2Core.c777
-rw-r--r--src/bdd/llb/llb2Driver.c222
-rw-r--r--src/bdd/llb/llb2Dump.c104
-rw-r--r--src/bdd/llb/llb2Flow.c1376
-rw-r--r--src/bdd/llb/llb2Image.c482
-rw-r--r--src/bdd/llb/llb3Image.c1095
-rw-r--r--src/bdd/llb/llb3Nonlin.c872
-rw-r--r--src/bdd/llb/llb4Cex.c320
-rw-r--r--src/bdd/llb/llb4Cluster.c452
-rw-r--r--src/bdd/llb/llb4Image.c863
-rw-r--r--src/bdd/llb/llb4Map.c123
-rw-r--r--src/bdd/llb/llb4Nonlin.c1185
-rw-r--r--src/bdd/llb/llb4Sweep.c589
-rw-r--r--src/bdd/llb/llbInt.h212
-rw-r--r--src/bdd/llb/module.make22
28 files changed, 12634 insertions, 0 deletions
diff --git a/src/bdd/llb/llb.c b/src/bdd/llb/llb.c
new file mode 100644
index 00000000..348c0622
--- /dev/null
+++ b/src/bdd/llb/llb.c
@@ -0,0 +1,52 @@
+/**CFile****************************************************************
+
+ FileName [llb.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/bdd/llb/llb.h b/src/bdd/llb/llb.h
new file mode 100644
index 00000000..f465359d
--- /dev/null
+++ b/src/bdd/llb/llb.h
@@ -0,0 +1,96 @@
+/**CFile****************************************************************
+
+ FileName [llb.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD-based reachability.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 8, 2010.]
+
+ Revision [$Id: llb.h,v 1.00 2010/05/08 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__llb__llb_h
+#define ABC__aig__llb__llb_h
+
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Gia_ParLlb_t_ Gia_ParLlb_t;
+struct Gia_ParLlb_t_
+{
+ int nBddMax; // maximum BDD size
+ int nIterMax; // maximum iteration count
+ int nClusterMax; // maximum cluster size
+ int nHintDepth; // the number of times to cofactor
+ int HintFirst; // the number of first hint to use
+ int fUseFlow; // use flow computation
+ int nVolumeMax; // the largest volume
+ int nVolumeMin; // the smallest volume
+ int nPartValue; // partitioning value
+ int fBackward; // enable backward reachability
+ int fReorder; // enable dynamic variable reordering
+ int fIndConstr; // extract inductive constraints
+ int fUsePivots; // use internal pivot variables
+ int fCluster; // use partition clustering
+ int fSchedule; // use cluster scheduling
+ int fDumpReached; // dump reached states into a file
+ int fVerbose; // print verbose information
+ int fVeryVerbose; // print dependency matrices
+ int fSilent; // do not print any infomation
+ int fSkipReach; // skip reachability (preparation phase only)
+ int fSkipOutCheck; // does not check the property output
+ int TimeLimit; // time limit for one reachability run
+ int TimeLimitGlo; // time limit for all reachability runs
+ // internal parameters
+ abctime TimeTarget; // the time to stop
+ int iFrame; // explored up to this frame
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== llbCore.c ==========================================================*/
+extern void Llb_ManSetDefaultParams( Gia_ParLlb_t * pPars );
+/*=== llb4Nonlin.c ==========================================================*/
+extern int Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/bdd/llb/llb1Cluster.c b/src/bdd/llb/llb1Cluster.c
new file mode 100644
index 00000000..1356e484
--- /dev/null
+++ b/src/bdd/llb/llb1Cluster.c
@@ -0,0 +1,356 @@
+/**CFile****************************************************************
+
+ FileName [llb1Cluster.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Clustering algorithm.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb1Cluster.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManComputeCommonQuant( Llb_Mtr_t * p, int iCol1, int iCol2 )
+{
+ int iVar, Weight = 0;
+ for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ )
+ {
+ // count each removed variable as 2
+ if ( p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 1 && p->pRowSums[iVar] == 2 )
+ Weight += 2;
+ // count each added variale as -1
+ else if ( (p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 0) ||
+ (p->pMatrix[iCol1][iVar] == 0 && p->pMatrix[iCol2][iVar] == 1) )
+ Weight--;
+ }
+ return Weight;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManComputeBestQuant( Llb_Mtr_t * p )
+{
+ int i, k, WeightBest = -100000, WeightCur, RetValue = -1;
+ for ( i = 1; i < p->nCols-1; i++ )
+ for ( k = i+1; k < p->nCols-1; k++ )
+ {
+ if ( p->pColSums[i] == 0 || p->pColSums[i] > p->pMan->pPars->nClusterMax )
+ continue;
+ if ( p->pColSums[k] == 0 || p->pColSums[k] > p->pMan->pPars->nClusterMax )
+ continue;
+
+ WeightCur = Llb_ManComputeCommonQuant( p, i, k );
+ if ( WeightCur <= 0 )
+ continue;
+ if ( WeightBest < WeightCur )
+ {
+ WeightBest = WeightCur;
+ RetValue = (i << 16) | k;
+ }
+ }
+// printf( "Choosing best quant Weight %4d\n", WeightCur );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float ** Llb_ManComputeQuant( Llb_Mtr_t * p )
+{
+ float ** pCosts;
+ int i, k;
+ // alloc and clean
+ pCosts = (float **)Extra_ArrayAlloc( p->nCols, p->nCols, sizeof(float) );
+ for ( i = 0; i < p->nCols; i++ )
+ for ( k = 0; k < p->nCols; k++ )
+ pCosts[i][i] = 0.0;
+ // fill up
+ for ( i = 1; i < p->nCols-1; i++ )
+ for ( k = i+1; k < p->nCols-1; k++ )
+ pCosts[i][k] = pCosts[k][i] = Llb_ManComputeCommonQuant( p, i, k );
+ return pCosts;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Llb_ManComputeCommonAttr( Llb_Mtr_t * p, int iCol1, int iCol2 )
+{
+ int iVar, CountComm = 0, CountDiff = 0;
+ for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ )
+ {
+ if ( p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 1 )
+ CountComm++;
+ else if ( p->pMatrix[iCol1][iVar] == 1 || p->pMatrix[iCol2][iVar] == 1 )
+ CountDiff++;
+ }
+/*
+ printf( "Attr cost for %4d and %4d: %4d %4d (%5.2f)\n",
+ iCol1, iCol2,
+ CountDiff, CountComm,
+ -1.0 * CountDiff / ( CountComm + CountDiff ) );
+*/
+ return -1.0 * CountDiff / ( CountComm + CountDiff );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManComputeBestAttr( Llb_Mtr_t * p )
+{
+ float WeightBest = -100000, WeightCur;
+ int i, k, RetValue = -1;
+ for ( i = 1; i < p->nCols-1; i++ )
+ for ( k = i+1; k < p->nCols-1; k++ )
+ {
+ if ( p->pColSums[i] == 0 || p->pColSums[i] > p->pMan->pPars->nClusterMax )
+ continue;
+ if ( p->pColSums[k] == 0 || p->pColSums[k] > p->pMan->pPars->nClusterMax )
+ continue;
+ WeightCur = Llb_ManComputeCommonAttr( p, i, k );
+ if ( WeightBest < WeightCur )
+ {
+ WeightBest = WeightCur;
+ RetValue = (i << 16) | k;
+ }
+ }
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float ** Llb_ManComputeAttr( Llb_Mtr_t * p )
+{
+ float ** pCosts;
+ int i, k;
+ // alloc and clean
+ pCosts = (float **)Extra_ArrayAlloc( p->nCols, p->nCols, sizeof(float) );
+ for ( i = 0; i < p->nCols; i++ )
+ for ( k = 0; k < p->nCols; k++ )
+ pCosts[i][i] = 0.0;
+ // fill up
+ for ( i = 1; i < p->nCols-1; i++ )
+ for ( k = i+1; k < p->nCols-1; k++ )
+ pCosts[i][k] = pCosts[k][i] = Llb_ManComputeCommonAttr( p, i, k );
+ return pCosts;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of variables that will be saved.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MtrCombineSelectedColumns( Llb_Mtr_t * p, int iGrp1, int iGrp2 )
+{
+ int iVar;
+ assert( iGrp1 >= 1 && iGrp1 < p->nCols - 1 );
+ assert( iGrp2 >= 1 && iGrp2 < p->nCols - 1 );
+ assert( p->pColGrps[iGrp1] != NULL );
+ assert( p->pColGrps[iGrp2] != NULL );
+ for ( iVar = 0; iVar < p->nRows; iVar++ )
+ {
+ if ( p->pMatrix[iGrp1][iVar] == 1 && p->pMatrix[iGrp2][iVar] == 1 )
+ p->pRowSums[iVar]--;
+ if ( p->pMatrix[iGrp1][iVar] == 0 && p->pMatrix[iGrp2][iVar] == 1 )
+ {
+ p->pMatrix[iGrp1][iVar] = 1;
+ p->pColSums[iGrp1]++;
+ }
+ if ( p->pMatrix[iGrp2][iVar] == 1 )
+ p->pMatrix[iGrp2][iVar] = 0;
+ }
+ p->pColSums[iGrp2] = 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Combines one pair of columns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManClusterOne( Llb_Mtr_t * p, int iCol1, int iCol2 )
+{
+ int fVerbose = 0;
+ Llb_Grp_t * pGrp;
+ int iVar;
+
+ if ( fVerbose )
+ {
+ printf( "Combining %d and %d\n", iCol1, iCol2 );
+ for ( iVar = 0; iVar < p->nRows; iVar++ )
+ {
+ if ( p->pMatrix[iCol1][iVar] == 0 && p->pMatrix[iCol2][iVar] == 0 )
+ continue;
+ printf( "%3d : %c%c\n", iVar,
+ p->pMatrix[iCol1][iVar]? '*':' ',
+ p->pMatrix[iCol2][iVar]? '*':' ' );
+ }
+ }
+ pGrp = Llb_ManGroupsCombine( p->pColGrps[iCol1], p->pColGrps[iCol2] );
+ Llb_MtrCombineSelectedColumns( p, iCol1, iCol2 );
+ p->pColGrps[iCol1] = pGrp;
+ p->pColGrps[iCol2] = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes empty columns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManClusterCompress( Llb_Mtr_t * p )
+{
+ int i, k = 0;
+ for ( i = 0; i < p->nCols; i++ )
+ {
+ if ( p->pColGrps[i] == NULL )
+ {
+ assert( p->pColSums[i] == 0 );
+ assert( p->pMatrix[i] != NULL );
+ ABC_FREE( p->pMatrix[i] );
+ continue;
+ }
+ p->pMatrix[k] = p->pMatrix[i];
+ p->pColGrps[k] = p->pColGrps[i];
+ p->pColSums[k] = p->pColSums[i];
+ k++;
+ }
+ p->nCols = k;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Combines one pair of columns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManCluster( Llb_Mtr_t * p )
+{
+ int RetValue;
+ do
+ {
+ do {
+ RetValue = Llb_ManComputeBestQuant( p );
+ if ( RetValue > 0 )
+ Llb_ManClusterOne( p, RetValue >> 16, RetValue & 0xffff );
+ }
+ while ( RetValue > 0 );
+
+ RetValue = Llb_ManComputeBestAttr( p );
+ if ( RetValue > 0 )
+ Llb_ManClusterOne( p, RetValue >> 16, RetValue & 0xffff );
+
+ Llb_MtrVerifyMatrix( p );
+ }
+ while ( RetValue > 0 );
+
+ Llb_ManClusterCompress( p );
+
+ Llb_MtrVerifyMatrix( p );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/bdd/llb/llb1Constr.c b/src/bdd/llb/llb1Constr.c
new file mode 100644
index 00000000..1ef4ce14
--- /dev/null
+++ b/src/bdd/llb/llb1Constr.c
@@ -0,0 +1,313 @@
+/**CFile****************************************************************
+
+ FileName [llb1Constr.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Computing inductive constraints.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb1Constr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of constraint candidates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManCountEntries( Vec_Int_t * vCands )
+{
+ int i, Entry, Counter = 0;
+ Vec_IntForEachEntry( vCands, Entry, i )
+ Counter += ((Entry == 0) || (Entry == 1));
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of constraint candidates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManPrintEntries( Aig_Man_t * p, Vec_Int_t * vCands )
+{
+ int i, Entry;
+ if ( vCands == NULL )
+ {
+ printf( "There is no hints.\n" );
+ return;
+ }
+ Entry = Llb_ManCountEntries(vCands);
+ printf( "\n*** Using %d hint%s:\n", Entry, (Entry != 1 ? "s":"") );
+ Vec_IntForEachEntry( vCands, Entry, i )
+ {
+ if ( Entry != 0 && Entry != 1 )
+ continue;
+ printf( "%c", Entry ? '+' : '-' );
+ printf( "%-6d : ", i );
+ Aig_ObjPrint( p, Aig_ManObj(p, i) );
+ printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Dereference BDD nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManDerefenceBdds( Aig_Man_t * p, DdManager * dd )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Aig_ManForEachObj( p, pObj, i )
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of constraint candidates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_ManComputeIndCase_rec( Aig_Man_t * p, Aig_Obj_t * pObj, DdManager * dd, Vec_Ptr_t * vBdds )
+{
+ DdNode * bBdd0, * bBdd1;
+ DdNode * bFunc = (DdNode *)Vec_PtrEntry( vBdds, Aig_ObjId(pObj) );
+ if ( bFunc != NULL )
+ return bFunc;
+ assert( Aig_ObjIsNode(pObj) );
+ bBdd0 = Llb_ManComputeIndCase_rec( p, Aig_ObjFanin0(pObj), dd, vBdds );
+ bBdd1 = Llb_ManComputeIndCase_rec( p, Aig_ObjFanin1(pObj), dd, vBdds );
+ bBdd0 = Cudd_NotCond( bBdd0, Aig_ObjFaninC0(pObj) );
+ bBdd1 = Cudd_NotCond( bBdd1, Aig_ObjFaninC1(pObj) );
+ bFunc = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bFunc );
+ Vec_PtrWriteEntry( vBdds, Aig_ObjId(pObj), bFunc );
+ return bFunc;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of constraint candidates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManComputeIndCase( Aig_Man_t * p, DdManager * dd, Vec_Int_t * vNodes )
+{
+ Vec_Ptr_t * vBdds;
+ Aig_Obj_t * pObj;
+ DdNode * bFunc;
+ int i, Entry;
+ vBdds = Vec_PtrStart( Aig_ManObjNumMax(p) );
+ bFunc = Cudd_ReadOne(dd); Cudd_Ref( bFunc );
+ Vec_PtrWriteEntry( vBdds, Aig_ObjId(Aig_ManConst1(p)), bFunc );
+ Saig_ManForEachPi( p, pObj, i )
+ {
+ bFunc = Cudd_bddIthVar( dd, Aig_ManCiNum(p) + i ); Cudd_Ref( bFunc );
+ Vec_PtrWriteEntry( vBdds, Aig_ObjId(pObj), bFunc );
+ }
+ Saig_ManForEachLi( p, pObj, i )
+ {
+ bFunc = (DdNode *)pObj->pData; Cudd_Ref( bFunc );
+ Vec_PtrWriteEntry( vBdds, Aig_ObjId(Saig_ObjLiToLo(p, pObj)), bFunc );
+ }
+ Vec_IntForEachEntry( vNodes, Entry, i )
+ {
+ if ( Entry != 0 && Entry != 1 )
+ continue;
+ pObj = Aig_ManObj( p, i );
+ bFunc = Llb_ManComputeIndCase_rec( p, pObj, dd, vBdds );
+ if ( Entry == 0 )
+ {
+// Extra_bddPrint( dd, Cudd_Not(pObj->pData) ); printf( "\n" );
+// Extra_bddPrint( dd, Cudd_Not(bFunc) ); printf( "\n" );
+ if ( !Cudd_bddLeq( dd, Cudd_Not(pObj->pData), Cudd_Not(bFunc) ) )
+ Vec_IntWriteEntry( vNodes, i, -1 );
+ }
+ else if ( Entry == 1 )
+ {
+// Extra_bddPrint( dd, pObj->pData ); printf( "\n" );
+// Extra_bddPrint( dd, bFunc ); printf( "\n" );
+ if ( !Cudd_bddLeq( dd, (DdNode *)pObj->pData, bFunc ) )
+ Vec_IntWriteEntry( vNodes, i, -1 );
+ }
+ }
+ Vec_PtrForEachEntry( DdNode *, vBdds, bFunc, i )
+ if ( bFunc )
+ Cudd_RecursiveDeref( dd, bFunc );
+ Vec_PtrFree( vBdds );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of constraint candidates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_ManComputeBaseCase( Aig_Man_t * p, DdManager * dd )
+{
+ Vec_Int_t * vNodes;
+ Aig_Obj_t * pObj, * pRoot;
+ int i;
+ pRoot = Aig_ManCo( p, 0 );
+ vNodes = Vec_IntStartFull( Aig_ManObjNumMax(p) );
+ Aig_ManForEachObj( p, pObj, i )
+ {
+ if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) )
+ continue;
+ if ( Cudd_bddLeq( dd, (DdNode *)pObj->pData, Cudd_Not(pRoot->pData) ) )
+ Vec_IntWriteEntry( vNodes, i, 1 );
+ else if ( Cudd_bddLeq( dd, Cudd_Not((DdNode *)pObj->pData), Cudd_Not(pRoot->pData) ) )
+ Vec_IntWriteEntry( vNodes, i, 0 );
+ }
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Constructs global BDDs for each object in the AIG manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdManager * Llb_ManConstructGlobalBdds( Aig_Man_t * p )
+{
+ DdManager * dd;
+ DdNode * bBdd0, * bBdd1;
+ Aig_Obj_t * pObj;
+ int i;
+ dd = Cudd_Init( Aig_ManCiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+ pObj = Aig_ManConst1(p);
+ pObj->pData = Cudd_ReadOne(dd); Cudd_Ref( (DdNode *)pObj->pData );
+ Aig_ManForEachCi( p, pObj, i )
+ {
+ pObj->pData = Cudd_bddIthVar(dd, i); Cudd_Ref( (DdNode *)pObj->pData );
+ }
+ Aig_ManForEachNode( p, pObj, i )
+ {
+ bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+ pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData );
+ }
+ Aig_ManForEachCo( p, pObj, i )
+ {
+ pObj->pData = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); Cudd_Ref( (DdNode *)pObj->pData );
+ }
+ return dd;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives inductive constraints.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_ManDeriveConstraints( Aig_Man_t * p )
+{
+ DdManager * dd;
+ Vec_Int_t * vNodes;
+ if ( Saig_ManPoNum(p) != 1 )
+ {
+ printf( "The AIG has %d property outputs.\n", Saig_ManPoNum(p) );
+ return NULL;
+ }
+ assert( Saig_ManPoNum(p) == 1 );
+ dd = Llb_ManConstructGlobalBdds( p );
+ vNodes = Llb_ManComputeBaseCase( p, dd );
+ if ( Llb_ManCountEntries(vNodes) > 0 )
+ Llb_ManComputeIndCase( p, dd, vNodes );
+ if ( Llb_ManCountEntries(vNodes) == 0 )
+ Vec_IntFreeP( &vNodes );
+ Llb_ManDerefenceBdds( p, dd );
+ Extra_StopManager( dd );
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Tests derived constraints.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManConstrTest( Aig_Man_t * p )
+{
+ Vec_Int_t * vNodes;
+ vNodes = Llb_ManDeriveConstraints( p );
+ Llb_ManPrintEntries( p, vNodes );
+ Vec_IntFreeP( &vNodes );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/bdd/llb/llb1Core.c b/src/bdd/llb/llb1Core.c
new file mode 100644
index 00000000..213f2cd9
--- /dev/null
+++ b/src/bdd/llb/llb1Core.c
@@ -0,0 +1,222 @@
+/**CFile****************************************************************
+
+ FileName [llb1Core.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Top-level procedure.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb1Core.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+#include "aig/gia/gia.h"
+#include "aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManSetDefaultParams( Gia_ParLlb_t * p )
+{
+ memset( p, 0, sizeof(Gia_ParLlb_t) );
+ p->nBddMax = 10000000;
+ p->nIterMax = 10000000;
+ p->nClusterMax = 20;
+ p->nHintDepth = 0;
+ p->HintFirst = 0;
+ p->fUseFlow = 0; // use flow
+ p->nVolumeMax = 100; // max volume
+ p->nVolumeMin = 30; // min volume
+ p->nPartValue = 5; // partitioning value
+ p->fBackward = 0; // forward by default
+ p->fReorder = 1;
+ p->fIndConstr = 0;
+ p->fUsePivots = 0;
+ p->fCluster = 0;
+ p->fSchedule = 0;
+ p->fDumpReached = 0;
+ p->fVerbose = 0;
+ p->fVeryVerbose = 0;
+ p->fSilent = 0;
+ p->TimeLimit = 0;
+// p->TimeLimit = 0;
+ p->TimeLimitGlo = 0;
+ p->TimeTarget = 0;
+ p->iFrame = -1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints statistics about MFFCs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManPrintAig( Llb_Man_t * p )
+{
+ Abc_Print( 1, "pi =%3d ", Saig_ManPiNum(p->pAig) );
+ Abc_Print( 1, "po =%3d ", Saig_ManPoNum(p->pAig) );
+ Abc_Print( 1, "ff =%3d ", Saig_ManRegNum(p->pAig) );
+ Abc_Print( 1, "int =%5d ", Vec_IntSize(p->vVar2Obj)-Aig_ManCiNum(p->pAig)-Saig_ManRegNum(p->pAig) );
+ Abc_Print( 1, "var =%5d ", Vec_IntSize(p->vVar2Obj) );
+ Abc_Print( 1, "part =%5d ", Vec_PtrSize(p->vGroups)-2 );
+ Abc_Print( 1, "and =%5d ", Aig_ManNodeNum(p->pAig) );
+ Abc_Print( 1, "lev =%4d ", Aig_ManLevelNum(p->pAig) );
+// Abc_Print( 1, "cut =%4d ", Llb_ManCrossCut(p->pAig) );
+ Abc_Print( 1, "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManModelCheckAig( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars, Vec_Int_t * vHints, DdManager ** pddGlo )
+{
+ Llb_Man_t * p = NULL;
+ Aig_Man_t * pAig;
+ int RetValue = -1;
+ abctime clk = Abc_Clock();
+
+ if ( pPars->fIndConstr )
+ {
+ assert( vHints == NULL );
+ vHints = Llb_ManDeriveConstraints( pAigGlo );
+ }
+
+ // derive AIG for hints
+ if ( vHints == NULL )
+ pAig = Aig_ManDupSimple( pAigGlo );
+ else
+ {
+ if ( pPars->fVerbose )
+ Llb_ManPrintEntries( pAigGlo, vHints );
+ pAig = Aig_ManDupSimpleWithHints( pAigGlo, vHints );
+ }
+
+
+ if ( pPars->fUseFlow )
+ {
+// p = Llb_ManStartFlow( pAigGlo, pAig, pPars );
+ }
+ else
+ {
+ p = Llb_ManStart( pAigGlo, pAig, pPars );
+ if ( pPars->fVerbose )
+ {
+ Llb_ManPrintAig( p );
+ printf( "Original matrix: " );
+ Llb_MtrPrintMatrixStats( p->pMatrix );
+ if ( pPars->fVeryVerbose )
+ Llb_MtrPrint( p->pMatrix, 1 );
+ }
+ if ( pPars->fCluster )
+ {
+ Llb_ManCluster( p->pMatrix );
+ if ( pPars->fVerbose )
+ {
+ printf( "Matrix after clustering: " );
+ Llb_MtrPrintMatrixStats( p->pMatrix );
+ if ( pPars->fVeryVerbose )
+ Llb_MtrPrint( p->pMatrix, 1 );
+ }
+ }
+ if ( pPars->fSchedule )
+ {
+ Llb_MtrSchedule( p->pMatrix );
+ if ( pPars->fVerbose )
+ {
+ printf( "Matrix after scheduling: " );
+ Llb_MtrPrintMatrixStats( p->pMatrix );
+ if ( pPars->fVeryVerbose )
+ Llb_MtrPrint( p->pMatrix, 1 );
+ }
+ }
+ }
+
+ if ( !p->pPars->fSkipReach )
+ RetValue = Llb_ManReachability( p, vHints, pddGlo );
+ Llb_ManStop( p );
+
+ Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+
+ if ( pPars->fIndConstr )
+ Vec_IntFreeP( &vHints );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManModelCheckGia( Gia_Man_t * pGia, Gia_ParLlb_t * pPars )
+{
+ Gia_Man_t * pGia2;
+ Aig_Man_t * pAig;
+ int RetValue = -1;
+ pGia2 = Gia_ManDupDfs( pGia );
+ pAig = Gia_ManToAigSimple( pGia2 );
+ Gia_ManStop( pGia2 );
+//Aig_ManShow( pAig, 0, NULL );
+
+ if ( pPars->nHintDepth == 0 )
+ RetValue = Llb_ManModelCheckAig( pAig, pPars, NULL, NULL );
+ else
+ RetValue = Llb_ManModelCheckAigWithHints( pAig, pPars );
+ pGia->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL;
+ Aig_ManStop( pAig );
+ return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/bdd/llb/llb1Group.c b/src/bdd/llb/llb1Group.c
new file mode 100644
index 00000000..1099b2cd
--- /dev/null
+++ b/src/bdd/llb/llb1Group.c
@@ -0,0 +1,474 @@
+/**CFile****************************************************************
+
+ FileName [llb1Group.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Initial partition computation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb1Group.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Grp_t * Llb_ManGroupAlloc( Llb_Man_t * pMan )
+{
+ Llb_Grp_t * p;
+ p = ABC_CALLOC( Llb_Grp_t, 1 );
+ p->pMan = pMan;
+ p->vIns = Vec_PtrAlloc( 8 );
+ p->vOuts = Vec_PtrAlloc( 8 );
+ p->Id = Vec_PtrSize( pMan->vGroups );
+ Vec_PtrPush( pMan->vGroups, p );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManGroupStop( Llb_Grp_t * p )
+{
+ if ( p == NULL )
+ return;
+ Vec_PtrWriteEntry( p->pMan->vGroups, p->Id, NULL );
+ Vec_PtrFreeP( &p->vIns );
+ Vec_PtrFreeP( &p->vOuts );
+ Vec_PtrFreeP( &p->vNodes );
+ ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManGroupCollect_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+ if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+ return;
+ Aig_ObjSetTravIdCurrent(pAig, pObj);
+ if ( Aig_ObjIsConst1(pObj) )
+ return;
+ if ( Aig_ObjIsCo(pObj) )
+ {
+ Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin0(pObj), vNodes );
+ return;
+ }
+ assert( Aig_ObjIsAnd(pObj) );
+ Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin0(pObj), vNodes );
+ Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin1(pObj), vNodes );
+ Vec_PtrPush( vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the support of MFFC.]
+
+ Description [Returns the number of internal nodes in the MFFC.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManGroupCollect( Llb_Grp_t * pGroup )
+{
+ Vec_Ptr_t * vNodes;
+ Aig_Obj_t * pObj;
+ int i;
+ vNodes = Vec_PtrAlloc( 100 );
+ Aig_ManIncrementTravId( pGroup->pMan->pAig );
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i )
+ Aig_ObjSetTravIdCurrent( pGroup->pMan->pAig, pObj );
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i )
+ Aig_ObjSetTravIdPrevious( pGroup->pMan->pAig, pObj );
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i )
+ Llb_ManGroupCollect_rec( pGroup->pMan->pAig, pObj, vNodes );
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManGroupCreate_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vSupp )
+{
+ if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+ return;
+ Aig_ObjSetTravIdCurrent(pAig, pObj);
+ if ( Aig_ObjIsConst1(pObj) )
+ return;
+ if ( pObj->fMarkA )
+ {
+ Vec_PtrPush( vSupp, pObj );
+ return;
+ }
+ assert( Aig_ObjIsAnd(pObj) );
+ Llb_ManGroupCreate_rec( pAig, Aig_ObjFanin0(pObj), vSupp );
+ Llb_ManGroupCreate_rec( pAig, Aig_ObjFanin1(pObj), vSupp );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Grp_t * Llb_ManGroupCreate( Llb_Man_t * pMan, Aig_Obj_t * pObj )
+{
+ Llb_Grp_t * p;
+ assert( pObj->fMarkA == 1 );
+ // derive group
+ p = Llb_ManGroupAlloc( pMan );
+ Vec_PtrPush( p->vOuts, pObj );
+ Aig_ManIncrementTravId( pMan->pAig );
+ if ( Aig_ObjIsCo(pObj) )
+ Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin0(pObj), p->vIns );
+ else
+ {
+ Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin0(pObj), p->vIns );
+ Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin1(pObj), p->vIns );
+ }
+ // derive internal objects
+ assert( p->vNodes == NULL );
+ p->vNodes = Llb_ManGroupCollect( p );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Grp_t * Llb_ManGroupCreateFirst( Llb_Man_t * pMan )
+{
+ Llb_Grp_t * p;
+ Aig_Obj_t * pObj;
+ int i;
+ p = Llb_ManGroupAlloc( pMan );
+ Saig_ManForEachLo( pMan->pAig, pObj, i )
+ Vec_PtrPush( p->vOuts, pObj );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Grp_t * Llb_ManGroupCreateLast( Llb_Man_t * pMan )
+{
+ Llb_Grp_t * p;
+ Aig_Obj_t * pObj;
+ int i;
+ p = Llb_ManGroupAlloc( pMan );
+ Saig_ManForEachLi( pMan->pAig, pObj, i )
+ Vec_PtrPush( p->vIns, pObj );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Grp_t * Llb_ManGroupsCombine( Llb_Grp_t * p1, Llb_Grp_t * p2 )
+{
+ Llb_Grp_t * p;
+ Aig_Obj_t * pObj;
+ int i;
+ p = Llb_ManGroupAlloc( p1->pMan );
+ // create inputs
+ Vec_PtrForEachEntry( Aig_Obj_t *, p1->vIns, pObj, i )
+ Vec_PtrPush( p->vIns, pObj );
+ Vec_PtrForEachEntry( Aig_Obj_t *, p2->vIns, pObj, i )
+ Vec_PtrPushUnique( p->vIns, pObj );
+ // create outputs
+ Vec_PtrForEachEntry( Aig_Obj_t *, p1->vOuts, pObj, i )
+ Vec_PtrPush( p->vOuts, pObj );
+ Vec_PtrForEachEntry( Aig_Obj_t *, p2->vOuts, pObj, i )
+ Vec_PtrPushUnique( p->vOuts, pObj );
+
+ // derive internal objects
+ assert( p->vNodes == NULL );
+ p->vNodes = Llb_ManGroupCollect( p );
+ return p;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManGroupMarkNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ return;
+ if ( Aig_ObjIsTravIdPrevious(p, pObj) )
+ {
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ return;
+ }
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ assert( Aig_ObjIsNode(pObj) );
+ Llb_ManGroupMarkNodes_rec( p, Aig_ObjFanin0(pObj) );
+ Llb_ManGroupMarkNodes_rec( p, Aig_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates group from two cuts derived by the flow computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Grp_t * Llb_ManGroupCreateFromCuts( Llb_Man_t * pMan, Vec_Int_t * vCut1, Vec_Int_t * vCut2 )
+{
+ Llb_Grp_t * p;
+ Aig_Obj_t * pObj;
+ int i;
+ p = Llb_ManGroupAlloc( pMan );
+
+ // mark Cut1
+ Aig_ManIncrementTravId( pMan->pAig );
+ Aig_ManForEachObjVec( vCut1, pMan->pAig, pObj, i )
+ Aig_ObjSetTravIdCurrent( pMan->pAig, pObj );
+ // collect unmarked Cut2
+ Aig_ManForEachObjVec( vCut2, pMan->pAig, pObj, i )
+ if ( !Aig_ObjIsTravIdCurrent( pMan->pAig, pObj ) )
+ Vec_PtrPush( p->vOuts, pObj );
+
+ // mark nodes reachable from Cut2
+ Aig_ManIncrementTravId( pMan->pAig );
+ Aig_ManForEachObjVec( vCut2, pMan->pAig, pObj, i )
+ Llb_ManGroupMarkNodes_rec( pMan->pAig, pObj );
+ // collect marked Cut1
+ Aig_ManForEachObjVec( vCut1, pMan->pAig, pObj, i )
+ if ( Aig_ObjIsTravIdCurrent( pMan->pAig, pObj ) )
+ Vec_PtrPush( p->vIns, pObj );
+
+ // derive internal objects
+ assert( p->vNodes == NULL );
+ p->vNodes = Llb_ManGroupCollect( p );
+ return p;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManPrepareGroups( Llb_Man_t * pMan )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ assert( pMan->vGroups == NULL );
+ pMan->vGroups = Vec_PtrAlloc( 1000 );
+ Llb_ManGroupCreateFirst( pMan );
+ Aig_ManForEachNode( pMan->pAig, pObj, i )
+ {
+ if ( pObj->fMarkA )
+ Llb_ManGroupCreate( pMan, pObj );
+ }
+ Saig_ManForEachLi( pMan->pAig, pObj, i )
+ {
+ if ( pObj->fMarkA )
+ Llb_ManGroupCreate( pMan, pObj );
+ }
+ Llb_ManGroupCreateLast( pMan );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManPrintSpan( Llb_Man_t * p )
+{
+ Llb_Grp_t * pGroup;
+ Aig_Obj_t * pVar;
+ int i, k, Span = 0, SpanMax = 0;
+ Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGroup, i )
+ {
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k )
+ if ( Vec_IntEntry(p->vVarBegs, pVar->Id) == i )
+ Span++;
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k )
+ if ( Vec_IntEntry(p->vVarBegs, pVar->Id) == i )
+ Span++;
+
+ SpanMax = Abc_MaxInt( SpanMax, Span );
+printf( "%d ", Span );
+
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k )
+ if ( Vec_IntEntry(p->vVarEnds, pVar->Id) == i )
+ Span--;
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k )
+ if ( Vec_IntEntry(p->vVarEnds, pVar->Id) == i )
+ Span--;
+ }
+printf( "\n" );
+printf( "Max = %d\n", SpanMax );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManGroupHasVar( Llb_Man_t * p, int iGroup, int iVar )
+{
+ Llb_Grp_t * pGroup = (Llb_Grp_t *)Vec_PtrEntry( p->vGroups, iGroup );
+ Aig_Obj_t * pObj;
+ int i;
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i )
+ if ( pObj->Id == iVar )
+ return 1;
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i )
+ if ( pObj->Id == iVar )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManPrintHisto( Llb_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i, k;
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ {
+ if ( Vec_IntEntry(p->vObj2Var, i) < 0 )
+ continue;
+ printf( "%3d :", i );
+ for ( k = 0; k < Vec_IntEntry(p->vVarBegs, i); k++ )
+ printf( " " );
+ for ( ; k <= Vec_IntEntry(p->vVarEnds, i); k++ )
+ printf( "%c", Llb_ManGroupHasVar(p, k, i)? '*':'-' );
+ printf( "\n" );
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/bdd/llb/llb1Hint.c b/src/bdd/llb/llb1Hint.c
new file mode 100644
index 00000000..353b4c69
--- /dev/null
+++ b/src/bdd/llb/llb1Hint.c
@@ -0,0 +1,226 @@
+/**CFile****************************************************************
+
+ FileName [llb1Hint.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Cofactors the circuit w.r.t. the high-fanout variables.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb1Hint.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Returns CI index with the largest number of fanouts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManMaxFanoutCi( Aig_Man_t * pAig )
+{
+ Aig_Obj_t * pObj;
+ int i, WeightMax = -ABC_INFINITY, iInput = -1;
+ Aig_ManForEachCi( pAig, pObj, i )
+ if ( WeightMax < Aig_ObjRefs(pObj) )
+ {
+ WeightMax = Aig_ObjRefs(pObj);
+ iInput = i;
+ }
+ assert( iInput >= 0 );
+ return iInput;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives AIG whose PI is substituted by a constant.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Llb_ManPerformHints( Aig_Man_t * pAig, int nHintDepth )
+{
+ Aig_Man_t * pNew, * pTemp;
+ int i, iInput;
+ pNew = Aig_ManDupDfs( pAig );
+ for ( i = 0; i < nHintDepth; i++ )
+ {
+ iInput = Llb_ManMaxFanoutCi( pNew );
+ Abc_Print( 1, "%d %3d\n", i, iInput );
+ pNew = Aig_ManDupCof( pTemp = pNew, iInput, 1 );
+ Aig_ManStop( pTemp );
+ }
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns CI index with the largest number of fanouts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_ManCollectHighFanoutObjects( Aig_Man_t * pAig, int nCandMax, int fCisOnly )
+{
+ Vec_Int_t * vFanouts, * vResult;
+ Aig_Obj_t * pObj;
+ int i, fChanges, PivotValue;
+// int Entry;
+ // collect fanout counts
+ vFanouts = Vec_IntAlloc( 100 );
+ Aig_ManForEachObj( pAig, pObj, i )
+ {
+// if ( !Aig_ObjIsCi(pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) )
+ if ( !Saig_ObjIsLo(pAig,pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) )
+ continue;
+ Vec_IntPush( vFanouts, Aig_ObjRefs(pObj) );
+ }
+ Vec_IntSort( vFanouts, 1 );
+ // pick the separator
+ nCandMax = Abc_MinInt( nCandMax, Vec_IntSize(vFanouts) - 1 );
+ PivotValue = Vec_IntEntry( vFanouts, nCandMax );
+ Vec_IntFree( vFanouts );
+ // collect obj satisfying the constraints
+ vResult = Vec_IntAlloc( 100 );
+ Aig_ManForEachObj( pAig, pObj, i )
+ {
+// if ( !Aig_ObjIsCi(pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) )
+ if ( !Saig_ObjIsLo(pAig,pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) )
+ continue;
+ if ( Aig_ObjRefs(pObj) < PivotValue )
+ continue;
+ Vec_IntPush( vResult, Aig_ObjId(pObj) );
+ }
+ assert( Vec_IntSize(vResult) >= nCandMax );
+ // order in the decreasing order of fanouts
+ do
+ {
+ fChanges = 0;
+ for ( i = 0; i < Vec_IntSize(vResult) - 1; i++ )
+ if ( Aig_ObjRefs(Aig_ManObj(pAig, Vec_IntEntry(vResult, i))) <
+ Aig_ObjRefs(Aig_ManObj(pAig, Vec_IntEntry(vResult, i+1))) )
+ {
+ int Temp = Vec_IntEntry( vResult, i );
+ Vec_IntWriteEntry( vResult, i, Vec_IntEntry(vResult, i+1) );
+ Vec_IntWriteEntry( vResult, i+1, Temp );
+ fChanges = 1;
+ }
+ }
+ while ( fChanges );
+/*
+ Vec_IntForEachEntry( vResult, Entry, i )
+ printf( "%d ", Aig_ObjRefs(Aig_ManObj(pAig, Entry)) );
+printf( "\n" );
+*/
+ return vResult;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives AIG whose PI is substituted by a constant.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManModelCheckAigWithHints( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars )
+{
+ DdManager * ddGlo = NULL;
+ Vec_Int_t * vHints;
+ Vec_Int_t * vHFCands;
+ int i, Entry, RetValue = -1;
+ abctime clk = Abc_Clock();
+ assert( pPars->nHintDepth > 0 );
+/*
+ // perform reachability without hints
+ RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, NULL, NULL );
+ if ( RetValue >= 0 )
+ return RetValue;
+*/
+ // create hints representation
+ vHFCands = Llb_ManCollectHighFanoutObjects( pAigGlo, pPars->nHintDepth+pPars->HintFirst, 1 );
+ vHints = Vec_IntStartFull( Aig_ManObjNumMax(pAigGlo) );
+ // add one hint at a time till the problem is solved
+ Vec_IntForEachEntryStart( vHFCands, Entry, i, pPars->HintFirst )
+ {
+ Vec_IntWriteEntry( vHints, Entry, 1 ); // change to 1 to start from zero cof!!!
+ // solve under hints
+ RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, vHints, &ddGlo );
+ if ( RetValue == 0 )
+ goto Finish;
+ if ( RetValue == 1 )
+ break;
+ }
+ if ( RetValue == -1 )
+ goto Finish;
+ // undo the hints one at a time
+ for ( ; i >= pPars->HintFirst; i-- )
+ {
+ Entry = Vec_IntEntry( vHFCands, i );
+ Vec_IntWriteEntry( vHints, Entry, -1 );
+ // solve under relaxed hints
+ RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, vHints, &ddGlo );
+ if ( RetValue == 0 )
+ goto Finish;
+ if ( RetValue == 1 )
+ continue;
+ break;
+ }
+Finish:
+ if ( ddGlo )
+ {
+ if ( ddGlo->bFunc )
+ Cudd_RecursiveDeref( ddGlo, ddGlo->bFunc );
+ Extra_StopManager( ddGlo );
+ }
+ Vec_IntFreeP( &vHFCands );
+ Vec_IntFreeP( &vHints );
+ if ( pPars->fVerbose )
+ Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clk );
+ return RetValue;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/bdd/llb/llb1Man.c b/src/bdd/llb/llb1Man.c
new file mode 100644
index 00000000..f5de25e0
--- /dev/null
+++ b/src/bdd/llb/llb1Man.c
@@ -0,0 +1,218 @@
+/**CFile****************************************************************
+
+ FileName [llb1Man.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Reachability manager.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb1Man.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManPrepareVarMap( Llb_Man_t * p )
+{
+ Aig_Obj_t * pObjLi, * pObjLo;
+ int i, iVarLi, iVarLo;
+ assert( p->vNs2Glo == NULL );
+ assert( p->vCs2Glo == NULL );
+ assert( p->vGlo2Cs == NULL );
+ assert( p->vGlo2Ns == NULL );
+ p->vNs2Glo = Vec_IntStartFull( Vec_IntSize(p->vVar2Obj) );
+ p->vCs2Glo = Vec_IntStartFull( Vec_IntSize(p->vVar2Obj) );
+ p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) );
+ p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) );
+ Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+ {
+ iVarLi = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLi));
+ iVarLo = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLo));
+ assert( iVarLi >= 0 && iVarLi < Vec_IntSize(p->vVar2Obj) );
+ assert( iVarLo >= 0 && iVarLo < Vec_IntSize(p->vVar2Obj) );
+ Vec_IntWriteEntry( p->vNs2Glo, iVarLi, i );
+ Vec_IntWriteEntry( p->vCs2Glo, iVarLo, i );
+ Vec_IntWriteEntry( p->vGlo2Cs, i, iVarLo );
+ Vec_IntWriteEntry( p->vGlo2Ns, i, iVarLi );
+ }
+ // add mapping of the PIs
+ Saig_ManForEachPi( p->pAig, pObjLo, i )
+ {
+ iVarLo = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLo));
+ Vec_IntWriteEntry( p->vCs2Glo, iVarLo, Aig_ManRegNum(p->pAig)+i );
+ Vec_IntWriteEntry( p->vNs2Glo, iVarLo, Aig_ManRegNum(p->pAig)+i );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManPrepareVarLimits( Llb_Man_t * p )
+{
+ Llb_Grp_t * pGroup;
+ Aig_Obj_t * pVar;
+ int i, k;
+ assert( p->vVarBegs == NULL );
+ assert( p->vVarEnds == NULL );
+ p->vVarEnds = Vec_IntStart( Aig_ManObjNumMax(p->pAig) );
+ p->vVarBegs = Vec_IntStart( Aig_ManObjNumMax(p->pAig) );
+ Vec_IntFill( p->vVarBegs, Aig_ManObjNumMax(p->pAig), p->pMatrix->nCols );
+
+ for ( i = 0; i < p->pMatrix->nCols; i++ )
+ {
+ pGroup = p->pMatrix->pColGrps[i];
+
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k )
+ if ( Vec_IntEntry(p->vVarBegs, pVar->Id) > i )
+ Vec_IntWriteEntry( p->vVarBegs, pVar->Id, i );
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k )
+ if ( Vec_IntEntry(p->vVarBegs, pVar->Id) > i )
+ Vec_IntWriteEntry( p->vVarBegs, pVar->Id, i );
+
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k )
+ if ( Vec_IntEntry(p->vVarEnds, pVar->Id) < i )
+ Vec_IntWriteEntry( p->vVarEnds, pVar->Id, i );
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k )
+ if ( Vec_IntEntry(p->vVarEnds, pVar->Id) < i )
+ Vec_IntWriteEntry( p->vVarEnds, pVar->Id, i );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManStop( Llb_Man_t * p )
+{
+ Llb_Grp_t * pGrp;
+ DdNode * bTemp;
+ int i;
+
+// Vec_IntFreeP( &p->vMem );
+// Vec_PtrFreeP( &p->vTops );
+// Vec_PtrFreeP( &p->vBots );
+// Vec_VecFreeP( (Vec_Vec_t **)&p->vCuts );
+
+ if ( p->pMatrix )
+ Llb_MtrFree( p->pMatrix );
+ Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGrp, i )
+ Llb_ManGroupStop( pGrp );
+ if ( p->dd )
+ {
+// printf( "Manager dd\n" );
+ Extra_StopManager( p->dd );
+ }
+ if ( p->ddG )
+ {
+// printf( "Manager ddG\n" );
+ if ( p->ddG->bFunc )
+ Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc );
+ Extra_StopManager( p->ddG );
+ }
+ if ( p->ddR )
+ {
+// printf( "Manager ddR\n" );
+ if ( p->ddR->bFunc )
+ Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc );
+ Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i )
+ Cudd_RecursiveDeref( p->ddR, bTemp );
+ Extra_StopManager( p->ddR );
+ }
+ Aig_ManStop( p->pAig );
+ Vec_PtrFreeP( &p->vGroups );
+ Vec_IntFreeP( &p->vVar2Obj );
+ Vec_IntFreeP( &p->vObj2Var );
+ Vec_IntFreeP( &p->vVarBegs );
+ Vec_IntFreeP( &p->vVarEnds );
+ Vec_PtrFreeP( &p->vRings );
+ Vec_IntFreeP( &p->vNs2Glo );
+ Vec_IntFreeP( &p->vCs2Glo );
+ Vec_IntFreeP( &p->vGlo2Cs );
+ Vec_IntFreeP( &p->vGlo2Ns );
+// Vec_IntFreeP( &p->vHints );
+ ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Man_t * Llb_ManStart( Aig_Man_t * pAigGlo, Aig_Man_t * pAig, Gia_ParLlb_t * pPars )
+{
+ Llb_Man_t * p;
+ Aig_ManCleanMarkA( pAig );
+ p = ABC_CALLOC( Llb_Man_t, 1 );
+ p->pAigGlo = pAigGlo;
+ p->pPars = pPars;
+ p->pAig = pAig;
+ p->vVar2Obj = Llb_ManMarkPivotNodes( p->pAig, pPars->fUsePivots );
+ p->vObj2Var = Vec_IntInvert( p->vVar2Obj, -1 );
+ p->vRings = Vec_PtrAlloc( 100 );
+ Llb_ManPrepareVarMap( p );
+ Llb_ManPrepareGroups( p );
+ Aig_ManCleanMarkA( pAig );
+ p->pMatrix = Llb_MtrCreate( p );
+ p->pMatrix->pMan = p;
+ return p;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/bdd/llb/llb1Matrix.c b/src/bdd/llb/llb1Matrix.c
new file mode 100644
index 00000000..7aa9c744
--- /dev/null
+++ b/src/bdd/llb/llb1Matrix.c
@@ -0,0 +1,430 @@
+/**CFile****************************************************************
+
+ FileName [llb1Matrix.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Partition clustering as a matrix problem.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb1Matrix.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// 0123 nCols
+// +--------------------->
+// pi 0 | 111 row0 pRowSums[0]
+// pi 1 | 1 11 row1 pRowSums[1]
+// pi 2 | 1 11 row2 pRowSums[2]
+// CS |1 1
+// CS |1 111
+// CS |111 111
+// int | 11111
+// int | 111
+// int | 111
+// int | 111
+// NS | 11 11
+// NS | 11 1
+// NS | 111
+// nRows |
+// v
+// cccc pColSums[0]
+// oooo pColSums[1]
+// llll pColSums[2]
+// 0123 pColSums[3]
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Verify columns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MtrVerifyRowsAll( Llb_Mtr_t * p )
+{
+ int iRow, iCol, Counter;
+ for ( iCol = 0; iCol < p->nCols; iCol++ )
+ {
+ Counter = 0;
+ for ( iRow = 0; iRow < p->nRows; iRow++ )
+ if ( p->pMatrix[iCol][iRow] == 1 )
+ Counter++;
+ assert( Counter == p->pColSums[iCol] );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verify columns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MtrVerifyColumnsAll( Llb_Mtr_t * p )
+{
+ int iRow, iCol, Counter;
+ for ( iRow = 0; iRow < p->nRows; iRow++ )
+ {
+ Counter = 0;
+ for ( iCol = 0; iCol < p->nCols; iCol++ )
+ if ( p->pMatrix[iCol][iRow] == 1 )
+ Counter++;
+ assert( Counter == p->pRowSums[iRow] );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verify columns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MtrVerifyMatrix( Llb_Mtr_t * p )
+{
+ Llb_MtrVerifyRowsAll( p );
+ Llb_MtrVerifyColumnsAll( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sort variables in the order of removal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int * Llb_MtrFindVarOrder( Llb_Mtr_t * p )
+{
+ int * pOrder, * pLast;
+ int i, k, fChanges, Temp;
+ pOrder = ABC_CALLOC( int, p->nRows );
+ pLast = ABC_CALLOC( int, p->nRows );
+ for ( i = 0; i < p->nRows; i++ )
+ {
+ pOrder[i] = i;
+ for ( k = p->nCols - 1; k >= 0; k-- )
+ if ( p->pMatrix[k][i] )
+ {
+ pLast[i] = k;
+ break;
+ }
+ }
+ do
+ {
+ fChanges = 0;
+ for ( i = 0; i < p->nRows - 1; i++ )
+ if ( pLast[i] > pLast[i+1] )
+ {
+ Temp = pOrder[i];
+ pOrder[i] = pOrder[i+1];
+ pOrder[i+1] = Temp;
+
+ Temp = pLast[i];
+ pLast[i] = pLast[i+1];
+ pLast[i+1] = Temp;
+
+ fChanges = 1;
+ }
+ }
+ while ( fChanges );
+ ABC_FREE( pLast );
+ return pOrder;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns type of a variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Llb_MtrVarName( Llb_Mtr_t * p, int iVar )
+{
+ static char Buffer[10];
+ if ( iVar < p->nPis )
+ strcpy( Buffer, "pi" );
+ else if ( iVar < p->nPis + p->nFfs )
+ strcpy( Buffer, "CS" );
+ else if ( iVar >= p->nRows - p->nFfs )
+ strcpy( Buffer, "NS" );
+ else
+ strcpy( Buffer, "int" );
+ return Buffer;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates one column with vars in the array.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MtrPrint( Llb_Mtr_t * p, int fOrder )
+{
+ int * pOrder = NULL;
+ int i, iRow, iCol;
+ if ( fOrder )
+ pOrder = Llb_MtrFindVarOrder( p );
+ for ( i = 0; i < p->nRows; i++ )
+ {
+ iRow = pOrder ? pOrder[i] : i;
+ printf( "%3d : ", iRow );
+ printf( "%3d ", p->pRowSums[iRow] );
+ printf( "%3s ", Llb_MtrVarName(p, iRow) );
+ for ( iCol = 0; iCol < p->nCols; iCol++ )
+ printf( "%c", p->pMatrix[iCol][iRow] ? '*' : ' ' );
+ printf( "\n" );
+ }
+ ABC_FREE( pOrder );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verify columns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MtrPrintMatrixStats( Llb_Mtr_t * p )
+{
+ int iVar, iGrp, iGrp1, iGrp2, Span = 0, nCutSize = 0, nCutSizeMax = 0;
+ int * pGrp1 = ABC_CALLOC( int, p->nRows );
+ int * pGrp2 = ABC_CALLOC( int, p->nRows );
+ for ( iVar = 0; iVar < p->nRows; iVar++ )
+ {
+ if ( p->pRowSums[iVar] == 0 )
+ continue;
+ for ( iGrp1 = 0; iGrp1 < p->nCols; iGrp1++ )
+ if ( p->pMatrix[iGrp1][iVar] == 1 )
+ break;
+ for ( iGrp2 = p->nCols - 1; iGrp2 >= 0; iGrp2-- )
+ if ( p->pMatrix[iGrp2][iVar] == 1 )
+ break;
+ assert( iGrp1 <= iGrp2 );
+ pGrp1[iVar] = iGrp1;
+ pGrp2[iVar] = iGrp2;
+ Span += iGrp2 - iGrp1;
+ }
+ // compute span
+ for ( iGrp = 0; iGrp < p->nCols; iGrp++ )
+ {
+ for ( iVar = 0; iVar < p->nRows; iVar++ )
+ if ( pGrp1[iVar] == iGrp )
+ nCutSize++;
+ if ( nCutSizeMax < nCutSize )
+ nCutSizeMax = nCutSize;
+ for ( iVar = 0; iVar < p->nRows; iVar++ )
+ if ( pGrp2[iVar] == iGrp )
+ nCutSize--;
+ }
+ ABC_FREE( pGrp1 );
+ ABC_FREE( pGrp2 );
+ printf( "[%4d x %4d] Life-span =%6.2f Max-cut =%5d\n",
+ p->nCols, p->nRows, 1.0*Span/p->nRows, nCutSizeMax );
+ if ( nCutSize )
+ Abc_Print( -1, "Cut size is not zero (%d).\n", nCutSize );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Starts the matrix representation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Mtr_t * Llb_MtrAlloc( int nPis, int nFfs, int nCols, int nRows )
+{
+ Llb_Mtr_t * p;
+ int i;
+ p = ABC_CALLOC( Llb_Mtr_t, 1 );
+ p->nPis = nPis;
+ p->nFfs = nFfs;
+ p->nRows = nRows;
+ p->nCols = nCols;
+ p->pRowSums = ABC_CALLOC( int, nRows );
+ p->pColSums = ABC_CALLOC( int, nCols );
+ p->pColGrps = ABC_CALLOC( Llb_Grp_t *, nCols );
+ p->pMatrix = ABC_CALLOC( char *, nCols );
+ for ( i = 0; i < nCols; i++ )
+ p->pMatrix[i] = ABC_CALLOC( char, nRows );
+ // partial product
+ p->pProdVars = ABC_CALLOC( char, nRows ); // variables in the partial product
+ p->pProdNums = ABC_CALLOC( int, nRows ); // var counts in the remaining partitions
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the matrix representation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MtrFree( Llb_Mtr_t * p )
+{
+ int i;
+ ABC_FREE( p->pProdVars );
+ ABC_FREE( p->pProdNums );
+ for ( i = 0; i < p->nCols; i++ )
+ ABC_FREE( p->pMatrix[i] );
+ ABC_FREE( p->pRowSums );
+ ABC_FREE( p->pColSums );
+ ABC_FREE( p->pMatrix );
+ ABC_FREE( p->pColGrps );
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates one column with vars in the array.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MtrAddColumn( Llb_Mtr_t * p, Llb_Grp_t * pGrp )
+{
+ Aig_Obj_t * pVar;
+ int i, iRow, iCol = pGrp->Id;
+ assert( iCol >= 0 && iCol < p->nCols );
+ p->pColGrps[iCol] = pGrp;
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGrp->vIns, pVar, i )
+ {
+ iRow = Vec_IntEntry( pGrp->pMan->vObj2Var, Aig_ObjId(pVar) );
+ assert( iRow >= 0 && iRow < p->nRows );
+ p->pMatrix[iCol][iRow] = 1;
+ p->pColSums[iCol]++;
+ p->pRowSums[iRow]++;
+ }
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGrp->vOuts, pVar, i )
+ {
+ iRow = Vec_IntEntry( pGrp->pMan->vObj2Var, Aig_ObjId(pVar) );
+ assert( iRow >= 0 && iRow < p->nRows );
+ p->pMatrix[iCol][iRow] = 1;
+ p->pColSums[iCol]++;
+ p->pRowSums[iRow]++;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Matrix reduce.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MtrRemoveSingletonRows( Llb_Mtr_t * p )
+{
+ int i, k;
+ for ( i = 0; i < p->nRows; i++ )
+ if ( p->pRowSums[i] < 2 )
+ {
+ p->pRowSums[i] = 0;
+ for ( k = 0; k < p->nCols; k++ )
+ {
+ if ( p->pMatrix[k][i] == 1 )
+ {
+ p->pMatrix[k][i] = 0;
+ p->pColSums[k]--;
+ }
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Matrix reduce.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Mtr_t * Llb_MtrCreate( Llb_Man_t * p )
+{
+ Llb_Mtr_t * pMatrix;
+ Llb_Grp_t * pGroup;
+ int i;
+ pMatrix = Llb_MtrAlloc( Saig_ManPiNum(p->pAig), Saig_ManRegNum(p->pAig),
+ Vec_PtrSize(p->vGroups), Vec_IntSize(p->vVar2Obj) );
+ Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGroup, i )
+ Llb_MtrAddColumn( pMatrix, pGroup );
+// Llb_MtrRemoveSingletonRows( pMatrix );
+ return pMatrix;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/bdd/llb/llb1Pivot.c b/src/bdd/llb/llb1Pivot.c
new file mode 100644
index 00000000..7a5bb66f
--- /dev/null
+++ b/src/bdd/llb/llb1Pivot.c
@@ -0,0 +1,254 @@
+/**CFile****************************************************************
+
+ FileName [llb1Pivot.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Determining pivot variables.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb1Pivot.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManTracePaths_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pPivot )
+{
+ Aig_Obj_t * pFanout;
+ int k, iFan = -1;
+ if ( Aig_ObjIsTravIdPrevious(p, pObj) )
+ return 0;
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ return 1;
+ if ( Saig_ObjIsLi(p, pObj) )
+ return 0;
+ if ( Saig_ObjIsPo(p, pObj) )
+ return 0;
+ if ( pObj == pPivot )
+ return 1;
+ assert( Aig_ObjIsCand(pObj) );
+ Aig_ObjForEachFanout( p, pObj, pFanout, iFan, k )
+ if ( !Llb_ManTracePaths_rec( p, pFanout, pPivot ) )
+ {
+ Aig_ObjSetTravIdPrevious(p, pObj);
+ return 0;
+ }
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManTracePaths( Aig_Man_t * p, Aig_Obj_t * pPivot )
+{
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ Aig_ManIncrementTravId( p ); // prev = visited with path to LI (value 0)
+ Aig_ManIncrementTravId( p ); // cur = visited w/o path to LI (value 1)
+ Saig_ManForEachLo( p, pObj, i )
+ Counter += Llb_ManTracePaths_rec( p, pObj, pPivot );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManTestCuts( Aig_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i, Count;
+ Aig_ManFanoutStart( p );
+ Aig_ManForEachNode( p, pObj, i )
+ {
+ if ( Aig_ObjRefs(pObj) <= 1 )
+ continue;
+ Count = Llb_ManTracePaths( p, pObj );
+ printf( "Obj =%5d. Lev =%3d. Fanout =%5d. Count = %3d.\n",
+ i, Aig_ObjLevel(pObj), Aig_ObjRefs(pObj), Count );
+ }
+ Aig_ManFanoutStop( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManLabelLiCones_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+ if ( pObj->fMarkB )
+ return;
+ pObj->fMarkB = 1;
+ assert( Aig_ObjIsNode(pObj) );
+ Llb_ManLabelLiCones_rec( p, Aig_ObjFanin0(pObj) );
+ Llb_ManLabelLiCones_rec( p, Aig_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Determine starting cut-points.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManLabelLiCones( Aig_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ // mark const and PIs
+ Aig_ManConst1(p)->fMarkB = 1;
+ Aig_ManForEachCi( p, pObj, i )
+ pObj->fMarkB = 1;
+ // mark cones
+ Saig_ManForEachLi( p, pObj, i )
+ Llb_ManLabelLiCones_rec( p, Aig_ObjFanin0(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Determine starting cut-points.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManMarkInternalPivots( Aig_Man_t * p )
+{
+ Vec_Ptr_t * vMuxes;
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+
+ // remove refs due to MUXes
+ vMuxes = Aig_ManMuxesCollect( p );
+ Aig_ManMuxesDeref( p, vMuxes );
+
+ // mark nodes feeding into LIs
+ Aig_ManCleanMarkB( p );
+ Llb_ManLabelLiCones( p );
+
+ // mark internal nodes
+ Aig_ManFanoutStart( p );
+ Aig_ManForEachNode( p, pObj, i )
+ if ( pObj->fMarkB && pObj->nRefs > 1 )
+ {
+ if ( Llb_ManTracePaths(p, pObj) > 0 )
+ pObj->fMarkA = 1;
+ Counter++;
+ }
+ Aig_ManFanoutStop( p );
+// printf( "TracePath tried = %d.\n", Counter );
+
+ // mark nodes feeding into LIs
+ Aig_ManCleanMarkB( p );
+
+ // add refs due to MUXes
+ Aig_ManMuxesRef( p, vMuxes );
+ Vec_PtrFree( vMuxes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Determine starting cut-points.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_ManMarkPivotNodes( Aig_Man_t * p, int fUseInternal )
+{
+ Vec_Int_t * vVar2Obj;
+ Aig_Obj_t * pObj;
+ int i;
+ // mark inputs/outputs
+ Aig_ManForEachCi( p, pObj, i )
+ pObj->fMarkA = 1;
+ Saig_ManForEachLi( p, pObj, i )
+ pObj->fMarkA = 1;
+
+ // mark internal pivot nodes
+ if ( fUseInternal )
+ Llb_ManMarkInternalPivots( p );
+
+ // assign variable numbers
+ Aig_ManConst1(p)->fMarkA = 0;
+ vVar2Obj = Vec_IntAlloc( 100 );
+ Aig_ManForEachCi( p, pObj, i )
+ Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) );
+ Aig_ManForEachNode( p, pObj, i )
+ if ( pObj->fMarkA )
+ Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) );
+ Saig_ManForEachLi( p, pObj, i )
+ Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) );
+ return vVar2Obj;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/bdd/llb/llb1Reach.c b/src/bdd/llb/llb1Reach.c
new file mode 100644
index 00000000..fae7bee2
--- /dev/null
+++ b/src/bdd/llb/llb1Reach.c
@@ -0,0 +1,904 @@
+/**CFile****************************************************************
+
+ FileName [llb1Reach.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Reachability analysis.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb1Reach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Derives global BDD for the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_ManConstructOutBdd( Aig_Man_t * pAig, Aig_Obj_t * pNode, DdManager * dd )
+{
+ DdNode * bBdd0, * bBdd1, * bFunc;
+ Vec_Ptr_t * vNodes;
+ Aig_Obj_t * pObj = NULL;
+ int i;
+ abctime TimeStop;
+ if ( Aig_ObjFanin0(pNode) == Aig_ManConst1(pAig) )
+ return Cudd_NotCond( Cudd_ReadOne(dd), Aig_ObjFaninC0(pNode) );
+ TimeStop = dd->TimeStop; dd->TimeStop = 0;
+ vNodes = Aig_ManDfsNodes( pAig, &pNode, 1 );
+ assert( Vec_PtrSize(vNodes) > 0 );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+ {
+ if ( !Aig_ObjIsNode(pObj) )
+ continue;
+ bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bBdd1 = Cudd_NotCond( Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+ pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData );
+ }
+ bFunc = (DdNode *)pObj->pData; Cudd_Ref( bFunc );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+ {
+ if ( !Aig_ObjIsNode(pObj) )
+ continue;
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+ }
+ Vec_PtrFree( vNodes );
+ if ( Aig_ObjIsCo(pNode) )
+ bFunc = Cudd_NotCond( bFunc, Aig_ObjFaninC0(pNode) );
+ Cudd_Deref( bFunc );
+ dd->TimeStop = TimeStop;
+ return bFunc;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives BDD for the group.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_ManConstructGroupBdd( Llb_Man_t * p, Llb_Grp_t * pGroup )
+{
+ Aig_Obj_t * pObj;
+ DdNode * bBdd0, * bBdd1, * bRes, * bXor, * bTemp;
+ int i, k;
+ Aig_ManConst1(p->pAig)->pData = Cudd_ReadOne( p->dd );
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i )
+ pObj->pData = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vNodes, pObj, i )
+ {
+ bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bBdd1 = Cudd_NotCond( Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+// pObj->pData = Extra_bddAndTime( p->dd, bBdd0, bBdd1, p->pPars->TimeTarget );
+ pObj->pData = Cudd_bddAnd( p->dd, bBdd0, bBdd1 );
+ if ( pObj->pData == NULL )
+ {
+ Vec_PtrForEachEntryStop( Aig_Obj_t *, pGroup->vNodes, pObj, k, i )
+ if ( pObj->pData )
+ Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData );
+ return NULL;
+ }
+ Cudd_Ref( (DdNode *)pObj->pData );
+ }
+ bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes );
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i )
+ {
+ if ( Aig_ObjIsCo(pObj) )
+ bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ else
+ bBdd0 = (DdNode *)pObj->pData;
+ bBdd1 = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
+ bXor = Cudd_bddXor( p->dd, bBdd0, bBdd1 ); Cudd_Ref( bXor );
+// bRes = Extra_bddAndTime( p->dd, bTemp = bRes, Cudd_Not(bXor), p->pPars->TimeTarget );
+ bRes = Cudd_bddAnd( p->dd, bTemp = bRes, Cudd_Not(bXor) );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->dd, bXor );
+ Vec_PtrForEachEntryStop( Aig_Obj_t *, pGroup->vNodes, pObj, k, i )
+ if ( pObj->pData )
+ Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData );
+ return NULL;
+ }
+ Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->dd, bXor );
+ }
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vNodes, pObj, i )
+ Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData );
+ Cudd_Deref( bRes );
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives quantification cube.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_ManConstructQuantCubeIntern( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace, int fBackward )
+{
+ Aig_Obj_t * pObj;
+ DdNode * bRes, * bTemp, * bVar;
+ int i, iGroupFirst, iGroupLast;
+ abctime TimeStop;
+ TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
+ bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes );
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i )
+ {
+ if ( fBackward && Saig_ObjIsPi(p->pAig, pObj) )
+ continue;
+ iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj));
+ iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj));
+ assert( iGroupFirst <= iGroupLast );
+ if ( iGroupFirst < iGroupLast )
+ continue;
+ bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
+ bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i )
+ {
+ if ( fBackward && Saig_ObjIsPi(p->pAig, pObj) )
+ continue;
+ iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj));
+ iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj));
+ assert( iGroupFirst <= iGroupLast );
+ if ( iGroupFirst < iGroupLast )
+ continue;
+ bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
+ bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ Cudd_Deref( bRes );
+ p->dd->TimeStop = TimeStop;
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives quantification cube.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_ManConstructQuantCubeFwd( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace )
+{
+ Aig_Obj_t * pObj;
+ DdNode * bRes, * bTemp, * bVar;
+ int i, iGroupLast;
+ abctime TimeStop;
+ TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
+ bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes );
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i )
+ {
+ iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj));
+ assert( iGroupLast >= iGrpPlace );
+ if ( iGroupLast > iGrpPlace )
+ continue;
+ bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
+ bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i )
+ {
+ iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj));
+ assert( iGroupLast >= iGrpPlace );
+ if ( iGroupLast > iGrpPlace )
+ continue;
+ bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
+ bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ Cudd_Deref( bRes );
+ p->dd->TimeStop = TimeStop;
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives quantification cube.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_ManConstructQuantCubeBwd( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace )
+{
+ Aig_Obj_t * pObj;
+ DdNode * bRes, * bTemp, * bVar;
+ int i, iGroupFirst;
+ abctime TimeStop;
+ TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
+ bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes );
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i )
+ {
+ if ( Saig_ObjIsPi(p->pAig, pObj) )
+ continue;
+ iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj));
+ assert( iGroupFirst <= iGrpPlace );
+ if ( iGroupFirst < iGrpPlace )
+ continue;
+ bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
+ bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i )
+ {
+ if ( Saig_ObjIsPi(p->pAig, pObj) )
+ continue;
+ iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj));
+ assert( iGroupFirst <= iGrpPlace );
+ if ( iGroupFirst < iGrpPlace )
+ continue;
+ bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
+ bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ Cudd_Deref( bRes );
+ p->dd->TimeStop = TimeStop;
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_ManComputeInitState( Llb_Man_t * p, DdManager * dd )
+{
+ Aig_Obj_t * pObj;
+ DdNode * bRes, * bVar, * bTemp;
+ int i, iVar;
+ abctime TimeStop;
+ TimeStop = dd->TimeStop; dd->TimeStop = 0;
+ bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes );
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ {
+ iVar = (dd == p->ddG) ? i : Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj));
+ bVar = Cudd_bddIthVar( dd, iVar );
+ bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bRes );
+ dd->TimeStop = TimeStop;
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_ManComputeImage( Llb_Man_t * p, DdNode * bInit, int fBackward )
+{
+ int fCheckSupport = 0;
+ Llb_Grp_t * pGroup;
+ DdNode * bImage, * bGroup, * bCube, * bTemp;
+ int k, Index;
+ bImage = bInit; Cudd_Ref( bImage );
+ for ( k = 1; k < p->pMatrix->nCols-1; k++ )
+ {
+ if ( fBackward )
+ Index = p->pMatrix->nCols - 1 - k;
+ else
+ Index = k;
+
+ // compute group BDD
+ pGroup = p->pMatrix->pColGrps[Index];
+ bGroup = Llb_ManConstructGroupBdd( p, pGroup );
+ if ( bGroup == NULL )
+ {
+ Cudd_RecursiveDeref( p->dd, bImage );
+ return NULL;
+ }
+ Cudd_Ref( bGroup );
+ // quantify variables appearing only in this group
+ bCube = Llb_ManConstructQuantCubeIntern( p, pGroup, Index, fBackward ); Cudd_Ref( bCube );
+ bGroup = Cudd_bddExistAbstract( p->dd, bTemp = bGroup, bCube );
+ if ( bGroup == NULL )
+ {
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->dd, bCube );
+ return NULL;
+ }
+ Cudd_Ref( bGroup );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->dd, bCube );
+ // perform partial product
+ if ( fBackward )
+ bCube = Llb_ManConstructQuantCubeBwd( p, pGroup, Index );
+ else
+ bCube = Llb_ManConstructQuantCubeFwd( p, pGroup, Index );
+ Cudd_Ref( bCube );
+// bImage = Extra_bddAndAbstractTime( p->dd, bTemp = bImage, bGroup, bCube, p->pPars->TimeTarget );
+ bImage = Cudd_bddAndAbstract( p->dd, bTemp = bImage, bGroup, bCube );
+ if ( bImage == NULL )
+ {
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->dd, bGroup );
+ Cudd_RecursiveDeref( p->dd, bCube );
+ return NULL;
+ }
+ Cudd_Ref( bImage );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->dd, bGroup );
+ Cudd_RecursiveDeref( p->dd, bCube );
+ }
+
+ // make sure image depends on next state vars
+ if ( fCheckSupport )
+ {
+ bCube = Cudd_Support( p->dd, bImage ); Cudd_Ref( bCube );
+ for ( bTemp = bCube; bTemp != p->dd->one; bTemp = cuddT(bTemp) )
+ {
+ int ObjId = Vec_IntEntry( p->vVar2Obj, bTemp->index );
+ Aig_Obj_t * pObj = Aig_ManObj( p->pAig, ObjId );
+ if ( !Saig_ObjIsLi(p->pAig, pObj) )
+ printf( "Var %d assigned to obj %d that is not LI\n", bTemp->index, ObjId );
+ }
+ Cudd_RecursiveDeref( p->dd, bCube );
+ }
+ Cudd_Deref( bImage );
+ return bImage;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_ManCreateConstraints( Llb_Man_t * p, Vec_Int_t * vHints, int fUseNsVars )
+{
+ DdNode * bConstr, * bFunc, * bTemp;
+ Aig_Obj_t * pObj;
+ int i, Entry;
+ abctime TimeStop;
+ if ( vHints == NULL )
+ return Cudd_ReadOne( p->dd );
+ TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
+ assert( Aig_ManCiNum(p->pAig) == Aig_ManCiNum(p->pAigGlo) );
+ // assign const and PI nodes to the original AIG
+ Aig_ManCleanData( p->pAig );
+ Aig_ManConst1( p->pAig )->pData = Cudd_ReadOne( p->dd );
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ pObj->pData = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var,Aig_ObjId(pObj)) );
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ {
+ if ( fUseNsVars )
+ Entry = Vec_IntEntry( p->vObj2Var, Aig_ObjId(Saig_ObjLoToLi(p->pAig, pObj)) );
+ else
+ Entry = Vec_IntEntry( p->vObj2Var, Aig_ObjId(pObj) );
+ pObj->pData = Cudd_bddIthVar( p->dd, Entry );
+ }
+ // transfer them to the global AIG
+ Aig_ManCleanData( p->pAigGlo );
+ Aig_ManConst1( p->pAigGlo )->pData = Cudd_ReadOne( p->dd );
+ Aig_ManForEachCi( p->pAigGlo, pObj, i )
+ pObj->pData = Aig_ManCi(p->pAig, i)->pData;
+ // derive consraints
+ bConstr = Cudd_ReadOne( p->dd ); Cudd_Ref( bConstr );
+ Vec_IntForEachEntry( vHints, Entry, i )
+ {
+ if ( Entry != 0 && Entry != 1 )
+ continue;
+ bFunc = Llb_ManConstructOutBdd( p->pAigGlo, Aig_ManObj(p->pAigGlo, i), p->dd ); Cudd_Ref( bFunc );
+ bFunc = Cudd_NotCond( bFunc, Entry ); // restrict to not constraint
+ // make the product
+ bConstr = Cudd_bddAnd( p->dd, bTemp = bConstr, bFunc ); Cudd_Ref( bConstr );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->dd, bFunc );
+ }
+ Cudd_Deref( bConstr );
+ p->dd->TimeStop = TimeStop;
+ return bConstr;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Perform reachability with hints and returns reached states in ppGlo.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Cex_t * Llb_ManReachDeriveCex( Llb_Man_t * p )
+{
+ Abc_Cex_t * pCex;
+ Aig_Obj_t * pObj;
+ DdNode * bState = NULL, * bImage, * bOneCube, * bTemp, * bRing;
+ int i, v, RetValue, nPiOffset;
+ char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) );
+ assert( Vec_PtrSize(p->vRings) > 0 );
+
+ p->dd->TimeStop = 0;
+ p->ddR->TimeStop = 0;
+
+/*
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ printf( "%d ", pObj->Id );
+ printf( "\n" );
+ Saig_ManForEachLi( p->pAig, pObj, i )
+ printf( "%d(%d) ", pObj->Id, Aig_ObjFaninId0(pObj) );
+ printf( "\n" );
+*/
+ // allocate room for the counter-example
+ pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) );
+ pCex->iFrame = Vec_PtrSize(p->vRings) - 1;
+ pCex->iPo = -1;
+
+ // get the last cube
+ bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc ); Cudd_Ref( bOneCube );
+ RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues );
+ Cudd_RecursiveDeref( p->ddR, bOneCube );
+ assert( RetValue );
+
+ // write PIs of counter-example
+ nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1);
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 )
+ Abc_InfoSetBit( pCex->pData, nPiOffset + i );
+
+ // write state in terms of NS variables
+ if ( Vec_PtrSize(p->vRings) > 1 )
+ {
+ bState = Llb_CoreComputeCube( p->dd, p->vGlo2Ns, 1, pValues ); Cudd_Ref( bState );
+ }
+ // perform backward analysis
+ Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v )
+ {
+ if ( v == Vec_PtrSize(p->vRings) - 1 )
+ continue;
+//Extra_bddPrintSupport( p->dd, bState ); printf( "\n" );
+//Extra_bddPrintSupport( p->dd, bRing ); printf( "\n" );
+ // compute the next states
+ bImage = Llb_ManComputeImage( p, bState, 1 );
+ assert( bImage != NULL );
+ Cudd_Ref( bImage );
+ Cudd_RecursiveDeref( p->dd, bState );
+//Extra_bddPrintSupport( p->dd, bImage ); printf( "\n" );
+
+ // move reached states into ring manager
+ bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) ); Cudd_Ref( bImage );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+//Extra_bddPrintSupport( p->ddR, bImage ); printf( "\n" );
+
+ // intersect with the previous set
+ bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing ); Cudd_Ref( bOneCube );
+ Cudd_RecursiveDeref( p->ddR, bImage );
+
+ // find any assignment of the BDD
+ RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues );
+ Cudd_RecursiveDeref( p->ddR, bOneCube );
+ assert( RetValue );
+/*
+ for ( i = 0; i < p->ddR->size; i++ )
+ printf( "%d ", pValues[i] );
+ printf( "\n" );
+*/
+ // write PIs of counter-example
+ nPiOffset -= Saig_ManPiNum(p->pAig);
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 )
+ Abc_InfoSetBit( pCex->pData, nPiOffset + i );
+
+ // check that we get the init state
+ if ( v == 0 )
+ {
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ assert( pValues[i] == 0 );
+ break;
+ }
+
+ // write state in terms of NS variables
+ bState = Llb_CoreComputeCube( p->dd, p->vGlo2Ns, 1, pValues ); Cudd_Ref( bState );
+ }
+ assert( nPiOffset == Saig_ManRegNum(p->pAig) );
+ // update the output number
+//Abc_CexPrint( pCex );
+ RetValue = Saig_ManFindFailedPoCex( p->pAigGlo, pCex );
+ assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pAigGlo) ); // invalid CEX!!!
+ pCex->iPo = RetValue;
+ // cleanup
+ ABC_FREE( pValues );
+ return pCex;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Perform reachability with hints and returns reached states in ppGlo.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManReachability( Llb_Man_t * p, Vec_Int_t * vHints, DdManager ** pddGlo )
+{
+ int * pNs2Glo = Vec_IntArray( p->vNs2Glo );
+ int * pCs2Glo = Vec_IntArray( p->vCs2Glo );
+ int * pGlo2Cs = Vec_IntArray( p->vGlo2Cs );
+ DdNode * bCurrent, * bReached, * bNext, * bTemp, * bCube;
+ DdNode * bConstrCs, * bConstrNs;
+ abctime clk2, clk = Abc_Clock();
+ int nIters, nBddSize = 0;
+// int nThreshold = 10000;
+
+ // compute time to stop
+ p->pPars->TimeTarget = p->pPars->TimeLimit ? p->pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0;
+
+ // define variable limits
+ Llb_ManPrepareVarLimits( p );
+
+ // start the managers
+ assert( p->dd == NULL );
+ assert( p->ddG == NULL );
+ assert( p->ddR == NULL );
+ p->dd = Cudd_Init( Vec_IntSize(p->vVar2Obj), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ p->ddR = Cudd_Init( Aig_ManCiNum(p->pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ if ( pddGlo && *pddGlo )
+ p->ddG = *pddGlo, *pddGlo = NULL;
+ else
+ p->ddG = Cudd_Init( Aig_ManRegNum(p->pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+
+ if ( p->pPars->fReorder )
+ {
+ Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT );
+ Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT );
+ Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT );
+ }
+ else
+ {
+ Cudd_AutodynDisable( p->dd );
+ Cudd_AutodynDisable( p->ddG );
+ Cudd_AutodynDisable( p->ddR );
+ }
+
+ // set the stop time parameter
+ p->dd->TimeStop = p->pPars->TimeTarget;
+ p->ddG->TimeStop = p->pPars->TimeTarget;
+ p->ddR->TimeStop = p->pPars->TimeTarget;
+
+ // create bad state in the ring manager
+ p->ddR->bFunc = Llb_BddComputeBad( p->pAigGlo, p->ddR, p->pPars->TimeTarget );
+ if ( p->ddR->bFunc == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = -1;
+ return -1;
+ }
+ Cudd_Ref( p->ddR->bFunc );
+
+ // derive constraints
+ bConstrCs = Llb_ManCreateConstraints( p, vHints, 0 ); Cudd_Ref( bConstrCs );
+ bConstrNs = Llb_ManCreateConstraints( p, vHints, 1 ); Cudd_Ref( bConstrNs );
+//Extra_bddPrint( p->dd, bConstrCs ); printf( "\n" );
+//Extra_bddPrint( p->dd, bConstrNs ); printf( "\n" );
+
+ // perform reachability analysis
+ // compute the starting set of states
+ if ( p->ddG->bFunc )
+ {
+ bReached = p->ddG->bFunc; p->ddG->bFunc = NULL;
+ bCurrent = Extra_TransferPermute( p->ddG, p->dd, bReached, pGlo2Cs ); Cudd_Ref( bCurrent );
+ }
+ else
+ {
+ bReached = Llb_ManComputeInitState( p, p->ddG ); Cudd_Ref( bReached );
+ bCurrent = Llb_ManComputeInitState( p, p->dd ); Cudd_Ref( bCurrent );
+ }
+//Extra_bddPrintSupport( p->ddG, bReached ); printf( "\n" );
+//Extra_bddPrintSupport( p->dd, bCurrent ); printf( "\n" );
+
+//Extra_bddPrintSupport( p->dd, bCurrent ); printf( "\n" );
+ for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ )
+ {
+ clk2 = Abc_Clock();
+ // check the runtime limit
+ if ( p->pPars->TimeLimit && Abc_Clock() > p->pPars->TimeTarget )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout during image computation (%d seconds).\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL;
+ Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL;
+ Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL;
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+
+ // save the onion ring
+ bTemp = Extra_TransferPermute( p->dd, p->ddR, bCurrent, pCs2Glo );
+ if ( bTemp == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during ring transfer.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL;
+ Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL;
+ Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL;
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+ Cudd_Ref( bTemp );
+ Vec_PtrPush( p->vRings, bTemp );
+
+ // check it for bad states
+ if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) )
+ {
+ assert( p->pAigGlo->pSeqModel == NULL );
+ if ( !p->pPars->fBackward )
+ p->pAigGlo->pSeqModel = Llb_ManReachDeriveCex( p );
+ if ( !p->pPars->fSilent )
+ {
+ if ( !p->pPars->fBackward )
+ Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", p->pAigGlo->pSeqModel->iPo, p->pAigGlo->pName, p->pAigGlo->pName, nIters );
+ else
+ Abc_Print( 1, "Output ??? of miter \"%s\" was asserted in frame %d (counter-example is not produced). ", p->pAigGlo->pName, nIters );
+ Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+ }
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL;
+ Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL;
+ Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL;
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ return 0;
+ }
+
+ // restrict reachable states using constraints
+ if ( vHints )
+ {
+ bCurrent = Cudd_bddAnd( p->dd, bTemp = bCurrent, bConstrCs ); Cudd_Ref( bCurrent );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+
+ // quantify variables appearing only in the init state
+ bCube = Llb_ManConstructQuantCubeIntern( p, (Llb_Grp_t *)Vec_PtrEntry(p->vGroups,0), 0, 0 ); Cudd_Ref( bCube );
+ bCurrent = Cudd_bddExistAbstract( p->dd, bTemp = bCurrent, bCube ); Cudd_Ref( bCurrent );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->dd, bCube );
+
+ // compute the next states
+ bNext = Llb_ManComputeImage( p, bCurrent, 0 );
+ if ( bNext == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL;
+ Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL;
+ Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL;
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+ Cudd_Ref( bNext );
+ Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL;
+
+ // restrict reachable states using constraints
+ if ( vHints )
+ {
+ bNext = Cudd_bddAnd( p->dd, bTemp = bNext, bConstrNs ); Cudd_Ref( bNext );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+//Extra_bddPrintSupport( p->dd, bNext ); printf( "\n" );
+
+ // remap these states into the current state vars
+// bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pNs2Glo ); Cudd_Ref( bNext );
+// Cudd_RecursiveDeref( p->dd, bTemp );
+// bNext = Extra_TransferPermuteTime( p->dd, p->ddG, bTemp = bNext, pNs2Glo, p->pPars->TimeTarget );
+ bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pNs2Glo );
+ if ( bNext == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL;
+ Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL;
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+ Cudd_Ref( bNext );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+
+
+ // check if there are any new states
+ if ( Cudd_bddLeq( p->ddG, bNext, bReached ) ) // implication = no new states
+ {
+ Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL;
+ break;
+ }
+
+ // check the BDD size
+ nBddSize = Cudd_DagSize(bNext);
+ if ( nBddSize > p->pPars->nBddMax )
+ {
+ Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL;
+ break;
+ }
+
+ // get the new states
+ bCurrent = Cudd_bddAnd( p->ddG, bNext, Cudd_Not(bReached) );
+ if ( bCurrent == NULL )
+ {
+ Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL;
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ break;
+ }
+ Cudd_Ref( bCurrent );
+ // minimize the new states with the reached states
+// bCurrent = Cudd_bddConstrain( p->ddG, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent );
+// bCurrent = Cudd_bddRestrict( p->ddG, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent );
+// Cudd_RecursiveDeref( p->ddG, bTemp );
+//printf( "Initial BDD =%7d. Constrained BDD =%7d.\n", Cudd_DagSize(bTemp), Cudd_DagSize(bCurrent) );
+
+ // remap these states into the current state vars
+// bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs ); Cudd_Ref( bCurrent );
+// Cudd_RecursiveDeref( p->ddG, bTemp );
+// bCurrent = Extra_TransferPermuteTime( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs, p->pPars->TimeTarget );
+ bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs );
+ if ( bCurrent == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->ddG, bTemp );
+ Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL;
+ Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL;
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+ Cudd_Ref( bCurrent );
+ Cudd_RecursiveDeref( p->ddG, bTemp );
+
+
+ // add to the reached states
+ bReached = Cudd_bddOr( p->ddG, bTemp = bReached, bNext );
+ if ( bReached == NULL )
+ {
+ Cudd_RecursiveDeref( p->ddG, bTemp ); bTemp = NULL;
+ Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL;
+ break;
+ }
+ Cudd_Ref( bReached );
+ Cudd_RecursiveDeref( p->ddG, bTemp );
+ Cudd_RecursiveDeref( p->ddG, bNext );
+ bNext = NULL;
+
+ if ( p->pPars->fVerbose )
+ {
+ fprintf( stdout, "F =%5d : ", nIters );
+ fprintf( stdout, "Im =%6d ", nBddSize );
+ fprintf( stdout, "(%4d %3d) ", Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) );
+ fprintf( stdout, "Rea =%6d ", Cudd_DagSize(bReached) );
+ fprintf( stdout, "(%4d%4d) ", Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) );
+ Abc_PrintTime( 1, "Time", Abc_Clock() - clk2 );
+ }
+/*
+ if ( p->pPars->fVerbose )
+ {
+ double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) );
+// Extra_bddPrint( p->ddG, bReached );printf( "\n" );
+ fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) );
+ fflush( stdout );
+ }
+*/
+ }
+ Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL;
+ Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL;
+ if ( bReached == NULL )
+ {
+ p->pPars->iFrame = nIters - 1;
+ return 0; // reachable
+ }
+// assert( bCurrent == NULL );
+ if ( bCurrent )
+ Cudd_RecursiveDeref( p->dd, bCurrent );
+ // report the stats
+ if ( p->pPars->fVerbose )
+ {
+ double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) );
+ if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax )
+ fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters );
+ else
+ fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters );
+ fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) );
+ fflush( stdout );
+ }
+ if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Verified only for states reachable in %d frames. ", nIters );
+ p->pPars->iFrame = p->pPars->nIterMax;
+ Cudd_RecursiveDeref( p->ddG, bReached );
+ return -1; // undecided
+ }
+ if ( pddGlo )
+ {
+ assert( p->ddG->bFunc == NULL );
+ p->ddG->bFunc = bReached; bReached = NULL;
+ assert( *pddGlo == NULL );
+ *pddGlo = p->ddG; p->ddG = NULL;
+ }
+ else
+ Cudd_RecursiveDeref( p->ddG, bReached );
+ if ( !p->pPars->fSilent )
+ printf( "The miter is proved unreachable after %d iterations. ", nIters );
+ p->pPars->iFrame = nIters - 1;
+ return 1; // unreachable
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/bdd/llb/llb1Sched.c b/src/bdd/llb/llb1Sched.c
new file mode 100644
index 00000000..51de973a
--- /dev/null
+++ b/src/bdd/llb/llb1Sched.c
@@ -0,0 +1,257 @@
+/**CFile****************************************************************
+
+ FileName [llb1Sched.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Partition scheduling algorithm.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb1Sched.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Swaps two rows.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MtrSwapColumns( Llb_Mtr_t * p, int iCol1, int iCol2 )
+{
+ Llb_Grp_t * pGemp;
+ char * pTemp;
+ int iTemp;
+ assert( iCol1 >= 0 && iCol1 < p->nCols );
+ assert( iCol2 >= 0 && iCol2 < p->nCols );
+ if ( iCol1 == iCol2 )
+ return;
+ assert( iCol1 != iCol2 );
+ // swap col groups
+ pGemp = p->pColGrps[iCol1];
+ p->pColGrps[iCol1] = p->pColGrps[iCol2];
+ p->pColGrps[iCol2] = pGemp;
+ // swap col vectors
+ pTemp = p->pMatrix[iCol1];
+ p->pMatrix[iCol1] = p->pMatrix[iCol2];
+ p->pMatrix[iCol2] = pTemp;
+ // swap col sums
+ iTemp = p->pColSums[iCol1];
+ p->pColSums[iCol1] = p->pColSums[iCol2];
+ p->pColSums[iCol2] = iTemp;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find columns which brings as few vars as possible.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_MtrFindBestColumn( Llb_Mtr_t * p, int iGrpStart )
+{
+ int Cost, Cost2, CostBest = ABC_INFINITY, Cost2Best = ABC_INFINITY;
+ int WeightCur, WeightBest = -ABC_INFINITY, iGrp = -1, iGrpBest = -1;
+ int k, c, iVar, Counter;
+ // find partition that reduces partial product as much as possible
+ for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ )
+ {
+ if ( p->pRowSums[iVar] < 2 )
+ continue;
+ // look at present variables that can be quantified
+ if ( !(p->pProdVars[iVar] == 1 && p->pProdNums[iVar] == 1) )
+ continue;
+ // check that it appears in one partition only
+ Counter = 0;
+ for ( c = iGrpStart; c < p->nCols-1; c++ )
+ if ( p->pMatrix[c][iVar] == 1 )
+ {
+ iGrp = c;
+ Counter++;
+ }
+ assert( Counter == 1 );
+ if ( Counter != 1 )
+ Abc_Print( -1, "Llb_MtrFindBestColumn() Internal error!\n" );
+ // find weight of this column
+ WeightCur = 0;
+ for ( k = 0; k < p->nRows; k++ )
+ {
+ // increase weight if variable k will be quantified from partial product
+ if ( p->pProdVars[k] == 1 && p->pMatrix[iGrp][k] == 1 && p->pProdNums[k] == 1 )
+ WeightCur += 2;
+ // decrease weight if variable k will be added to partial product
+ if ( p->pProdVars[k] == 0 && p->pMatrix[iGrp][k] == 1 )
+ WeightCur--;
+ }
+ if ( WeightCur > 0 && WeightBest < WeightCur )
+ {
+ WeightBest = WeightCur;
+ iGrpBest = iGrp;
+ }
+ }
+ if ( iGrpBest >= 0 )
+ return iGrpBest;
+ // could not find the group with any vars to quantify
+ // select the group that contains as few extra variables as possible
+ // if there is a tie, select variables that appear in less groups than others
+ for ( iGrp = iGrpStart; iGrp < p->nCols-1; iGrp++ )
+ {
+ Cost = Cost2 = 0;
+ for ( k = 0; k < p->nRows; k++ )
+ if ( p->pProdVars[k] == 0 && p->pMatrix[iGrp][k] == 1 )
+ {
+ Cost++;
+ Cost2 += p->pProdNums[k];
+ }
+ if ( CostBest > Cost ||
+ (CostBest == Cost && Cost2 > Cost2Best) )
+ {
+ CostBest = Cost;
+ Cost2Best = Cost2;
+ iGrpBest = iGrp;
+ }
+ }
+ return iGrpBest;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of variables that will be saved.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MtrUseSelectedColumn( Llb_Mtr_t * p, int iCol )
+{
+ int iVar;
+ assert( iCol >= 1 && iCol < p->nCols - 1 );
+ for ( iVar = 0; iVar < p->nRows; iVar++ )
+ {
+ if ( p->pMatrix[iCol][iVar] == 0 )
+ continue;
+ if ( p->pProdVars[iVar] == 1 && p->pProdNums[iVar] == 1 )
+ {
+ p->pProdVars[iVar] = 0;
+ p->pProdNums[iVar] = 0;
+ continue;
+ }
+ if ( p->pProdVars[iVar] == 0 )
+ {
+ p->pProdVars[iVar] = 1;
+ p->pProdNums[iVar] = p->pRowSums[iVar];
+ }
+ p->pProdNums[iVar]--;
+ assert( p->pProdNums[iVar] >= 0 );
+ if ( p->pProdNums[iVar] < 0 )
+ Abc_Print( -1, "Llb_MtrUseSelectedColumn() Internal error!\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verify columns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MtrVerifyColumns( Llb_Mtr_t * p, int iGrpStart )
+{
+ int iVar, iGrp, Counter;
+ for ( iVar = 0; iVar < p->nRows; iVar++ )
+ {
+ if ( p->pProdVars[iVar] == 0 )
+ continue;
+ Counter = 0;
+ for ( iGrp = iGrpStart; iGrp < p->nCols; iGrp++ )
+ if ( p->pMatrix[iGrp][iVar] == 1 )
+ Counter++;
+ assert( Counter == p->pProdNums[iVar] );
+ if ( Counter != p->pProdNums[iVar] )
+ Abc_Print( -1, "Llb_MtrVerifyColumns(): Internal error.\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Matrix reduce.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MtrSchedule( Llb_Mtr_t * p )
+{
+ int iGrp, iGrpBest, i;
+ // start partial product
+ for ( i = 0; i < p->nRows; i++ )
+ {
+ if ( i >= p->nPis && i < p->nPis + p->nFfs )
+ {
+ p->pProdVars[i] = 1;
+ p->pProdNums[i] = p->pRowSums[i] - 1;
+ }
+ else
+ {
+ p->pProdVars[i] = 0;
+ p->pProdNums[i] = p->pRowSums[i];
+ }
+ }
+ // order the partitions
+ Llb_MtrVerifyMatrix( p );
+ for ( iGrp = 1; iGrp < p->nCols-1; iGrp++ )
+ {
+ Llb_MtrVerifyColumns( p, iGrp );
+ iGrpBest = Llb_MtrFindBestColumn( p, iGrp );
+ Llb_MtrUseSelectedColumn( p, iGrpBest );
+ Llb_MtrSwapColumns( p, iGrp, iGrpBest );
+ }
+ Llb_MtrVerifyMatrix( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/bdd/llb/llb2Bad.c b/src/bdd/llb/llb2Bad.c
new file mode 100644
index 00000000..ac04b563
--- /dev/null
+++ b/src/bdd/llb/llb2Bad.c
@@ -0,0 +1,138 @@
+/**CFile****************************************************************
+
+ FileName [llb2Bad.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Computing bad states.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb2Bad.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes bad in working manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_BddComputeBad( Aig_Man_t * pInit, DdManager * dd, abctime TimeOut )
+{
+ Vec_Ptr_t * vNodes;
+ DdNode * bBdd0, * bBdd1, * bTemp, * bResult;
+ Aig_Obj_t * pObj;
+ int i, k;
+ assert( Cudd_ReadSize(dd) == Aig_ManCiNum(pInit) );
+ // initialize elementary variables
+ Aig_ManConst1(pInit)->pData = Cudd_ReadOne( dd );
+ Saig_ManForEachLo( pInit, pObj, i )
+ pObj->pData = Cudd_bddIthVar( dd, i );
+ Saig_ManForEachPi( pInit, pObj, i )
+ pObj->pData = Cudd_bddIthVar( dd, Aig_ManRegNum(pInit) + i );
+ // compute internal nodes
+ vNodes = Aig_ManDfsNodes( pInit, (Aig_Obj_t **)Vec_PtrArray(pInit->vCos), Saig_ManPoNum(pInit) );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+ {
+ if ( !Aig_ObjIsNode(pObj) )
+ continue;
+ bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+// pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeOut );
+ pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 );
+ if ( pObj->pData == NULL )
+ {
+ Vec_PtrForEachEntryStop( Aig_Obj_t *, vNodes, pObj, k, i )
+ if ( pObj->pData )
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+ Vec_PtrFree( vNodes );
+ return NULL;
+ }
+ Cudd_Ref( (DdNode *)pObj->pData );
+ }
+ // quantify PIs of each PO
+ bResult = Cudd_ReadLogicZero( dd ); Cudd_Ref( bResult );
+ Saig_ManForEachPo( pInit, pObj, i )
+ {
+ bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bResult = Cudd_bddOr( dd, bTemp = bResult, bBdd0 ); Cudd_Ref( bResult );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ // deref
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+ {
+ if ( !Aig_ObjIsNode(pObj) )
+ continue;
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+ }
+ Vec_PtrFree( vNodes );
+ Cudd_Deref( bResult );
+ return bResult;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_BddQuantifyPis( Aig_Man_t * pInit, DdManager * dd, DdNode * bFunc )
+{
+ DdNode * bVar, * bCube, * bTemp;
+ Aig_Obj_t * pObj;
+ int i;
+ abctime TimeStop;
+ assert( Cudd_ReadSize(dd) == Aig_ManCiNum(pInit) );
+ TimeStop = dd->TimeStop; dd->TimeStop = 0;
+ // create PI cube
+ bCube = Cudd_ReadOne( dd ); Cudd_Ref( bCube );
+ Saig_ManForEachPi( pInit, pObj, i ) {
+ bVar = Cudd_bddIthVar( dd, Aig_ManRegNum(pInit) + i );
+ bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ // quantify PI cube
+ bFunc = Cudd_bddExistAbstract( dd, bFunc, bCube ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( dd, bCube );
+ Cudd_Deref( bFunc );
+ dd->TimeStop = TimeStop;
+ return bFunc;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/bdd/llb/llb2Core.c b/src/bdd/llb/llb2Core.c
new file mode 100644
index 00000000..3d62b322
--- /dev/null
+++ b/src/bdd/llb/llb2Core.c
@@ -0,0 +1,777 @@
+/**CFile****************************************************************
+
+ FileName [llb2Core.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Core procedure.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb2Core.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Llb_Img_t_ Llb_Img_t;
+struct Llb_Img_t_
+{
+ Aig_Man_t * pInit; // AIG manager
+ Aig_Man_t * pAig; // AIG manager
+ Gia_ParLlb_t * pPars; // parameters
+
+ DdManager * dd; // BDD manager
+ DdManager * ddG; // BDD manager
+ DdManager * ddR; // BDD manager
+ Vec_Ptr_t * vDdMans; // BDD managers for each partition
+ Vec_Ptr_t * vRings; // onion rings in ddR
+
+ Vec_Int_t * vDriRefs; // driver references
+ Vec_Int_t * vVarsCs; // cur state variables
+ Vec_Int_t * vVarsNs; // next state variables
+
+ Vec_Int_t * vCs2Glo; // cur state variables into global variables
+ Vec_Int_t * vNs2Glo; // next state variables into global variables
+ Vec_Int_t * vGlo2Cs; // global variables into cur state variables
+ Vec_Int_t * vGlo2Ns; // global variables into next state variables
+};
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes cube composed of given variables with given values.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_CoreComputeCube( DdManager * dd, Vec_Int_t * vVars, int fUseVarIndex, char * pValues )
+{
+ DdNode * bRes, * bVar, * bTemp;
+ int i, iVar, Index;
+ abctime TimeStop;
+ TimeStop = dd->TimeStop; dd->TimeStop = 0;
+ bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes );
+ Vec_IntForEachEntry( vVars, Index, i )
+ {
+ iVar = fUseVarIndex ? Index : i;
+ bVar = Cudd_NotCond( Cudd_bddIthVar(dd, iVar), (int)(pValues == NULL || pValues[i] != 1) );
+ bRes = Cudd_bddAnd( dd, bTemp = bRes, bVar ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bRes );
+ dd->TimeStop = TimeStop;
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives counter-example by backward reachability.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Cex_t * Llb_CoreDeriveCex( Llb_Img_t * p )
+{
+ Abc_Cex_t * pCex;
+ Aig_Obj_t * pObj;
+ Vec_Ptr_t * vSupps, * vQuant0, * vQuant1;
+ DdNode * bState = NULL, * bImage, * bOneCube, * bTemp, * bRing;
+ int i, v, RetValue, nPiOffset;
+ char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) );
+ assert( Vec_PtrSize(p->vRings) > 0 );
+
+ p->dd->TimeStop = 0;
+ p->ddR->TimeStop = 0;
+
+ // get supports and quantified variables
+ Vec_PtrReverseOrder( p->vDdMans );
+ vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsNs, p->vVarsCs, 1, 0 );
+ Llb_ImgSchedule( vSupps, &vQuant0, &vQuant1, 0 );
+ Vec_VecFree( (Vec_Vec_t *)vSupps );
+ Llb_ImgQuantifyReset( p->vDdMans );
+// Llb_ImgQuantifyFirst( p->pAig, p->vDdMans, vQuant0 );
+
+ // allocate room for the counter-example
+ pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) );
+ pCex->iFrame = Vec_PtrSize(p->vRings) - 1;
+ pCex->iPo = -1;
+
+ // get the last cube
+ bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc ); Cudd_Ref( bOneCube );
+ RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues );
+ Cudd_RecursiveDeref( p->ddR, bOneCube );
+ assert( RetValue );
+
+ // write PIs of counter-example
+ nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1);
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 )
+ Abc_InfoSetBit( pCex->pData, nPiOffset + i );
+
+ // write state in terms of NS variables
+ if ( Vec_PtrSize(p->vRings) > 1 )
+ {
+ bState = Llb_CoreComputeCube( p->dd, p->vVarsNs, 1, pValues ); Cudd_Ref( bState );
+ }
+ // perform backward analysis
+ Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v )
+ {
+ if ( v == Vec_PtrSize(p->vRings) - 1 )
+ continue;
+ // compute the next states
+ bImage = Llb_ImgComputeImage( p->pAig, p->vDdMans, p->dd, bState,
+ vQuant0, vQuant1, p->vDriRefs, p->pPars->TimeTarget, 1, 0, 0 );
+ assert( bImage != NULL );
+ Cudd_Ref( bImage );
+ Cudd_RecursiveDeref( p->dd, bState );
+//Extra_bddPrintSupport( p->dd, bImage ); printf( "\n" );
+
+ // move reached states into ring manager
+ bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) ); Cudd_Ref( bImage );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+
+ // intersect with the previous set
+ bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing ); Cudd_Ref( bOneCube );
+ Cudd_RecursiveDeref( p->ddR, bImage );
+
+ // find any assignment of the BDD
+ RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues );
+ Cudd_RecursiveDeref( p->ddR, bOneCube );
+ assert( RetValue );
+
+ // write PIs of counter-example
+ nPiOffset -= Saig_ManPiNum(p->pAig);
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 )
+ Abc_InfoSetBit( pCex->pData, nPiOffset + i );
+
+ // check that we get the init state
+ if ( v == 0 )
+ {
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ assert( pValues[i] == 0 );
+ break;
+ }
+
+ // write state in terms of NS variables
+ bState = Llb_CoreComputeCube( p->dd, p->vVarsNs, 1, pValues ); Cudd_Ref( bState );
+ }
+ assert( nPiOffset == Saig_ManRegNum(p->pAig) );
+ // update the output number
+ RetValue = Saig_ManFindFailedPoCex( p->pInit, pCex );
+ assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pInit) ); // invalid CEX!!!
+ pCex->iPo = RetValue;
+ // cleanup
+ ABC_FREE( pValues );
+ Vec_VecFree( (Vec_Vec_t *)vQuant0 );
+ Vec_VecFree( (Vec_Vec_t *)vQuant1 );
+ return pCex;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_CoreReachability_int( Llb_Img_t * p, Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1 )
+{
+ int * pLoc2Glo = p->pPars->fBackward? Vec_IntArray( p->vCs2Glo ) : Vec_IntArray( p->vNs2Glo );
+ int * pLoc2GloR = p->pPars->fBackward? Vec_IntArray( p->vNs2Glo ) : Vec_IntArray( p->vCs2Glo );
+ int * pGlo2Loc = p->pPars->fBackward? Vec_IntArray( p->vGlo2Ns ) : Vec_IntArray( p->vGlo2Cs );
+ DdNode * bCurrent, * bReached, * bNext, * bTemp;
+ abctime clk2, clk = Abc_Clock();
+ int nIters, nBddSize;//, iOutFail = -1;
+/*
+ // compute time to stop
+ if ( p->pPars->TimeLimit )
+ p->pPars->TimeTarget = Abc_Clock() + p->pPars->TimeLimit * CLOCKS_PER_SEC;
+ else
+ p->pPars->TimeTarget = 0;
+*/
+
+ if ( Abc_Clock() > p->pPars->TimeTarget )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) before image computation.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = -1;
+ return -1;
+ }
+
+ // set the stop time parameter
+ p->dd->TimeStop = p->pPars->TimeTarget;
+ p->ddG->TimeStop = p->pPars->TimeTarget;
+ p->ddR->TimeStop = p->pPars->TimeTarget;
+
+ // compute initial states
+ if ( p->pPars->fBackward )
+ {
+ // create init state in the global manager
+ bTemp = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget );
+ if ( bTemp == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) while computing bad states.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = -1;
+ return -1;
+ }
+ Cudd_Ref( bTemp );
+ // create bad state in the ring manager
+ p->ddR->bFunc = Llb_CoreComputeCube( p->ddR, p->vVarsCs, 0, NULL ); Cudd_Ref( p->ddR->bFunc );
+ bCurrent = Llb_BddQuantifyPis( p->pInit, p->ddR, bTemp ); Cudd_Ref( bCurrent );
+ Cudd_RecursiveDeref( p->ddR, bTemp );
+ bReached = Cudd_bddTransfer( p->ddR, p->ddG, bCurrent ); Cudd_Ref( bReached );
+ Cudd_RecursiveDeref( p->ddR, bCurrent );
+ // move init state to the working manager
+ bCurrent = Extra_TransferPermute( p->ddG, p->dd, bReached, pGlo2Loc );
+ if ( bCurrent == NULL )
+ {
+ Cudd_RecursiveDeref( p->ddG, bReached );
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during transfer 0.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = -1;
+ return -1;
+ }
+ Cudd_Ref( bCurrent );
+ }
+ else
+ {
+ // create bad state in the ring manager
+ p->ddR->bFunc = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget );
+ if ( p->ddR->bFunc == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) while computing bad states.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = -1;
+ return -1;
+ }
+ Cudd_Ref( p->ddR->bFunc );
+ // create init state in the working and global manager
+ bCurrent = Llb_CoreComputeCube( p->dd, p->vVarsCs, 1, NULL ); Cudd_Ref( bCurrent );
+ bReached = Llb_CoreComputeCube( p->ddG, p->vVarsCs, 0, NULL ); Cudd_Ref( bReached );
+//Extra_bddPrint( p->dd, bCurrent ); printf( "\n" );
+//Extra_bddPrint( p->ddG, bReached ); printf( "\n" );
+ }
+
+ // compute onion rings
+ for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ )
+ {
+ clk2 = Abc_Clock();
+ // check the runtime limit
+ if ( p->pPars->TimeLimit && Abc_Clock() > p->pPars->TimeTarget )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL;
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+
+ // save the onion ring
+ bTemp = Extra_TransferPermute( p->dd, p->ddR, bCurrent, pLoc2GloR );
+ if ( bTemp == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL;
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+ Cudd_Ref( bTemp );
+ Vec_PtrPush( p->vRings, bTemp );
+
+ // check it for bad states
+ if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) )
+ {
+ assert( p->pInit->pSeqModel == NULL );
+ if ( !p->pPars->fBackward )
+ p->pInit->pSeqModel = Llb_CoreDeriveCex( p );
+ Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL;
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ if ( !p->pPars->fSilent )
+ {
+ if ( !p->pPars->fBackward )
+ Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", p->pInit->pSeqModel->iPo, p->pInit->pName, nIters );
+ else
+ Abc_Print( 1, "Output ??? was asserted in frame %d (counter-example is not produced). ", nIters );
+ Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+ }
+ p->pPars->iFrame = nIters - 1;
+ return 0;
+ }
+
+ // compute the next states
+ bNext = Llb_ImgComputeImage( p->pAig, p->vDdMans, p->dd, bCurrent,
+ vQuant0, vQuant1, p->vDriRefs, p->pPars->TimeTarget,
+ p->pPars->fBackward, p->pPars->fReorder, p->pPars->fVeryVerbose );
+ if ( bNext == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL;
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+ Cudd_Ref( bNext );
+ Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL;
+//Extra_bddPrintSupport( p->dd, bNext ); printf( "\n" );
+
+ // remap these states into the global manager
+// bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pLoc2Glo ); Cudd_Ref( bNext );
+// Cudd_RecursiveDeref( p->dd, bTemp );
+
+// bNext = Extra_TransferPermuteTime( p->dd, p->ddG, bTemp = bNext, pLoc2Glo, p->pPars->TimeTarget );
+ bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pLoc2Glo );
+ if ( bNext == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+ Cudd_Ref( bNext );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+
+ nBddSize = Cudd_DagSize(bNext);
+ // check if there are any new states
+ if ( Cudd_bddLeq( p->ddG, bNext, bReached ) ) // implication = no new states
+ {
+ Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL;
+ break;
+ }
+
+ // get the new states
+ bCurrent = Cudd_bddAnd( p->ddG, bNext, Cudd_Not(bReached) );
+ if ( bCurrent == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->ddG, bNext );
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+ Cudd_Ref( bCurrent );
+
+ // remap these states into the current state vars
+// bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc ); Cudd_Ref( bCurrent );
+// Cudd_RecursiveDeref( p->ddG, bTemp );
+
+// bCurrent = Extra_TransferPermuteTime( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc, p->pPars->TimeTarget );
+ bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc );
+ if ( bCurrent == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->ddG, bTemp );
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+ Cudd_Ref( bCurrent );
+ Cudd_RecursiveDeref( p->ddG, bTemp );
+
+ // add to the reached states
+ bReached = Cudd_bddOr( p->ddG, bTemp = bReached, bNext ); Cudd_Ref( bReached );
+ Cudd_RecursiveDeref( p->ddG, bTemp );
+ Cudd_RecursiveDeref( p->ddG, bNext );
+ bNext = NULL;
+
+ if ( p->pPars->fVeryVerbose )
+ {
+ double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) );
+// Extra_bddPrint( p->ddG, bReached );printf( "\n" );
+ fprintf( stdout, " Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) );
+ fflush( stdout );
+ }
+ if ( p->pPars->fVerbose )
+ {
+ fprintf( stdout, "F =%3d : ", nIters );
+ fprintf( stdout, "Image =%6d ", nBddSize );
+ fprintf( stdout, "(%4d%4d) ",
+ Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) );
+ fprintf( stdout, "Reach =%6d ", Cudd_DagSize(bReached) );
+ fprintf( stdout, "(%4d%4d) ",
+ Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) );
+ Abc_PrintTime( 1, "Time", Abc_Clock() - clk2 );
+ }
+
+ // check timeframe limit
+ if ( nIters == p->pPars->nIterMax - 1 )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nIterMax );
+ p->pPars->iFrame = nIters;
+ Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL;
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+ }
+ if ( bReached == NULL )
+ {
+ p->pPars->iFrame = nIters - 1;
+ return 0; // reachable
+ }
+ if ( bCurrent )
+ Cudd_RecursiveDeref( p->dd, bCurrent );
+ // report the stats
+ if ( p->pPars->fVerbose )
+ {
+ double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) );
+ if ( nIters >= p->pPars->nIterMax )
+ fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters );
+ else
+ fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters );
+ fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) );
+ fflush( stdout );
+ }
+ if ( p->pPars->fDumpReached )
+ {
+ Llb_ManDumpReached( p->ddG, bReached, p->pAig->pName, "reached.blif" );
+ printf( "Reached states with %d BDD nodes are dumpted into file \"reached.blif\".\n", Cudd_DagSize(bReached) );
+ }
+ Cudd_RecursiveDeref( p->ddG, bReached );
+ if ( nIters >= p->pPars->nIterMax )
+ {
+ if ( !p->pPars->fSilent )
+ {
+ printf( "Verified only for states reachable in %d frames. ", nIters );
+ Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+ }
+ p->pPars->iFrame = p->pPars->nIterMax;
+ return -1; // undecided
+ }
+ if ( !p->pPars->fSilent )
+ {
+ printf( "The miter is proved unreachable after %d iterations. ", nIters );
+ Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+ }
+ p->pPars->iFrame = nIters - 1;
+ return 1; // unreachable
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_CoreReachability( Llb_Img_t * p )
+{
+ Vec_Ptr_t * vSupps, * vQuant0, * vQuant1;
+ int RetValue;
+ // get supports and quantified variables
+ if ( p->pPars->fBackward )
+ {
+ Vec_PtrReverseOrder( p->vDdMans );
+ vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsNs, p->vVarsCs, 0, p->pPars->fVeryVerbose );
+ }
+ else
+ vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsCs, p->vVarsNs, 0, p->pPars->fVeryVerbose );
+ Llb_ImgSchedule( vSupps, &vQuant0, &vQuant1, p->pPars->fVeryVerbose );
+ Vec_VecFree( (Vec_Vec_t *)vSupps );
+ // remove variables
+ Llb_ImgQuantifyFirst( p->pAig, p->vDdMans, vQuant0, p->pPars->fVeryVerbose );
+ // perform reachability
+ RetValue = Llb_CoreReachability_int( p, vQuant0, vQuant1 );
+ Vec_VecFree( (Vec_Vec_t *)vQuant0 );
+ Vec_VecFree( (Vec_Vec_t *)vQuant1 );
+ return RetValue;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_CoreConstructAll( Aig_Man_t * p, Vec_Ptr_t * vResult, Vec_Int_t * vVarsNs, abctime TimeTarget )
+{
+ DdManager * dd;
+ Vec_Ptr_t * vDdMans;
+ Vec_Ptr_t * vLower, * vUpper = NULL;
+ int i;
+ vDdMans = Vec_PtrStart( Vec_PtrSize(vResult) );
+ Vec_PtrForEachEntryReverse( Vec_Ptr_t *, vResult, vLower, i )
+ {
+ if ( i < Vec_PtrSize(vResult) - 1 )
+ dd = Llb_ImgPartition( p, vLower, vUpper, TimeTarget );
+ else
+ dd = Llb_DriverLastPartition( p, vVarsNs, TimeTarget );
+ if ( dd == NULL )
+ {
+ Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i )
+ {
+ if ( dd == NULL )
+ continue;
+ if ( dd->bFunc )
+ Cudd_RecursiveDeref( dd, dd->bFunc );
+ Extra_StopManager( dd );
+ }
+ Vec_PtrFree( vDdMans );
+ return NULL;
+ }
+ Vec_PtrWriteEntry( vDdMans, i, dd );
+ vUpper = vLower;
+ }
+ return vDdMans;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_CoreSetVarMaps( Llb_Img_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i, iVarCs, iVarNs;
+ assert( p->vVarsCs != NULL );
+ assert( p->vVarsNs != NULL );
+ assert( p->vCs2Glo == NULL );
+ assert( p->vNs2Glo == NULL );
+ assert( p->vGlo2Cs == NULL );
+ assert( p->vGlo2Ns == NULL );
+ p->vCs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) );
+ p->vNs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) );
+ p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) );
+ p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) );
+ for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ )
+ {
+ iVarCs = Vec_IntEntry( p->vVarsCs, i );
+ iVarNs = Vec_IntEntry( p->vVarsNs, i );
+ assert( iVarCs >= 0 && iVarCs < Aig_ManObjNumMax(p->pAig) );
+ assert( iVarNs >= 0 && iVarNs < Aig_ManObjNumMax(p->pAig) );
+ Vec_IntWriteEntry( p->vCs2Glo, iVarCs, i );
+ Vec_IntWriteEntry( p->vNs2Glo, iVarNs, i );
+ Vec_IntWriteEntry( p->vGlo2Cs, i, iVarCs );
+ Vec_IntWriteEntry( p->vGlo2Ns, i, iVarNs );
+ }
+ // add mapping of the PIs
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ Vec_IntWriteEntry( p->vCs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Img_t * Llb_CoreStart( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars )
+{
+ Llb_Img_t * p;
+ p = ABC_CALLOC( Llb_Img_t, 1 );
+ p->pInit = pInit;
+ p->pAig = pAig;
+ p->pPars = pPars;
+ p->dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ p->ddG = Cudd_Init( Aig_ManRegNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ p->ddR = Cudd_Init( Aig_ManCiNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT );
+ Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT );
+ Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT );
+ p->vRings = Vec_PtrAlloc( 100 );
+ p->vDriRefs = Llb_DriverCountRefs( pAig );
+ p->vVarsCs = Llb_DriverCollectCs( pAig );
+ p->vVarsNs = Llb_DriverCollectNs( pAig, p->vDriRefs );
+ Llb_CoreSetVarMaps( p );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_CoreStop( Llb_Img_t * p )
+{
+ DdManager * dd;
+ DdNode * bTemp;
+ int i;
+ if ( p->vDdMans )
+ Vec_PtrForEachEntry( DdManager *, p->vDdMans, dd, i )
+ {
+ if ( dd->bFunc )
+ Cudd_RecursiveDeref( dd, dd->bFunc );
+ if ( dd->bFunc2 )
+ Cudd_RecursiveDeref( dd, dd->bFunc2 );
+ Extra_StopManager( dd );
+ }
+ Vec_PtrFreeP( &p->vDdMans );
+ if ( p->ddR->bFunc )
+ Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc );
+ Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i )
+ Cudd_RecursiveDeref( p->ddR, bTemp );
+ Vec_PtrFree( p->vRings );
+ Extra_StopManager( p->dd );
+ Extra_StopManager( p->ddG );
+ Extra_StopManager( p->ddR );
+ Vec_IntFreeP( &p->vDriRefs );
+ Vec_IntFreeP( &p->vVarsCs );
+ Vec_IntFreeP( &p->vVarsNs );
+ Vec_IntFreeP( &p->vCs2Glo );
+ Vec_IntFreeP( &p->vNs2Glo );
+ Vec_IntFreeP( &p->vGlo2Cs );
+ Vec_IntFreeP( &p->vGlo2Ns );
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_CoreExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, abctime TimeTarget )
+{
+ int RetValue;
+ Llb_Img_t * p;
+// printf( "\n" );
+// pPars->fVerbose = 1;
+ p = Llb_CoreStart( pInit, pAig, pPars );
+ p->vDdMans = Llb_CoreConstructAll( pAig, vResult, p->vVarsNs, TimeTarget );
+ if ( p->vDdMans == NULL )
+ {
+ if ( !pPars->fSilent )
+ printf( "Reached timeout (%d seconds) while deriving the partitions.\n", pPars->TimeLimit );
+ Llb_CoreStop( p );
+ return -1;
+ }
+ RetValue = Llb_CoreReachability( p );
+ Llb_CoreStop( p );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds balanced cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManReachMinCut( Aig_Man_t * pAig, Gia_ParLlb_t * pPars )
+{
+ extern Vec_Ptr_t * Llb_ManComputeCuts( Aig_Man_t * p, int Num, int fVerbose, int fVeryVerbose );
+ Vec_Ptr_t * vResult;
+ Aig_Man_t * p;
+ int RetValue = -1;
+ abctime clk = Abc_Clock();
+
+ // compute time to stop
+ pPars->TimeTarget = pPars->TimeLimit ? pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0;
+
+ p = Aig_ManDupFlopsOnly( pAig );
+//Aig_ManShow( p, 0, NULL );
+ if ( pPars->fVerbose )
+ Aig_ManPrintStats( pAig );
+ if ( pPars->fVerbose )
+ Aig_ManPrintStats( p );
+ Aig_ManFanoutStart( p );
+
+ vResult = Llb_ManComputeCuts( p, pPars->nPartValue, pPars->fVerbose, pPars->fVeryVerbose );
+
+ if ( pPars->TimeLimit && Abc_Clock() > pPars->TimeTarget )
+ {
+ if ( !pPars->fSilent )
+ printf( "Reached timeout (%d seconds) after partitioning.\n", pPars->TimeLimit );
+
+ Vec_VecFree( (Vec_Vec_t *)vResult );
+ Aig_ManFanoutStop( p );
+ Aig_ManCleanMarkAB( p );
+ Aig_ManStop( p );
+ return RetValue;
+ }
+
+ if ( !pPars->fSkipReach )
+ RetValue = Llb_CoreExperiment( pAig, p, pPars, vResult, pPars->TimeTarget );
+
+ Vec_VecFree( (Vec_Vec_t *)vResult );
+ Aig_ManFanoutStop( p );
+ Aig_ManCleanMarkAB( p );
+ Aig_ManStop( p );
+
+ if ( RetValue == -1 )
+ Abc_PrintTime( 1, "Total runtime of the min-cut-based reachability engine", Abc_Clock() - clk );
+ return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/bdd/llb/llb2Driver.c b/src/bdd/llb/llb2Driver.c
new file mode 100644
index 00000000..1471f377
--- /dev/null
+++ b/src/bdd/llb/llb2Driver.c
@@ -0,0 +1,222 @@
+/**CFile****************************************************************
+
+ FileName [llb2Driver.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Procedures working with flop drivers.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb2Driver.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// driver issue:arises when creating
+// - driver ref-counter array
+// - Ns2Glo maps
+// - final partition
+// - change-phase cube
+
+// LI variable is used when
+// - driver drives more than one LI
+// - driver is a PI
+// - driver is a constant
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of times each flop driver is referenced.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_DriverCountRefs( Aig_Man_t * p )
+{
+ Vec_Int_t * vCounts;
+ Aig_Obj_t * pObj;
+ int i;
+ vCounts = Vec_IntStart( Aig_ManObjNumMax(p) );
+ Saig_ManForEachLi( p, pObj, i )
+ Vec_IntAddToEntry( vCounts, Aig_ObjFaninId0(pObj), 1 );
+ return vCounts;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns array of NS variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_DriverCollectNs( Aig_Man_t * pAig, Vec_Int_t * vDriRefs )
+{
+ Vec_Int_t * vVars;
+ Aig_Obj_t * pObj, * pDri;
+ int i;
+ vVars = Vec_IntAlloc( Aig_ManRegNum(pAig) );
+ Saig_ManForEachLi( pAig, pObj, i )
+ {
+ pDri = Aig_ObjFanin0(pObj);
+ if ( Vec_IntEntry( vDriRefs, Aig_ObjId(pDri) ) != 1 || Saig_ObjIsPi(pAig, pDri) || Aig_ObjIsConst1(pDri) )
+ Vec_IntPush( vVars, Aig_ObjId(pObj) );
+ else
+ Vec_IntPush( vVars, Aig_ObjId(pDri) );
+ }
+ return vVars;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns array of CS variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_DriverCollectCs( Aig_Man_t * pAig )
+{
+ Vec_Int_t * vVars;
+ Aig_Obj_t * pObj;
+ int i;
+ vVars = Vec_IntAlloc( Aig_ManRegNum(pAig) );
+ Saig_ManForEachLo( pAig, pObj, i )
+ Vec_IntPush( vVars, Aig_ObjId(pObj) );
+ return vVars;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create cube for phase swapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_DriverPhaseCube( Aig_Man_t * pAig, Vec_Int_t * vDriRefs, DdManager * dd )
+{
+ DdNode * bCube, * bVar, * bTemp;
+ Aig_Obj_t * pObj;
+ int i;
+ abctime TimeStop;
+ TimeStop = dd->TimeStop; dd->TimeStop = 0;
+ bCube = Cudd_ReadOne( dd ); Cudd_Ref( bCube );
+ Saig_ManForEachLi( pAig, pObj, i )
+ {
+ assert( Vec_IntEntry( vDriRefs, Aig_ObjFaninId0(pObj) ) >= 1 );
+ if ( Vec_IntEntry( vDriRefs, Aig_ObjFaninId0(pObj) ) != 1 )
+ continue;
+ if ( !Aig_ObjFaninC0(pObj) )
+ continue;
+ bVar = Cudd_bddIthVar( dd, Aig_ObjFaninId0(pObj) );
+ bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bCube );
+ dd->TimeStop = TimeStop;
+ return bCube;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute the last partition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdManager * Llb_DriverLastPartition( Aig_Man_t * p, Vec_Int_t * vVarsNs, abctime TimeTarget )
+{
+// int fVerbose = 1;
+ DdManager * dd;
+ DdNode * bVar1, * bVar2, * bProd, * bRes, * bTemp;
+ Aig_Obj_t * pObj;
+ int i;
+ dd = Cudd_Init( Aig_ManObjNumMax(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+ dd->TimeStop = TimeTarget;
+ bRes = Cudd_ReadOne(dd); Cudd_Ref( bRes );
+
+ // mark the duplicated flop inputs
+ Aig_ManForEachObjVec( vVarsNs, p, pObj, i )
+ {
+ if ( !Saig_ObjIsLi(p, pObj) )
+ continue;
+ bVar1 = Cudd_bddIthVar( dd, Aig_ObjId(pObj) );
+ bVar2 = Cudd_bddIthVar( dd, Aig_ObjFaninId0(pObj) );
+ if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) )
+ bVar2 = Cudd_ReadOne(dd);
+ bVar2 = Cudd_NotCond( bVar2, Aig_ObjFaninC0(pObj) );
+ bProd = Cudd_bddXnor( dd, bVar1, bVar2 ); Cudd_Ref( bProd );
+// bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); Cudd_Ref( bRes );
+// bRes = Extra_bddAndTime( dd, bTemp = bRes, bProd, TimeTarget );
+ bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bProd );
+ return NULL;
+ }
+ Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bProd );
+ }
+
+/*
+ Saig_ManForEachLi( p, pObj, i )
+ printf( "%d ", Aig_ObjId(pObj) );
+ printf( "\n" );
+ Saig_ManForEachLi( p, pObj, i )
+ printf( "%c%d ", Aig_ObjFaninC0(pObj)? '-':'+', Aig_ObjFaninId0(pObj) );
+ printf( "\n" );
+*/
+ Cudd_AutodynDisable( dd );
+// Cudd_RecursiveDeref( dd, bRes );
+// Extra_StopManager( dd );
+ dd->bFunc = bRes;
+ dd->TimeStop = 0;
+ return dd;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/bdd/llb/llb2Dump.c b/src/bdd/llb/llb2Dump.c
new file mode 100644
index 00000000..74f07922
--- /dev/null
+++ b/src/bdd/llb/llb2Dump.c
@@ -0,0 +1,104 @@
+/**CFile****************************************************************
+
+ FileName [llb2Dump.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Dumps the BDD of reached states into a file.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb2Dump.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Returns a dummy name.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Llb_ManGetDummyName( char * pPrefix, int Num, int nDigits )
+{
+ static char Buffer[2000];
+ sprintf( Buffer, "%s%0*d", pPrefix, nDigits, Num );
+ return Buffer;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes reached state BDD into a BLIF file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManDumpReached( DdManager * ddG, DdNode * bReached, char * pModel, char * pFileName )
+{
+ FILE * pFile;
+ Vec_Ptr_t * vNamesIn, * vNamesOut;
+ char * pName;
+ int i, nDigits;
+ // reorder the BDD
+ Cudd_ReduceHeap( ddG, CUDD_REORDER_SYMM_SIFT, 1 );
+
+ // create input names
+ nDigits = Abc_Base10Log( Cudd_ReadSize(ddG) );
+ vNamesIn = Vec_PtrAlloc( Cudd_ReadSize(ddG) );
+ for ( i = 0; i < Cudd_ReadSize(ddG); i++ )
+ {
+ pName = Llb_ManGetDummyName( "ff", i, nDigits );
+ Vec_PtrPush( vNamesIn, Extra_UtilStrsav(pName) );
+ }
+ // create output names
+ vNamesOut = Vec_PtrAlloc( 1 );
+ Vec_PtrPush( vNamesOut, Extra_UtilStrsav("Reached") );
+
+ // write the file
+ pFile = fopen( pFileName, "wb" );
+ Cudd_DumpBlif( ddG, 1, &bReached, (char **)Vec_PtrArray(vNamesIn), (char **)Vec_PtrArray(vNamesOut), pModel, pFile, 0 );
+ fclose( pFile );
+
+ // cleanup
+ Vec_PtrForEachEntry( char *, vNamesIn, pName, i )
+ ABC_FREE( pName );
+ Vec_PtrForEachEntry( char *, vNamesOut, pName, i )
+ ABC_FREE( pName );
+ Vec_PtrFree( vNamesIn );
+ Vec_PtrFree( vNamesOut );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/bdd/llb/llb2Flow.c b/src/bdd/llb/llb2Flow.c
new file mode 100644
index 00000000..64db32b3
--- /dev/null
+++ b/src/bdd/llb/llb2Flow.c
@@ -0,0 +1,1376 @@
+/**CFile****************************************************************
+
+ FileName [llb2Flow.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Flow computation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb2Flow.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int Llb_ObjSetPath( Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { pObj->pData = (void *)pNext; return 1; }
+static inline Aig_Obj_t * Llb_ObjGetPath( Aig_Obj_t * pObj ) { return (Aig_Obj_t *)pObj->pData; }
+static inline Aig_Obj_t * Llb_ObjGetFanoutPath( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+ Aig_Obj_t * pFanout;
+ int i, iFanout = -1;
+ assert( Llb_ObjGetPath(pObj) );
+ Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i )
+ if ( Llb_ObjGetPath(pFanout) == pObj )
+ return pFanout;
+ return NULL;
+}
+
+extern Vec_Ptr_t * Llb_ManCutSupp( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+ Synopsis [For each cut, returns PIs that can be quantified.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManCutSupps( Aig_Man_t * p, Vec_Ptr_t * vResult )
+{
+ Vec_Ptr_t * vSupps, * vOne, * vLower, * vUpper;
+ int i;
+ vSupps = Vec_PtrAlloc( 100 );
+ Vec_PtrPush( vSupps, Vec_PtrAlloc(0) );
+ vLower = (Vec_Ptr_t *)Vec_PtrEntry( vResult, 0 );
+ Vec_PtrForEachEntryStart( Vec_Ptr_t *, vResult, vUpper, i, 1 )
+ {
+ vOne = Llb_ManCutSupp( p, vLower, vUpper );
+ Vec_PtrPush( vSupps, vOne );
+ vLower = vUpper;
+ }
+ assert( Vec_PtrSize(vSupps) == Vec_PtrSize(vResult) );
+ return vSupps;
+}
+
+/**Function*************************************************************
+
+ Synopsis [For each cut, returns PIs that can be quantified.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManCutMap( Aig_Man_t * p, Vec_Ptr_t * vResult, Vec_Ptr_t * vSupps )
+{
+ int fShowMatrix = 1;
+ Vec_Ptr_t * vMaps, * vOne;
+ Vec_Int_t * vMap, * vPrev, * vNext;
+ Aig_Obj_t * pObj;
+ int * piFirst, * piLast;
+ int i, k, CounterPlus, CounterMinus, Counter;
+
+ vMaps = Vec_PtrAlloc( 100 );
+ Vec_PtrForEachEntry( Vec_Ptr_t *, vResult, vOne, i )
+ {
+ vMap = Vec_IntStart( Aig_ManObjNumMax(p) );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vOne, pObj, k )
+ {
+ if ( !Saig_ObjIsPi(p, pObj) )
+ Vec_IntWriteEntry( vMap, pObj->Id, 1 );
+// else
+//printf( "*" );
+//printf( "%d ", pObj->Id );
+ }
+ Vec_PtrPush( vMaps, vMap );
+//printf( "\n" );
+ }
+ Vec_PtrPush( vMaps, Vec_IntStart( Aig_ManObjNumMax(p) ) );
+ assert( Vec_PtrSize(vMaps) == Vec_PtrSize(vResult)+1 );
+
+ // collect the first and last PIs
+ piFirst = ABC_ALLOC( int, Saig_ManPiNum(p) );
+ piLast = ABC_ALLOC( int, Saig_ManPiNum(p) );
+ Saig_ManForEachPi( p, pObj, i )
+ piFirst[i] = piLast[i] = -1;
+ Vec_PtrForEachEntry( Vec_Ptr_t *, vSupps, vOne, i )
+ {
+ Vec_PtrForEachEntry( Aig_Obj_t *, vOne, pObj, k )
+ {
+ if ( !Saig_ObjIsPi(p, pObj) )
+ continue;
+ if ( piFirst[Aig_ObjCioId(pObj)] == -1 )
+ piFirst[Aig_ObjCioId(pObj)] = i;
+ piLast[Aig_ObjCioId(pObj)] = i;
+ }
+ }
+ // PIs feeding into the flops should be extended to the last frame
+ Saig_ManForEachLi( p, pObj, i )
+ {
+ if ( !Saig_ObjIsPi(p, Aig_ObjFanin0(pObj)) )
+ continue;
+ piLast[Aig_ObjCioId(Aig_ObjFanin0(pObj))] = Vec_PtrSize(vMaps)-1;
+ }
+
+ // set the PI map
+ Saig_ManForEachPi( p, pObj, i )
+ {
+ if ( piFirst[i] == -1 )
+ continue;
+ if ( piFirst[i] == piLast[i] )
+ {
+ vMap = (Vec_Int_t *)Vec_PtrEntry( vMaps, piFirst[i] );
+ Vec_IntWriteEntry( vMap, pObj->Id, 2 );
+ continue;
+ }
+
+ // set support for all in between
+ for ( k = piFirst[i]; k <= piLast[i]; k++ )
+ {
+ vMap = (Vec_Int_t *)Vec_PtrEntry( vMaps, k );
+ Vec_IntWriteEntry( vMap, pObj->Id, 1 );
+ }
+ }
+ ABC_FREE( piFirst );
+ ABC_FREE( piLast );
+
+
+ // find all that will appear here
+ Counter = Aig_ManRegNum(p);
+ printf( "%d ", Counter );
+ Vec_PtrForEachEntryStart( Vec_Int_t *, vMaps, vMap, i, 1 )
+ {
+ vPrev = (Vec_Int_t *)Vec_PtrEntry( vMaps, i-1 );
+ vNext = (i == Vec_PtrSize(vMaps)-1)? NULL: (Vec_Int_t *)Vec_PtrEntry( vMaps, i+1 );
+
+ CounterPlus = CounterMinus = 0;
+ Aig_ManForEachObj( p, pObj, k )
+ {
+ if ( Saig_ObjIsPi(p, pObj) )
+ {
+ if ( Vec_IntEntry(vPrev, k) == 0 && Vec_IntEntry(vMap, k) == 1 )
+ CounterPlus++;
+ if ( Vec_IntEntry(vMap, k) == 1 && (vNext == NULL || Vec_IntEntry(vNext, k) == 0) )
+ CounterMinus++;
+ }
+ else
+ {
+ if ( Vec_IntEntry(vPrev, k) == 0 && Vec_IntEntry(vMap, k) == 1 )
+ CounterPlus++;
+ if ( Vec_IntEntry(vPrev, k) == 1 && Vec_IntEntry(vMap, k) == 0 )
+ CounterMinus++;
+ }
+ }
+ Counter = Counter + CounterPlus - CounterMinus;
+ printf( "%d=%d ", i, Counter );
+ }
+ printf( "\n" );
+
+ if ( !fShowMatrix )
+ return vMaps;
+ Aig_ManForEachObj( p, pObj, i )
+ {
+ if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) )
+ continue;
+ Vec_PtrForEachEntry( Vec_Int_t *, vMaps, vMap, k )
+ if ( Vec_IntEntry(vMap, i) )
+ break;
+ if ( k == Vec_PtrSize(vMaps) )
+ continue;
+ printf( "Obj = %4d : ", i );
+ if ( Saig_ObjIsPi(p,pObj) )
+ printf( "pi " );
+ else if ( Saig_ObjIsLo(p,pObj) )
+ printf( "lo " );
+ else if ( Aig_ObjIsNode(pObj) )
+ printf( "and " );
+
+ Vec_PtrForEachEntry( Vec_Int_t *, vMaps, vMap, k )
+ printf( "%d", Vec_IntEntry(vMap, i) );
+ printf( "\n" );
+ }
+ return vMaps;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of PIs in the cut]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManCutPiNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut )
+{
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i )
+ if ( Saig_ObjIsPi(p,pObj) )
+ Counter++;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of LOs in the cut]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManCutLoNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut )
+{
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i )
+ if ( Saig_ObjIsLo(p,pObj) )
+ Counter++;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of LIs in the cut]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManCutLiNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut )
+{
+ Aig_Obj_t * pFanout;
+ Aig_Obj_t * pObj;
+ int i, k, iFanout = -1, Counter = 0;
+ Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i )
+ {
+ if ( Aig_ObjIsCi(pObj) )
+ continue;
+ Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, k )
+ {
+ if ( Saig_ObjIsLi(p, pFanout) )
+ {
+ Counter++;
+ break;
+ }
+ }
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes volume of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManCutVolume_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ return 0;
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ assert( Aig_ObjIsNode(pObj) );
+ return 1 + Llb_ManCutVolume_rec(p, Aig_ObjFanin0(pObj)) +
+ Llb_ManCutVolume_rec(p, Aig_ObjFanin1(pObj));
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes volume of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManCutVolume( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper )
+{
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ // mark the lower cut with the traversal ID
+ Aig_ManIncrementTravId(p);
+ Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+ Aig_ObjSetTravIdCurrent( p, pObj );
+ // count the upper cut
+ Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i )
+ Counter += Llb_ManCutVolume_rec( p, pObj );
+ return Counter;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes volume of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManCutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ return;
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ assert( Aig_ObjIsNode(pObj) );
+ Llb_ManCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes);
+ Llb_ManCutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes);
+ Vec_PtrPush( vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes volume of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper )
+{
+ Vec_Ptr_t * vNodes;
+ Aig_Obj_t * pObj;
+ int i;
+ // mark the lower cut with the traversal ID
+ Aig_ManIncrementTravId(p);
+ Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+ Aig_ObjSetTravIdCurrent( p, pObj );
+ // count the upper cut
+ vNodes = Vec_PtrAlloc( 100 );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i )
+ Llb_ManCutNodes_rec( p, pObj, vNodes );
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes volume of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManCutSupp( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper )
+{
+ Vec_Ptr_t * vNodes, * vSupp;
+ Aig_Obj_t * pObj;
+ int i;
+ vNodes = Llb_ManCutNodes( p, vLower, vUpper );
+ // mark support of the nodes
+ Aig_ManIncrementTravId(p);
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+ {
+ assert( Aig_ObjIsNode(pObj) );
+ Aig_ObjSetTravIdCurrent( p, Aig_ObjFanin0(pObj) );
+ Aig_ObjSetTravIdCurrent( p, Aig_ObjFanin1(pObj) );
+ }
+ Vec_PtrFree( vNodes );
+ // collect the support nodes
+ vSupp = Vec_PtrAlloc( 100 );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ Vec_PtrPush( vSupp, pObj );
+ return vSupp;
+
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes volume of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManCutRange( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper )
+{
+ Vec_Ptr_t * vRange;
+ Aig_Obj_t * pObj;
+ int i;
+ // mark the lower cut with the traversal ID
+ Aig_ManIncrementTravId(p);
+ Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+ Aig_ObjSetTravIdCurrent( p, pObj );
+ // collect the upper ones that are not marked
+ vRange = Vec_PtrAlloc( 100 );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i )
+ if ( !Aig_ObjIsTravIdCurrent(p, pObj) )
+ Vec_PtrPush( vRange, pObj );
+ return vRange;
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints the given cluster.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManCutPrint( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper )
+{
+ Vec_Ptr_t * vSupp, * vRange;
+ int Pis, Ffs, And;
+
+ Pis = Llb_ManCutPiNum(p, vLower);
+ Ffs = Llb_ManCutLoNum(p, vLower);
+ And = Vec_PtrSize(vLower) - Pis - Ffs;
+ printf( "Leaf: %3d=%3d+%3d+%3d ", Vec_PtrSize(vLower), Pis, Ffs, And );
+
+ Pis = Llb_ManCutPiNum(p, vUpper);
+ Ffs = Llb_ManCutLiNum(p, vUpper);
+ And = Vec_PtrSize(vUpper) - Pis - Ffs;
+ printf( "Root: %3d=%3d+%3d+%3d ", Vec_PtrSize(vUpper), Pis, Ffs, And );
+
+ vSupp = Llb_ManCutSupp( p, vLower, vUpper );
+ Pis = Llb_ManCutPiNum(p, vSupp);
+ Ffs = Llb_ManCutLoNum(p, vSupp);
+ And = Vec_PtrSize(vSupp) - Pis - Ffs;
+ printf( "Supp: %3d=%3d+%3d+%3d ", Vec_PtrSize(vSupp), Pis, Ffs, And );
+
+ vRange = Llb_ManCutRange( p, vLower, vUpper );
+ Pis = Llb_ManCutPiNum(p, vRange);
+ Ffs = Llb_ManCutLiNum(p, vRange);
+ And = Vec_PtrSize(vRange) - Pis - Ffs;
+ printf( "Range: %3d=%3d+%3d+%3d ", Vec_PtrSize(vRange), Pis, Ffs, And );
+
+ printf( "S =%3d. V =%3d.\n",
+ Vec_PtrSize(vSupp)+Vec_PtrSize(vRange), Llb_ManCutVolume(p, vLower, vUpper) );
+ Vec_PtrFree( vSupp );
+ Vec_PtrFree( vRange );
+/*
+ {
+ Aig_Obj_t * pObj;
+ int i;
+ printf( "Lower: " );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+ printf( " %d", pObj->Id );
+ printf( " " );
+ printf( "Upper: " );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i )
+ printf( " %d", pObj->Id );
+ printf( "\n" );
+ }
+*/
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the given cluster.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManResultPrint( Aig_Man_t * p, Vec_Ptr_t * vResult )
+{
+ Vec_Ptr_t * vLower, * vUpper = NULL;
+ int i;
+ Vec_PtrForEachEntryReverse( Vec_Ptr_t *, vResult, vLower, i )
+ {
+ if ( i < Vec_PtrSize(vResult) - 1 )
+ Llb_ManCutPrint( p, vLower, vUpper );
+ vUpper = vLower;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Tries to find an augmenting path originating in this node.]
+
+ Description [This procedure works for directed graphs only!]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManFlowBwdPath2_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+ Aig_Obj_t * pFanout;
+ assert( Aig_ObjIsNode(pObj) || Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) );
+ // skip visited nodes
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ return 0;
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ // process node without flow
+ if ( !Llb_ObjGetPath(pObj) )
+ {
+ // start the path if we reached a terminal node
+ if ( pObj->fMarkA )
+ return Llb_ObjSetPath( pObj, (Aig_Obj_t *)1 );
+ // explore the fanins
+// Abc_ObjForEachFanin( pObj, pFanin, i )
+// if ( Abc_NtkMaxFlowBwdPath2_rec(pFanin) )
+// return Abc_ObjSetPath( pObj, pFanin );
+ if ( Aig_ObjIsNode(pObj) )
+ {
+ if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ) )
+ return Llb_ObjSetPath( pObj, Aig_ObjFanin0(pObj) );
+ if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ) )
+ return Llb_ObjSetPath( pObj, Aig_ObjFanin1(pObj) );
+ }
+ return 0;
+ }
+ // pObj has flow - find the fanout with flow
+ pFanout = Llb_ObjGetFanoutPath( p, pObj );
+ if ( pFanout == NULL )
+ return 0;
+ // go through the fanins of the fanout with flow
+// Abc_ObjForEachFanin( pFanout, pFanin, i )
+// if ( Abc_NtkMaxFlowBwdPath2_rec( pFanin ) )
+// return Abc_ObjSetPath( pFanout, pFanin );
+ assert( Aig_ObjIsNode(pFanout) );
+ if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pFanout) ) )
+ return Llb_ObjSetPath( pFanout, Aig_ObjFanin0(pFanout) );
+ if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pFanout) ) )
+ return Llb_ObjSetPath( pFanout, Aig_ObjFanin1(pFanout) );
+ // try the fanout
+ if ( Llb_ManFlowBwdPath2_rec( p, pFanout ) )
+ return Llb_ObjSetPath( pFanout, NULL );
+ return 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Cleans markB.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManFlowLabelTfi_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ return;
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) )
+ return;
+ assert( Aig_ObjIsNode(pObj) );
+ Llb_ManFlowLabelTfi_rec( p, Aig_ObjFanin0(pObj) );
+ Llb_ManFlowLabelTfi_rec( p, Aig_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManFlowUpdateCut( Aig_Man_t * p, Vec_Ptr_t * vMinCut )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ // label the TFI of the cut nodes
+ Aig_ManIncrementTravId(p);
+ Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i )
+ Llb_ManFlowLabelTfi_rec( p, pObj );
+ // collect labeled fanins of non-labeled nodes
+ Vec_PtrClear( vMinCut );
+ Aig_ManIncrementTravId(p);
+ Aig_ManForEachObj( p, pObj, i )
+ {
+ if ( !Aig_ObjIsCo(pObj) && !Aig_ObjIsNode(pObj) )
+ continue;
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) || Aig_ObjIsTravIdPrevious(p, pObj) )
+ continue;
+ if ( Aig_ObjIsTravIdPrevious(p, Aig_ObjFanin0(pObj)) )
+ {
+ Aig_ObjSetTravIdCurrent(p, Aig_ObjFanin0(pObj));
+ Vec_PtrPush( vMinCut, Aig_ObjFanin0(pObj) );
+ }
+ if ( Aig_ObjIsNode(pObj) && Aig_ObjIsTravIdPrevious(p, Aig_ObjFanin1(pObj)) )
+ {
+ Aig_ObjSetTravIdCurrent(p, Aig_ObjFanin1(pObj));
+ Vec_PtrPush( vMinCut, Aig_ObjFanin1(pObj) );
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find minimum-volume minumum cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManFlowMinCut( Aig_Man_t * p )
+{
+ Vec_Ptr_t * vMinCut;
+ Aig_Obj_t * pObj;
+ int i;
+ // collect the cut nodes
+ vMinCut = Vec_PtrAlloc( Aig_ManRegNum(p) );
+ Aig_ManForEachObj( p, pObj, i )
+ {
+ // node without flow is not a cut node
+ if ( !Llb_ObjGetPath(pObj) )
+ continue;
+ // unvisited node is below the cut
+ if ( !Aig_ObjIsTravIdCurrent(p, pObj) )
+ continue;
+ // add terminal with flow or node whose path is not visited
+ if ( pObj->fMarkA || !Aig_ObjIsTravIdCurrent( p, Llb_ObjGetPath(pObj) ) )
+ Vec_PtrPush( vMinCut, pObj );
+ }
+ return vMinCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verifies the min-cut is indeed a cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManFlowVerifyCut_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+ // skip visited nodes
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ return 1;
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ // visit the node
+ if ( Aig_ObjIsConst1(pObj) )
+ return 1;
+ if ( Aig_ObjIsCi(pObj) )
+ return 0;
+ // explore the fanins
+ assert( Aig_ObjIsNode(pObj) );
+ if ( !Llb_ManFlowVerifyCut_rec(p, Aig_ObjFanin0(pObj)) )
+ return 0;
+ if ( !Llb_ManFlowVerifyCut_rec(p, Aig_ObjFanin1(pObj)) )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verifies the min-cut is indeed a cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManFlowVerifyCut( Aig_Man_t * p, Vec_Ptr_t * vMinCut )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ // mark the cut with the current traversal ID
+ Aig_ManIncrementTravId(p);
+ Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i )
+ Aig_ObjSetTravIdCurrent( p, pObj );
+ // search from the latches for a path to the COs/CIs
+ Saig_ManForEachLi( p, pObj, i )
+ {
+ if ( !Llb_ManFlowVerifyCut_rec( p, Aig_ObjFanin0(pObj) ) )
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implementation of max-flow/min-cut computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManFlow( Aig_Man_t * p, Vec_Ptr_t * vSources, int * pnFlow )
+{
+ Vec_Ptr_t * vMinCut;
+ Aig_Obj_t * pObj;
+ int Flow, FlowCur, RetValue, i;
+ // find the max-flow
+ Flow = 0;
+ Aig_ManCleanData( p );
+ Aig_ManIncrementTravId(p);
+ Vec_PtrForEachEntry( Aig_Obj_t *, vSources, pObj, i )
+ {
+ assert( !pObj->fMarkA && pObj->fMarkB );
+ if ( !Aig_ObjFanin0(pObj)->fMarkB )
+ {
+ FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) );
+ Flow += FlowCur;
+ if ( FlowCur )
+ Aig_ManIncrementTravId(p);
+ }
+ if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB )
+ {
+ FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) );
+ Flow += FlowCur;
+ if ( FlowCur )
+ Aig_ManIncrementTravId(p);
+ }
+ }
+ if ( pnFlow )
+ *pnFlow = Flow;
+
+ // mark the nodes reachable from the latches
+ Aig_ManIncrementTravId(p);
+ Vec_PtrForEachEntry( Aig_Obj_t *, vSources, pObj, i )
+ {
+ assert( !pObj->fMarkA && pObj->fMarkB );
+ if ( !Aig_ObjFanin0(pObj)->fMarkB )
+ {
+ RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) );
+ assert( RetValue == 0 );
+ }
+ if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB )
+ {
+ RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) );
+ assert( RetValue == 0 );
+ }
+ }
+
+ // find the min-cut with the smallest volume
+ vMinCut = Llb_ManFlowMinCut( p );
+ assert( Vec_PtrSize(vMinCut) == Flow );
+ // verify the cut
+ if ( !Llb_ManFlowVerifyCut(p, vMinCut) )
+ printf( "Llb_ManFlow() error! The computed min-cut is not a cut!\n" );
+// Llb_ManFlowPrintCut( p, vMinCut );
+ return vMinCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implementation of max-flow/min-cut computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManFlowCompute( Aig_Man_t * p )
+{
+ Vec_Ptr_t * vMinCut;
+ Aig_Obj_t * pObj;
+ int Flow, FlowCur, RetValue, i;
+ // find the max-flow
+ Flow = 0;
+ Aig_ManCleanData( p );
+ Aig_ManIncrementTravId(p);
+ Aig_ManForEachObj( p, pObj, i )
+ {
+ if ( !pObj->fMarkB )
+ continue;
+ assert( !pObj->fMarkA );
+ if ( !Aig_ObjFanin0(pObj)->fMarkB )
+ {
+//printf( "%d ", Aig_ObjFanin0(pObj)->Id );
+ FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) );
+ Flow += FlowCur;
+ if ( FlowCur )
+ Aig_ManIncrementTravId(p);
+ }
+ if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB )
+ {
+//printf( "%d ", Aig_ObjFanin1(pObj)->Id );
+ FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) );
+ Flow += FlowCur;
+ if ( FlowCur )
+ Aig_ManIncrementTravId(p);
+ }
+ }
+//printf( "\n" );
+
+ // mark the nodes reachable from the latches
+ Aig_ManIncrementTravId(p);
+ Aig_ManForEachObj( p, pObj, i )
+ {
+ if ( !pObj->fMarkB )
+ continue;
+ assert( !pObj->fMarkA );
+ if ( !Aig_ObjFanin0(pObj)->fMarkB )
+ {
+ RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) );
+ assert( RetValue == 0 );
+ }
+ if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB )
+ {
+ RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) );
+ assert( RetValue == 0 );
+ }
+ }
+ // find the min-cut with the smallest volume
+ vMinCut = Llb_ManFlowMinCut( p );
+ assert( Vec_PtrSize(vMinCut) == Flow );
+//printf( "%d ", Vec_PtrSize(vMinCut) );
+ Llb_ManFlowUpdateCut( p, vMinCut );
+//printf( "%d ", Vec_PtrSize(vMinCut) );
+ // verify the cut
+ if ( !Llb_ManFlowVerifyCut(p, vMinCut) )
+ printf( "Llb_ManFlow() error! The computed min-cut is not a cut!\n" );
+// Llb_ManFlowPrintCut( p, vMinCut );
+ return vMinCut;
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Cleans markB.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManFlowCleanMarkB_rec( Aig_Obj_t * pObj )
+{
+ if ( pObj->fMarkB == 0 )
+ return;
+ pObj->fMarkB = 0;
+ assert( Aig_ObjIsNode(pObj) );
+ Llb_ManFlowCleanMarkB_rec( Aig_ObjFanin0(pObj) );
+ Llb_ManFlowCleanMarkB_rec( Aig_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Cleans markB.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManFlowSetMarkA_rec( Aig_Obj_t * pObj )
+{
+ if ( pObj->fMarkA )
+ return;
+ pObj->fMarkA = 1;
+ if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) )
+ return;
+ assert( Aig_ObjIsNode(pObj) );
+ Llb_ManFlowSetMarkA_rec( Aig_ObjFanin0(pObj) );
+ Llb_ManFlowSetMarkA_rec( Aig_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares flow computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManFlowPrepareCut( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ // reset marks
+ Aig_ManForEachObj( p, pObj, i )
+ {
+ pObj->fMarkA = 0;
+ pObj->fMarkB = 1;
+ }
+ // clean PIs and const
+ Aig_ManConst1(p)->fMarkB = 0;
+ Aig_ManForEachCi( p, pObj, i )
+ pObj->fMarkB = 0;
+ // clean upper cut
+//printf( "Upper: ");
+ Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i )
+ {
+ Llb_ManFlowCleanMarkB_rec( pObj );
+//printf( "%d ", pObj->Id );
+ }
+//printf( "\n" );
+ // set lower cut
+//printf( "Lower: ");
+ Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+ {
+//printf( "%d ", pObj->Id );
+ assert( pObj->fMarkB == 0 );
+ Llb_ManFlowSetMarkA_rec( pObj );
+ }
+//printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares flow computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManFlowUnmarkCone( Aig_Man_t * p, Vec_Ptr_t * vCone )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Vec_PtrForEachEntry( Aig_Obj_t *, vCone, pObj, i )
+ {
+ assert( Aig_ObjIsNode(pObj) );
+ assert( pObj->fMarkB == 1 );
+ pObj->fMarkB = 0;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManFlowCollectAndMarkCone_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vCone )
+{
+ Aig_Obj_t * pFanout;
+ int i, iFanout = -1;
+ if ( Saig_ObjIsLi(p, pObj) )
+ return;
+ if ( pObj->fMarkB )
+ return;
+ if ( pObj->fMarkA == 0 )
+ {
+ assert( Aig_ObjIsNode(pObj) );
+ pObj->fMarkB = 1;
+ if ( Aig_ObjIsNode(pObj) )
+ Vec_PtrPush( vCone, pObj );
+ }
+ Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i )
+ Llb_ManFlowCollectAndMarkCone_rec( p, pFanout, vCone );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the cone.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManFlowCollectAndMarkCone( Aig_Man_t * p, Vec_Ptr_t * vStarts, Vec_Ptr_t * vCone )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Vec_PtrClear( vCone );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vStarts, pObj, i )
+ {
+ assert( pObj->fMarkA && !pObj->fMarkB );
+ Llb_ManFlowCollectAndMarkCone_rec( p, pObj, vCone );
+ }
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds balanced cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManComputeCutLo( Aig_Man_t * p )
+{
+ Vec_Ptr_t * vMinCut;
+ Aig_Obj_t * pObj;
+ int i;
+ vMinCut = Vec_PtrAlloc( 100 );
+ Aig_ManForEachCi( p, pObj, i )
+ Vec_PtrPush( vMinCut, pObj );
+ return vMinCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds balanced cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManComputeCutLi( Aig_Man_t * p )
+{
+ Vec_Ptr_t * vMinCut;
+ Aig_Obj_t * pObj;
+ int i;
+ assert( Saig_ManPoNum(p) == 0 );
+ vMinCut = Vec_PtrAlloc( 100 );
+ Aig_ManIncrementTravId(p);
+ Saig_ManForEachLi( p, pObj, i )
+ {
+ pObj = Aig_ObjFanin0(pObj);
+ if ( Aig_ObjIsConst1(pObj) )
+ continue;
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ continue;
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ Vec_PtrPush( vMinCut, pObj );
+ }
+ return vMinCut;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds balanced cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManFlowGetObjSet( Aig_Man_t * p, Vec_Ptr_t * vLower, int iStart, int nSize, Vec_Ptr_t * vSet )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Vec_PtrClear( vSet );
+ for ( i = 0; i < nSize; i++ )
+ {
+ pObj = (Aig_Obj_t *)Vec_PtrEntry( vLower, (iStart + i) % Vec_PtrSize(vLower) );
+ Vec_PtrPush( vSet, pObj );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds balanced cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManFlowFindBestCut( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, int Num )
+{
+ int nVolMin = Aig_ManNodeNum(p) / Num / 2;
+ Vec_Ptr_t * vMinCut;
+ Vec_Ptr_t * vCone, * vSet;
+ Aig_Obj_t * pObj;
+ int i, s, Vol, VolLower, VolUpper, VolCmp;
+ int iBest = -1, iMinCut = ABC_INFINITY, iVolBest = 0;
+
+ Vol = Llb_ManCutVolume( p, vLower, vUpper );
+ assert( Vol > nVolMin );
+ VolCmp = Abc_MinInt( nVolMin, Vol - nVolMin );
+ vCone = Vec_PtrAlloc( 100 );
+ vSet = Vec_PtrAlloc( 100 );
+ Llb_ManFlowPrepareCut( p, vLower, vUpper );
+ for ( s = 1; s < Aig_ManRegNum(p); s += 5 )
+ {
+ Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+ {
+ Llb_ManFlowGetObjSet( p, vLower, i, s, vSet );
+ Llb_ManFlowCollectAndMarkCone( p, vSet, vCone );
+ if ( Vec_PtrSize(vCone) == 0 )
+ continue;
+ vMinCut = Llb_ManFlowCompute( p );
+ Llb_ManFlowUnmarkCone( p, vCone );
+
+ VolLower = Llb_ManCutVolume( p, vLower, vMinCut );
+ VolUpper = Llb_ManCutVolume( p, vMinCut, vUpper );
+ Vol = Abc_MinInt( VolLower, VolUpper );
+ if ( Vol >= VolCmp && (iMinCut == -1 ||
+ iMinCut > Vec_PtrSize(vMinCut) ||
+ (iMinCut == Vec_PtrSize(vMinCut) && iVolBest < Vol)) )
+ {
+ iBest = i;
+ iMinCut = Vec_PtrSize(vMinCut);
+ iVolBest = Vol;
+ }
+ Vec_PtrFree( vMinCut );
+ }
+ if ( iBest >= 0 )
+ break;
+ }
+ if ( iBest == -1 )
+ {
+ // cleanup
+ Vec_PtrFree( vCone );
+ Vec_PtrFree( vSet );
+ return NULL;
+ }
+ // get the best cut
+ assert( iBest >= 0 );
+ Llb_ManFlowGetObjSet( p, vLower, iBest, s, vSet );
+ Llb_ManFlowCollectAndMarkCone( p, vSet, vCone );
+ vMinCut = Llb_ManFlowCompute( p );
+ Llb_ManFlowUnmarkCone( p, vCone );
+ // cleanup
+ Vec_PtrFree( vCone );
+ Vec_PtrFree( vSet );
+ return vMinCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds balanced cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManComputeCuts( Aig_Man_t * p, int Num, int fVerbose, int fVeryVerbose )
+{
+ int nVolMax = Aig_ManNodeNum(p) / Num;
+ Vec_Ptr_t * vResult, * vMinCut = NULL, * vLower, * vUpper;
+ int i, k, nVol;
+ abctime clk = Abc_Clock();
+ vResult = Vec_PtrAlloc( 100 );
+ Vec_PtrPush( vResult, Llb_ManComputeCutLo(p) );
+ Vec_PtrPush( vResult, Llb_ManComputeCutLi(p) );
+ while ( 1 )
+ {
+ // find a place to insert new cut
+ vLower = (Vec_Ptr_t *)Vec_PtrEntry( vResult, 0 );
+ Vec_PtrForEachEntryStart( Vec_Ptr_t *, vResult, vUpper, i, 1 )
+ {
+ nVol = Llb_ManCutVolume( p, vLower, vUpper );
+ if ( nVol <= nVolMax )
+ {
+ vLower = vUpper;
+ continue;
+ }
+
+ if ( fVeryVerbose )
+ Llb_ManCutPrint( p, vLower, vUpper );
+ vMinCut = Llb_ManFlowFindBestCut( p, vLower, vUpper, Num );
+ if ( vMinCut == NULL )
+ {
+ if ( fVeryVerbose )
+ printf( "Could not break the cut.\n" );
+ if ( fVeryVerbose )
+ printf( "\n" );
+ vLower = vUpper;
+ continue;
+ }
+
+ if ( fVeryVerbose )
+ Llb_ManCutPrint( p, vMinCut, vUpper );
+ if ( fVeryVerbose )
+ Llb_ManCutPrint( p, vLower, vMinCut );
+ if ( fVeryVerbose )
+ printf( "\n" );
+
+ break;
+ }
+ if ( i == Vec_PtrSize(vResult) )
+ break;
+ // insert vMinCut before vUpper
+ Vec_PtrPush( vResult, NULL );
+ for ( k = Vec_PtrSize(vResult) - 1; k > i; k-- )
+ Vec_PtrWriteEntry( vResult, k, Vec_PtrEntry(vResult, k-1) );
+ Vec_PtrWriteEntry( vResult, i, vMinCut );
+ }
+ if ( fVerbose )
+ {
+ printf( "Finished computing %d partitions. ", Vec_PtrSize(vResult) - 1 );
+ Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+ Llb_ManResultPrint( p, vResult );
+ }
+ return vResult;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_BddSetDefaultParams( Gia_ParLlb_t * p )
+{
+ memset( p, 0, sizeof(Gia_ParLlb_t) );
+ p->nBddMax = 1000000;
+ p->nIterMax = 10000000;
+ p->nClusterMax = 20;
+ p->nHintDepth = 0;
+ p->HintFirst = 0;
+ p->fUseFlow = 0; // use flow
+ p->nVolumeMax = 100; // max volume
+ p->nVolumeMin = 30; // min volume
+ p->fReorder = 1;
+ p->fIndConstr = 0;
+ p->fUsePivots = 0;
+ p->fCluster = 0;
+ p->fSchedule = 0;
+ p->fVerbose = 0;
+ p->fVeryVerbose = 0;
+ p->fSilent = 0;
+ p->TimeLimit = 0;
+// p->TimeLimit = 0;
+ p->TimeLimitGlo = 0;
+ p->TimeTarget = 0;
+ p->iFrame = -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds balanced cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManMinCutTest( Aig_Man_t * pAig, int Num )
+{
+ extern void Llb_BddConstructTest( Aig_Man_t * p, Vec_Ptr_t * vResult );
+ extern void Llb_BddExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, Vec_Ptr_t * vMaps );
+
+
+// int fVerbose = 1;
+ Gia_ParLlb_t Pars, * pPars = &Pars;
+ Vec_Ptr_t * vResult;//, * vSupps, * vMaps;
+ Aig_Man_t * p;
+
+ Llb_BddSetDefaultParams( pPars );
+
+ p = Aig_ManDupFlopsOnly( pAig );
+//Aig_ManShow( p, 0, NULL );
+ Aig_ManPrintStats( pAig );
+ Aig_ManPrintStats( p );
+ Aig_ManFanoutStart( p );
+
+ vResult = Llb_ManComputeCuts( p, Num, 1, 0 );
+// vSupps = Llb_ManCutSupps( p, vResult );
+// vMaps = Llb_ManCutMap( p, vResult, vSupps );
+
+// Llb_BddExperiment( pAig, p, pPars, vResult, vMaps );
+ Llb_CoreExperiment( pAig, p, pPars, vResult, 0 );
+
+// Vec_VecFree( (Vec_Vec_t *)vMaps );
+// Vec_VecFree( (Vec_Vec_t *)vSupps );
+ Vec_VecFree( (Vec_Vec_t *)vResult );
+
+ Aig_ManFanoutStop( p );
+ Aig_ManCleanMarkAB( p );
+ Aig_ManStop( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/bdd/llb/llb2Image.c b/src/bdd/llb/llb2Image.c
new file mode 100644
index 00000000..e245ba36
--- /dev/null
+++ b/src/bdd/llb/llb2Image.c
@@ -0,0 +1,482 @@
+/**CFile****************************************************************
+
+ FileName [llb2Image.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Computes image using partitioned structure.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb2Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern Vec_Ptr_t * Llb_ManCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper );
+extern Vec_Ptr_t * Llb_ManCutRange( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes supports of the partitions.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ImgSupports( Aig_Man_t * p, Vec_Ptr_t * vDdMans, Vec_Int_t * vStart, Vec_Int_t * vStop, int fAddPis, int fVerbose )
+{
+ Vec_Ptr_t * vSupps;
+ Vec_Int_t * vOne;
+ Aig_Obj_t * pObj;
+ DdManager * dd;
+ DdNode * bSupp, * bTemp;
+ int i, Entry, nSize;
+ nSize = Cudd_ReadSize( (DdManager *)Vec_PtrEntry( vDdMans, 0 ) );
+ vSupps = Vec_PtrAlloc( 100 );
+ // create initial
+ vOne = Vec_IntStart( nSize );
+ Vec_IntForEachEntry( vStart, Entry, i )
+ Vec_IntWriteEntry( vOne, Entry, 1 );
+ Vec_PtrPush( vSupps, vOne );
+ // create intermediate
+ Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i )
+ {
+ vOne = Vec_IntStart( nSize );
+ bSupp = Cudd_Support( dd, dd->bFunc ); Cudd_Ref( bSupp );
+ for ( bTemp = bSupp; bTemp != Cudd_ReadOne(dd); bTemp = cuddT(bTemp) )
+ Vec_IntWriteEntry( vOne, bTemp->index, 1 );
+ Cudd_RecursiveDeref( dd, bSupp );
+ Vec_PtrPush( vSupps, vOne );
+ }
+ // create final
+ vOne = Vec_IntStart( nSize );
+ Vec_IntForEachEntry( vStop, Entry, i )
+ Vec_IntWriteEntry( vOne, Entry, 1 );
+ if ( fAddPis )
+ Saig_ManForEachPi( p, pObj, i )
+ Vec_IntWriteEntry( vOne, Aig_ObjId(pObj), 1 );
+ Vec_PtrPush( vSupps, vOne );
+
+ // print supports
+ assert( nSize == Aig_ManObjNumMax(p) );
+ if ( !fVerbose )
+ return vSupps;
+ Aig_ManForEachObj( p, pObj, i )
+ {
+ int k, Counter = 0;
+ Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k )
+ Counter += Vec_IntEntry(vOne, i);
+ if ( Counter == 0 )
+ continue;
+ printf( "Obj = %4d : ", i );
+ if ( Saig_ObjIsPi(p,pObj) )
+ printf( "pi " );
+ else if ( Saig_ObjIsLo(p,pObj) )
+ printf( "lo " );
+ else if ( Saig_ObjIsLi(p,pObj) )
+ printf( "li " );
+ else if ( Aig_ObjIsNode(pObj) )
+ printf( "and " );
+ Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k )
+ printf( "%d", Vec_IntEntry(vOne, i) );
+ printf( "\n" );
+ }
+ return vSupps;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes quantification schedule.]
+
+ Description [Input array contains supports: 0=starting, ... intermediate...
+ N-1=final. Output arrays contain immediately quantifiable vars (vQuant0)
+ and vars that should be quantified after conjunction (vQuant1).]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ImgSchedule( Vec_Ptr_t * vSupps, Vec_Ptr_t ** pvQuant0, Vec_Ptr_t ** pvQuant1, int fVerbose )
+{
+ Vec_Int_t * vOne;
+ int nVarsAll, Counter, iSupp = -1, Entry, i, k;
+ // start quantification arrays
+ *pvQuant0 = Vec_PtrAlloc( Vec_PtrSize(vSupps) );
+ *pvQuant1 = Vec_PtrAlloc( Vec_PtrSize(vSupps) );
+ Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k )
+ {
+ Vec_PtrPush( *pvQuant0, Vec_IntAlloc(16) );
+ Vec_PtrPush( *pvQuant1, Vec_IntAlloc(16) );
+ }
+ // count how many times each var appears
+ nVarsAll = Vec_IntSize( (Vec_Int_t *)Vec_PtrEntry(vSupps, 0) );
+ for ( i = 0; i < nVarsAll; i++ )
+ {
+ Counter = 0;
+ Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k )
+ if ( Vec_IntEntry(vOne, i) )
+ {
+ iSupp = k;
+ Counter++;
+ }
+ if ( Counter == 0 )
+ continue;
+ if ( Counter == 1 )
+ Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(*pvQuant0, iSupp), i );
+ else // if ( Counter > 1 )
+ Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(*pvQuant1, iSupp), i );
+ }
+
+ if ( fVerbose )
+ for ( i = 0; i < Vec_PtrSize(vSupps); i++ )
+ {
+ printf( "%2d : Quant0 = ", i );
+ Vec_IntForEachEntry( (Vec_Int_t *)Vec_PtrEntry(*pvQuant0, i), Entry, k )
+ printf( "%d ", Entry );
+ printf( "\n" );
+ }
+
+ if ( fVerbose )
+ for ( i = 0; i < Vec_PtrSize(vSupps); i++ )
+ {
+ printf( "%2d : Quant1 = ", i );
+ Vec_IntForEachEntry( (Vec_Int_t *)Vec_PtrEntry(*pvQuant1, i), Entry, k )
+ printf( "%d ", Entry );
+ printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes one partition in a separate BDD manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdManager * Llb_ImgPartition( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, abctime TimeTarget )
+{
+ Vec_Ptr_t * vNodes, * vRange;
+ Aig_Obj_t * pObj;
+ DdManager * dd;
+ DdNode * bBdd0, * bBdd1, * bProd, * bRes, * bTemp;
+ int i;
+
+ dd = Cudd_Init( Aig_ManObjNumMax(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+ dd->TimeStop = TimeTarget;
+
+ Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+ pObj->pData = Cudd_bddIthVar( dd, Aig_ObjId(pObj) );
+
+ vNodes = Llb_ManCutNodes( p, vLower, vUpper );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+ {
+ bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+// pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData );
+// pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeTarget );
+ pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 );
+ if ( pObj->pData == NULL )
+ {
+ Cudd_Quit( dd );
+ Vec_PtrFree( vNodes );
+ return NULL;
+ }
+ Cudd_Ref( (DdNode *)pObj->pData );
+ }
+
+ vRange = Llb_ManCutRange( p, vLower, vUpper );
+ bRes = Cudd_ReadOne(dd); Cudd_Ref( bRes );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vRange, pObj, i )
+ {
+ assert( Aig_ObjIsNode(pObj) );
+ bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), (DdNode *)pObj->pData ); Cudd_Ref( bProd );
+// bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); Cudd_Ref( bRes );
+// bRes = Extra_bddAndTime( dd, bTemp = bRes, bProd, TimeTarget );
+ bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd );
+ if ( bRes == NULL )
+ {
+ Cudd_Quit( dd );
+ Vec_PtrFree( vRange );
+ Vec_PtrFree( vNodes );
+ return NULL;
+ }
+ Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bProd );
+ }
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+
+ Vec_PtrFree( vRange );
+ Vec_PtrFree( vNodes );
+ Cudd_AutodynDisable( dd );
+// Cudd_RecursiveDeref( dd, bRes );
+// Extra_StopManager( dd );
+ dd->bFunc = bRes;
+ dd->TimeStop = 0;
+ return dd;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives positive cube composed of nodes IDs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_ImgComputeCube( Aig_Man_t * pAig, Vec_Int_t * vNodeIds, DdManager * dd )
+{
+ DdNode * bProd, * bTemp;
+ Aig_Obj_t * pObj;
+ int i;
+ abctime TimeStop;
+ TimeStop = dd->TimeStop; dd->TimeStop = 0;
+ bProd = Cudd_ReadOne(dd); Cudd_Ref( bProd );
+ Aig_ManForEachObjVec( vNodeIds, pAig, pObj, i )
+ {
+ bProd = Cudd_bddAnd( dd, bTemp = bProd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)) ); Cudd_Ref( bProd );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bProd );
+ dd->TimeStop = TimeStop;
+ return bProd;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ImgQuantifyFirst( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, Vec_Ptr_t * vQuant0, int fVerbose )
+{
+ DdManager * dd;
+ DdNode * bProd, * bRes, * bTemp;
+ int i;
+ abctime clk = Abc_Clock();
+ Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i )
+ {
+ // remember unquantified ones
+ assert( dd->bFunc2 == NULL );
+ dd->bFunc2 = dd->bFunc; Cudd_Ref( dd->bFunc2 );
+
+ Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+
+ bRes = dd->bFunc;
+ if ( fVerbose )
+ Abc_Print( 1, "Part %2d : Init =%5d. ", i, Cudd_DagSize(bRes) );
+ bProd = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, i+1), dd ); Cudd_Ref( bProd );
+ bRes = Cudd_bddExistAbstract( dd, bTemp = bRes, bProd ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bProd );
+ dd->bFunc = bRes;
+
+ Cudd_AutodynDisable( dd );
+
+ if ( fVerbose )
+ Abc_Print( 1, "Quant =%5d. ", Cudd_DagSize(bRes) );
+ Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+ if ( fVerbose )
+ Abc_Print( 1, "Reo = %5d. ", Cudd_DagSize(bRes) );
+ Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+ if ( fVerbose )
+ Abc_Print( 1, "Reo = %5d. ", Cudd_DagSize(bRes) );
+ if ( fVerbose )
+ Abc_Print( 1, "Supp = %3d. ", Cudd_SupportSize(dd, bRes) );
+ if ( fVerbose )
+ Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ImgQuantifyReset( Vec_Ptr_t * vDdMans )
+{
+ DdManager * dd;
+ int i;
+ Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i )
+ {
+ assert( dd->bFunc2 != NULL );
+ Cudd_RecursiveDeref( dd, dd->bFunc );
+ dd->bFunc = dd->bFunc2;
+ dd->bFunc2 = NULL;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes image of the initial set of states.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_ImgComputeImage( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, DdManager * dd, DdNode * bInit,
+ Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1, Vec_Int_t * vDriRefs,
+ abctime TimeTarget, int fBackward, int fReorder, int fVerbose )
+{
+// int fCheckSupport = 0;
+ DdManager * ddPart;
+ DdNode * bImage, * bGroup, * bCube, * bTemp;
+ int i;
+ abctime clk, clk0 = Abc_Clock();
+
+ bImage = bInit; Cudd_Ref( bImage );
+ if ( fBackward )
+ {
+ // change polarity
+ bCube = Llb_DriverPhaseCube( pAig, vDriRefs, dd ); Cudd_Ref( bCube );
+ bImage = Extra_bddChangePolarity( dd, bTemp = bImage, bCube ); Cudd_Ref( bImage );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bCube );
+ }
+ else
+ {
+ // quantify unique vriables
+ bCube = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, 0), dd ); Cudd_Ref( bCube );
+ bImage = Cudd_bddExistAbstract( dd, bTemp = bImage, bCube );
+ if ( bImage == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bCube );
+ return NULL;
+ }
+ Cudd_Ref( bImage );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bCube );
+ }
+ // perform image computation
+ Vec_PtrForEachEntry( DdManager *, vDdMans, ddPart, i )
+ {
+ clk = Abc_Clock();
+if ( fVerbose )
+printf( " %2d : ", i );
+ // transfer the BDD from the group manager to the main manager
+ bGroup = Cudd_bddTransfer( ddPart, dd, ddPart->bFunc );
+ if ( bGroup == NULL )
+ return NULL;
+ Cudd_Ref( bGroup );
+if ( fVerbose )
+printf( "Pt0 =%6d. Pt1 =%6d. ", Cudd_DagSize(ddPart->bFunc), Cudd_DagSize(bGroup) );
+ // perform partial product
+ bCube = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant1, i+1), dd ); Cudd_Ref( bCube );
+// bImage = Cudd_bddAndAbstract( dd, bTemp = bImage, bGroup, bCube );
+// bImage = Extra_bddAndAbstractTime( dd, bTemp = bImage, bGroup, bCube, TimeTarget );
+ bImage = Cudd_bddAndAbstract( dd, bTemp = bImage, bGroup, bCube );
+ if ( bImage == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bCube );
+ Cudd_RecursiveDeref( dd, bGroup );
+ return NULL;
+ }
+ Cudd_Ref( bImage );
+
+if ( fVerbose )
+printf( "Im0 =%6d. Im1 =%6d. ", Cudd_DagSize(bTemp), Cudd_DagSize(bImage) );
+//printf("\n"); Extra_bddPrintSupport(dd, bImage); printf("\n");
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bCube );
+ Cudd_RecursiveDeref( dd, bGroup );
+
+// Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+// Abc_Print( 1, "Reo =%6d. ", Cudd_DagSize(bImage) );
+
+if ( fVerbose )
+printf( "Supp =%3d. ", Cudd_SupportSize(dd, bImage) );
+if ( fVerbose )
+Abc_PrintTime( 1, "T", Abc_Clock() - clk );
+ }
+
+ if ( !fBackward )
+ {
+ // change polarity
+ bCube = Llb_DriverPhaseCube( pAig, vDriRefs, dd ); Cudd_Ref( bCube );
+ bImage = Extra_bddChangePolarity( dd, bTemp = bImage, bCube ); Cudd_Ref( bImage );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bCube );
+ }
+ else
+ {
+ // quantify unique vriables
+ bCube = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, 0), dd ); Cudd_Ref( bCube );
+ bImage = Cudd_bddExistAbstract( dd, bTemp = bImage, bCube ); Cudd_Ref( bImage );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bCube );
+ }
+
+ if ( fReorder )
+ {
+ if ( fVerbose )
+ Abc_Print( 1, " Reordering... Before =%5d. ", Cudd_DagSize(bImage) );
+ Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+ if ( fVerbose )
+ Abc_Print( 1, "After =%5d. ", Cudd_DagSize(bImage) );
+// Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+// Abc_Print( 1, "After =%5d. ", Cudd_DagSize(bImage) );
+ if ( fVerbose )
+ Abc_PrintTime( 1, "Time", Abc_Clock() - clk0 );
+// Abc_Print( 1, "\n" );
+ }
+
+ Cudd_Deref( bImage );
+ return bImage;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/bdd/llb/llb3Image.c b/src/bdd/llb/llb3Image.c
new file mode 100644
index 00000000..72c6120a
--- /dev/null
+++ b/src/bdd/llb/llb3Image.c
@@ -0,0 +1,1095 @@
+/**CFile****************************************************************
+
+ FileName [llb3Image.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Computes image using partitioned structure.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb3Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Llb_Var_t_ Llb_Var_t;
+struct Llb_Var_t_
+{
+ int iVar; // variable number
+ int nScore; // variable score
+ Vec_Int_t * vParts; // partitions
+};
+
+typedef struct Llb_Prt_t_ Llb_Prt_t;
+struct Llb_Prt_t_
+{
+ int iPart; // partition number
+ int nSize; // the number of BDD nodes
+ DdNode * bFunc; // the partition
+ Vec_Int_t * vVars; // support
+};
+
+typedef struct Llb_Mgr_t_ Llb_Mgr_t;
+struct Llb_Mgr_t_
+{
+ Aig_Man_t * pAig; // AIG manager
+ Vec_Ptr_t * vLeaves; // leaves in the AIG manager
+ Vec_Ptr_t * vRoots; // roots in the AIG manager
+ DdManager * dd; // working BDD manager
+ int * pVars2Q; // variables to quantify
+ // internal
+ Llb_Prt_t ** pParts; // partitions
+ Llb_Var_t ** pVars; // variables
+ int iPartFree; // next free partition
+ int nVars; // the number of BDD variables
+ int nSuppMax; // maximum support size
+ // temporary
+ int * pSupp; // temporary support storage
+};
+
+static inline Llb_Var_t * Llb_MgrVar( Llb_Mgr_t * p, int i ) { return p->pVars[i]; }
+static inline Llb_Prt_t * Llb_MgrPart( Llb_Mgr_t * p, int i ) { return p->pParts[i]; }
+
+// iterator over vars
+#define Llb_MgrForEachVar( p, pVar, i ) \
+ for ( i = 0; (i < p->nVars) && (((pVar) = Llb_MgrVar(p, i)), 1); i++ ) if ( pVar == NULL ) {} else
+// iterator over parts
+#define Llb_MgrForEachPart( p, pPart, i ) \
+ for ( i = 0; (i < p->iPartFree) && (((pPart) = Llb_MgrPart(p, i)), 1); i++ ) if ( pPart == NULL ) {} else
+
+// iterator over vars of one partition
+#define Llb_PartForEachVar( p, pPart, pVar, i ) \
+ for ( i = 0; (i < Vec_IntSize(pPart->vVars)) && (((pVar) = Llb_MgrVar(p, Vec_IntEntry(pPart->vVars,i))), 1); i++ )
+// iterator over parts of one variable
+#define Llb_VarForEachPart( p, pVar, pPart, i ) \
+ for ( i = 0; (i < Vec_IntSize(pVar->vParts)) && (((pPart) = Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,i))), 1); i++ )
+
+// statistics
+abctime timeBuild, timeAndEx, timeOther;
+int nSuppMax;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Removes one variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinRemoveVar( Llb_Mgr_t * p, Llb_Var_t * pVar )
+{
+ assert( p->pVars[pVar->iVar] == pVar );
+ p->pVars[pVar->iVar] = NULL;
+ Vec_IntFree( pVar->vParts );
+ ABC_FREE( pVar );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes one partition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinRemovePart( Llb_Mgr_t * p, Llb_Prt_t * pPart )
+{
+ assert( p->pParts[pPart->iPart] == pPart );
+ p->pParts[pPart->iPart] = NULL;
+ Vec_IntFree( pPart->vVars );
+ Cudd_RecursiveDeref( p->dd, pPart->bFunc );
+ ABC_FREE( pPart );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create cube with singleton variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_NonlinCreateCube1( Llb_Mgr_t * p, Llb_Prt_t * pPart )
+{
+ DdNode * bCube, * bTemp;
+ Llb_Var_t * pVar;
+ int i;
+ abctime TimeStop;
+ TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
+ bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube );
+ Llb_PartForEachVar( p, pPart, pVar, i )
+ {
+ assert( Vec_IntSize(pVar->vParts) > 0 );
+ if ( Vec_IntSize(pVar->vParts) != 1 )
+ continue;
+ assert( Vec_IntEntry(pVar->vParts, 0) == pPart->iPart );
+ bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ Cudd_Deref( bCube );
+ p->dd->TimeStop = TimeStop;
+ return bCube;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create cube of variables appearing only in two partitions.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_NonlinCreateCube2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 )
+{
+ DdNode * bCube, * bTemp;
+ Llb_Var_t * pVar;
+ int i;
+ abctime TimeStop;
+ TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
+ bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube );
+ Llb_PartForEachVar( p, pPart1, pVar, i )
+ {
+ assert( Vec_IntSize(pVar->vParts) > 0 );
+ if ( Vec_IntSize(pVar->vParts) != 2 )
+ continue;
+ if ( (Vec_IntEntry(pVar->vParts, 0) == pPart1->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart2->iPart) ||
+ (Vec_IntEntry(pVar->vParts, 0) == pPart2->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart1->iPart) )
+ {
+ bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ }
+ Cudd_Deref( bCube );
+ p->dd->TimeStop = TimeStop;
+ return bCube;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if partition has singleton variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_NonlinHasSingletonVars( Llb_Mgr_t * p, Llb_Prt_t * pPart )
+{
+ Llb_Var_t * pVar;
+ int i;
+ Llb_PartForEachVar( p, pPart, pVar, i )
+ if ( Vec_IntSize(pVar->vParts) == 1 )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if partition has singleton variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinPrint( Llb_Mgr_t * p )
+{
+ Llb_Prt_t * pPart;
+ Llb_Var_t * pVar;
+ int i, k;
+ printf( "\n" );
+ Llb_MgrForEachVar( p, pVar, i )
+ {
+ printf( "Var %3d : ", i );
+ Llb_VarForEachPart( p, pVar, pPart, k )
+ printf( "%d ", pPart->iPart );
+ printf( "\n" );
+ }
+ Llb_MgrForEachPart( p, pPart, i )
+ {
+ printf( "Part %3d : ", i );
+ Llb_PartForEachVar( p, pPart, pVar, k )
+ printf( "%d ", pVar->iVar );
+ printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Quantifies singles belonging to one partition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_NonlinQuantify1( Llb_Mgr_t * p, Llb_Prt_t * pPart, int fSubset )
+{
+ Llb_Var_t * pVar;
+ Llb_Prt_t * pTemp;
+ Vec_Ptr_t * vSingles;
+ DdNode * bCube, * bTemp;
+ int i, RetValue, nSizeNew;
+ if ( fSubset )
+ {
+ int Length;
+// int nSuppSize = Cudd_SupportSize( p->dd, pPart->bFunc );
+// pPart->bFunc = Cudd_SubsetHeavyBranch( p->dd, bTemp = pPart->bFunc, nSuppSize, 3*pPart->nSize/4 ); Cudd_Ref( pPart->bFunc );
+ pPart->bFunc = Cudd_LargestCube( p->dd, bTemp = pPart->bFunc, &Length ); Cudd_Ref( pPart->bFunc );
+
+ printf( "Subsetting %3d : ", pPart->iPart );
+ printf( "(Supp =%3d Node =%5d) -> ", Cudd_SupportSize(p->dd, bTemp), Cudd_DagSize(bTemp) );
+ printf( "(Supp =%3d Node =%5d)\n", Cudd_SupportSize(p->dd, pPart->bFunc), Cudd_DagSize(pPart->bFunc) );
+
+ RetValue = (Cudd_DagSize(bTemp) == Cudd_DagSize(pPart->bFunc));
+
+ Cudd_RecursiveDeref( p->dd, bTemp );
+
+ if ( RetValue )
+ return 1;
+ }
+ else
+ {
+ // create cube to be quantified
+ bCube = Llb_NonlinCreateCube1( p, pPart ); Cudd_Ref( bCube );
+// assert( !Cudd_IsConstant(bCube) );
+ // derive new function
+ pPart->bFunc = Cudd_bddExistAbstract( p->dd, bTemp = pPart->bFunc, bCube ); Cudd_Ref( pPart->bFunc );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->dd, bCube );
+ }
+ // get support
+ vSingles = Vec_PtrAlloc( 0 );
+ nSizeNew = Cudd_DagSize(pPart->bFunc);
+ Extra_SupportArray( p->dd, pPart->bFunc, p->pSupp );
+ Llb_PartForEachVar( p, pPart, pVar, i )
+ if ( p->pSupp[pVar->iVar] )
+ {
+ assert( Vec_IntSize(pVar->vParts) > 1 );
+ pVar->nScore -= pPart->nSize - nSizeNew;
+ }
+ else
+ {
+ RetValue = Vec_IntRemove( pVar->vParts, pPart->iPart );
+ assert( RetValue );
+ pVar->nScore -= pPart->nSize;
+ if ( Vec_IntSize(pVar->vParts) == 0 )
+ Llb_NonlinRemoveVar( p, pVar );
+ else if ( Vec_IntSize(pVar->vParts) == 1 )
+ Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) );
+ }
+
+ // update partition
+ pPart->nSize = nSizeNew;
+ Vec_IntClear( pPart->vVars );
+ for ( i = 0; i < p->nVars; i++ )
+ if ( p->pSupp[i] && p->pVars2Q[i] )
+ Vec_IntPush( pPart->vVars, i );
+ // remove other variables
+ Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i )
+ Llb_NonlinQuantify1( p, pTemp, 0 );
+ Vec_PtrFree( vSingles );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Quantifies singles belonging to one partition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_NonlinQuantify2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 )
+{
+ int fVerbose = 0;
+ Llb_Var_t * pVar;
+ Llb_Prt_t * pTemp;
+ Vec_Ptr_t * vSingles;
+ DdNode * bCube, * bFunc;
+ int i, RetValue, nSuppSize;
+// int iPart1 = pPart1->iPart;
+// int iPart2 = pPart2->iPart;
+
+ // create cube to be quantified
+ bCube = Llb_NonlinCreateCube2( p, pPart1, pPart2 ); Cudd_Ref( bCube );
+if ( fVerbose )
+{
+printf( "\n" );
+printf( "\n" );
+Llb_NonlinPrint( p );
+printf( "Conjoining partitions %d and %d.\n", pPart1->iPart, pPart2->iPart );
+Extra_bddPrintSupport( p->dd, bCube ); printf( "\n" );
+}
+
+ // derive new function
+// bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube ); Cudd_Ref( bFunc );
+/*
+ bFunc = Cudd_bddAndAbstractLimit( p->dd, pPart1->bFunc, pPart2->bFunc, bCube, Limit );
+ if ( bFunc == NULL )
+ {
+ int RetValue;
+ Cudd_RecursiveDeref( p->dd, bCube );
+ if ( pPart1->nSize < pPart2->nSize )
+ RetValue = Llb_NonlinQuantify1( p, pPart1, 1 );
+ else
+ RetValue = Llb_NonlinQuantify1( p, pPart2, 1 );
+ if ( RetValue )
+ Limit = Limit + 1000;
+ Llb_NonlinQuantify2( p, pPart1, pPart2 );
+ return 0;
+ }
+ Cudd_Ref( bFunc );
+*/
+
+// bFunc = Extra_bddAndAbstractTime( p->dd, pPart1->bFunc, pPart2->bFunc, bCube, TimeOut );
+ bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube );
+ if ( bFunc == NULL )
+ {
+ Cudd_RecursiveDeref( p->dd, bCube );
+ return 0;
+ }
+ Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( p->dd, bCube );
+
+ // create new partition
+ pTemp = p->pParts[p->iPartFree] = ABC_CALLOC( Llb_Prt_t, 1 );
+ pTemp->iPart = p->iPartFree++;
+ pTemp->nSize = Cudd_DagSize(bFunc);
+ pTemp->bFunc = bFunc;
+ pTemp->vVars = Vec_IntAlloc( 8 );
+ // update variables
+ Llb_PartForEachVar( p, pPart1, pVar, i )
+ {
+ RetValue = Vec_IntRemove( pVar->vParts, pPart1->iPart );
+ assert( RetValue );
+ pVar->nScore -= pPart1->nSize;
+ }
+ // update variables
+ Llb_PartForEachVar( p, pPart2, pVar, i )
+ {
+ RetValue = Vec_IntRemove( pVar->vParts, pPart2->iPart );
+ assert( RetValue );
+ pVar->nScore -= pPart2->nSize;
+ }
+ // add variables to the new partition
+ nSuppSize = 0;
+ Extra_SupportArray( p->dd, bFunc, p->pSupp );
+ for ( i = 0; i < p->nVars; i++ )
+ {
+ nSuppSize += p->pSupp[i];
+ if ( p->pSupp[i] && p->pVars2Q[i] )
+ {
+ pVar = Llb_MgrVar( p, i );
+ pVar->nScore += pTemp->nSize;
+ Vec_IntPush( pVar->vParts, pTemp->iPart );
+ Vec_IntPush( pTemp->vVars, i );
+ }
+ }
+ p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize );
+ // remove variables and collect partitions with singleton variables
+ vSingles = Vec_PtrAlloc( 0 );
+ Llb_PartForEachVar( p, pPart1, pVar, i )
+ {
+ if ( Vec_IntSize(pVar->vParts) == 0 )
+ Llb_NonlinRemoveVar( p, pVar );
+ else if ( Vec_IntSize(pVar->vParts) == 1 )
+ {
+ if ( fVerbose )
+ printf( "Adding partition %d because of var %d.\n",
+ Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar );
+ Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) );
+ }
+ }
+ Llb_PartForEachVar( p, pPart2, pVar, i )
+ {
+ if ( pVar == NULL )
+ continue;
+ if ( Vec_IntSize(pVar->vParts) == 0 )
+ Llb_NonlinRemoveVar( p, pVar );
+ else if ( Vec_IntSize(pVar->vParts) == 1 )
+ {
+ if ( fVerbose )
+ printf( "Adding partition %d because of var %d.\n",
+ Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar );
+ Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) );
+ }
+ }
+ // remove partitions
+ Llb_NonlinRemovePart( p, pPart1 );
+ Llb_NonlinRemovePart( p, pPart2 );
+ // remove other variables
+if ( fVerbose )
+Llb_NonlinPrint( p );
+ Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i )
+ {
+if ( fVerbose )
+printf( "Updating partitiong %d with singlton vars.\n", pTemp->iPart );
+ Llb_NonlinQuantify1( p, pTemp, 0 );
+ }
+if ( fVerbose )
+Llb_NonlinPrint( p );
+ Vec_PtrFree( vSingles );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes volume of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinCutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ return;
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ if ( Saig_ObjIsLi(p, pObj) )
+ {
+ Llb_NonlinCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes);
+ return;
+ }
+ if ( Aig_ObjIsConst1(pObj) )
+ return;
+ assert( Aig_ObjIsNode(pObj) );
+ Llb_NonlinCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes);
+ Llb_NonlinCutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes);
+ Vec_PtrPush( vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes volume of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_NonlinCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper )
+{
+ Vec_Ptr_t * vNodes;
+ Aig_Obj_t * pObj;
+ int i;
+ // mark the lower cut with the traversal ID
+ Aig_ManIncrementTravId(p);
+ Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+ Aig_ObjSetTravIdCurrent( p, pObj );
+ // count the upper cut
+ vNodes = Vec_PtrAlloc( 100 );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i )
+ Llb_NonlinCutNodes_rec( p, pObj, vNodes );
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns array of BDDs for the roots in terms of the leaves.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_NonlinBuildBdds( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, DdManager * dd )
+{
+ Vec_Ptr_t * vNodes, * vResult;
+ Aig_Obj_t * pObj;
+ DdNode * bBdd0, * bBdd1, * bProd;
+ int i, k;
+
+ Aig_ManConst1(p)->pData = Cudd_ReadOne( dd );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+ pObj->pData = Cudd_bddIthVar( dd, Aig_ObjId(pObj) );
+
+ vNodes = Llb_NonlinCutNodes( p, vLower, vUpper );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+ {
+ bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+// pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeOut );
+ pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 );
+ if ( pObj->pData == NULL )
+ {
+ Vec_PtrForEachEntryStop( Aig_Obj_t *, vNodes, pObj, k, i )
+ if ( pObj->pData )
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+ Vec_PtrFree( vNodes );
+ return NULL;
+ }
+ Cudd_Ref( (DdNode *)pObj->pData );
+ }
+
+ vResult = Vec_PtrAlloc( 100 );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i )
+ {
+ if ( Aig_ObjIsNode(pObj) )
+ {
+ bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), (DdNode *)pObj->pData ); Cudd_Ref( bProd );
+ }
+ else
+ {
+ assert( Saig_ObjIsLi(p, pObj) );
+ bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), bBdd0 ); Cudd_Ref( bProd );
+ }
+ Vec_PtrPush( vResult, bProd );
+ }
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+
+ Vec_PtrFree( vNodes );
+ return vResult;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts non-linear quantification scheduling.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinAddPair( Llb_Mgr_t * p, DdNode * bFunc, int iPart, int iVar )
+{
+ if ( p->pVars[iVar] == NULL )
+ {
+ p->pVars[iVar] = ABC_CALLOC( Llb_Var_t, 1 );
+ p->pVars[iVar]->iVar = iVar;
+ p->pVars[iVar]->nScore = 0;
+ p->pVars[iVar]->vParts = Vec_IntAlloc( 8 );
+ }
+ Vec_IntPush( p->pVars[iVar]->vParts, iPart );
+ Vec_IntPush( p->pParts[iPart]->vVars, iVar );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts non-linear quantification scheduling.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinAddPartition( Llb_Mgr_t * p, int i, DdNode * bFunc )
+{
+ int k, nSuppSize;
+ assert( !Cudd_IsConstant(bFunc) );
+ // create partition
+ p->pParts[i] = ABC_CALLOC( Llb_Prt_t, 1 );
+ p->pParts[i]->iPart = i;
+ p->pParts[i]->bFunc = bFunc;
+ p->pParts[i]->vVars = Vec_IntAlloc( 8 );
+ // add support dependencies
+ nSuppSize = 0;
+ Extra_SupportArray( p->dd, bFunc, p->pSupp );
+ for ( k = 0; k < p->nVars; k++ )
+ {
+ nSuppSize += p->pSupp[k];
+ if ( p->pSupp[k] && p->pVars2Q[k] )
+ Llb_NonlinAddPair( p, bFunc, i, k );
+ }
+ p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts non-linear quantification scheduling.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_NonlinStart( Llb_Mgr_t * p )
+{
+ Vec_Ptr_t * vRootBdds;
+ DdNode * bFunc;
+ int i;
+ // create and collect BDDs
+ vRootBdds = Llb_NonlinBuildBdds( p->pAig, p->vLeaves, p->vRoots, p->dd ); // come referenced
+ if ( vRootBdds == NULL )
+ return 0;
+ // add pairs (refs are consumed inside)
+ Vec_PtrForEachEntry( DdNode *, vRootBdds, bFunc, i )
+ Llb_NonlinAddPartition( p, i, bFunc );
+ Vec_PtrFree( vRootBdds );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks that each var appears in at least one partition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+**********************************************************************/
+void Llb_NonlinCheckVars( Llb_Mgr_t * p )
+{
+ Llb_Var_t * pVar;
+ int i;
+ Llb_MgrForEachVar( p, pVar, i )
+ assert( Vec_IntSize(pVar->vParts) > 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find next partition to quantify]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_NonlinNextPartitions( Llb_Mgr_t * p, Llb_Prt_t ** ppPart1, Llb_Prt_t ** ppPart2 )
+{
+ Llb_Var_t * pVar, * pVarBest = NULL;
+ Llb_Prt_t * pPart, * pPart1Best = NULL, * pPart2Best = NULL;
+ int i;
+ Llb_NonlinCheckVars( p );
+ // find variable with minimum score
+ Llb_MgrForEachVar( p, pVar, i )
+ if ( pVarBest == NULL || pVarBest->nScore > pVar->nScore )
+ pVarBest = pVar;
+ if ( pVarBest == NULL )
+ return 0;
+ // find two partitions with minimum size
+ Llb_VarForEachPart( p, pVarBest, pPart, i )
+ {
+ if ( pPart1Best == NULL )
+ pPart1Best = pPart;
+ else if ( pPart2Best == NULL )
+ pPart2Best = pPart;
+ else if ( pPart1Best->nSize > pPart->nSize || pPart2Best->nSize > pPart->nSize )
+ {
+ if ( pPart1Best->nSize > pPart2Best->nSize )
+ pPart1Best = pPart;
+ else
+ pPart2Best = pPart;
+ }
+ }
+ *ppPart1 = pPart1Best;
+ *ppPart2 = pPart2Best;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reorders BDDs in the working manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinReorder( DdManager * dd, int fTwice, int fVerbose )
+{
+ abctime clk = Abc_Clock();
+ if ( fVerbose )
+ Abc_Print( 1, "Reordering... Before =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+ Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+ if ( fVerbose )
+ Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+ if ( fTwice )
+ {
+ Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+ if ( fVerbose )
+ Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+ }
+ if ( fVerbose )
+ Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recomputes scores after variable reordering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinRecomputeScores( Llb_Mgr_t * p )
+{
+ Llb_Prt_t * pPart;
+ Llb_Var_t * pVar;
+ int i, k;
+ Llb_MgrForEachPart( p, pPart, i )
+ pPart->nSize = Cudd_DagSize(pPart->bFunc);
+ Llb_MgrForEachVar( p, pVar, i )
+ {
+ pVar->nScore = 0;
+ Llb_VarForEachPart( p, pVar, pPart, k )
+ pVar->nScore += pPart->nSize;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recomputes scores after variable reordering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinVerifyScores( Llb_Mgr_t * p )
+{
+ Llb_Prt_t * pPart;
+ Llb_Var_t * pVar;
+ int i, k, nScore;
+ Llb_MgrForEachPart( p, pPart, i )
+ assert( pPart->nSize == Cudd_DagSize(pPart->bFunc) );
+ Llb_MgrForEachVar( p, pVar, i )
+ {
+ nScore = 0;
+ Llb_VarForEachPart( p, pVar, pPart, k )
+ nScore += pPart->nSize;
+ assert( nScore == pVar->nScore );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts non-linear quantification scheduling.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Mgr_t * Llb_NonlinAlloc( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, DdManager * dd )
+{
+ Llb_Mgr_t * p;
+ p = ABC_CALLOC( Llb_Mgr_t, 1 );
+ p->pAig = pAig;
+ p->vLeaves = vLeaves;
+ p->vRoots = vRoots;
+ p->dd = dd;
+ p->pVars2Q = pVars2Q;
+ p->nVars = Cudd_ReadSize(dd);
+ p->iPartFree = Vec_PtrSize(vRoots);
+ p->pVars = ABC_CALLOC( Llb_Var_t *, p->nVars );
+ p->pParts = ABC_CALLOC( Llb_Prt_t *, 2 * p->iPartFree + 2 );
+ p->pSupp = ABC_ALLOC( int, Cudd_ReadSize(dd) );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops non-linear quantification scheduling.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinFree( Llb_Mgr_t * p )
+{
+ Llb_Prt_t * pPart;
+ Llb_Var_t * pVar;
+ int i;
+ Llb_MgrForEachVar( p, pVar, i )
+ Llb_NonlinRemoveVar( p, pVar );
+ Llb_MgrForEachPart( p, pPart, i )
+ Llb_NonlinRemovePart( p, pPart );
+ ABC_FREE( p->pVars );
+ ABC_FREE( p->pParts );
+ ABC_FREE( p->pSupp );
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs image computation.]
+
+ Description [Computes image of BDDs (vFuncs).]
+
+ SideEffects [BDDs in vFuncs are derefed inside. The result is refed.]
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_NonlinImage( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q,
+ DdManager * dd, DdNode * bCurrent, int fReorder, int fVerbose, int * pOrder )
+{
+ Llb_Prt_t * pPart, * pPart1, * pPart2;
+ Llb_Mgr_t * p;
+ DdNode * bFunc, * bTemp;
+ int i, nReorders, timeInside;
+ abctime clk = Abc_Clock(), clk2;
+ // start the manager
+ clk2 = Abc_Clock();
+ p = Llb_NonlinAlloc( pAig, vLeaves, vRoots, pVars2Q, dd );
+ if ( !Llb_NonlinStart( p ) )
+ {
+ Llb_NonlinFree( p );
+ return NULL;
+ }
+ // add partition
+ Llb_NonlinAddPartition( p, p->iPartFree++, bCurrent );
+ // remove singles
+ Llb_MgrForEachPart( p, pPart, i )
+ if ( Llb_NonlinHasSingletonVars(p, pPart) )
+ Llb_NonlinQuantify1( p, pPart, 0 );
+ timeBuild += Abc_Clock() - clk2;
+ timeInside = Abc_Clock() - clk2;
+ // compute scores
+ Llb_NonlinRecomputeScores( p );
+ // save permutation
+ if ( pOrder )
+ memcpy( pOrder, dd->invperm, sizeof(int) * dd->size );
+ // iteratively quantify variables
+ while ( Llb_NonlinNextPartitions(p, &pPart1, &pPart2) )
+ {
+ clk2 = Abc_Clock();
+ nReorders = Cudd_ReadReorderings(dd);
+ if ( !Llb_NonlinQuantify2( p, pPart1, pPart2 ) )
+ {
+ Llb_NonlinFree( p );
+ return NULL;
+ }
+ timeAndEx += Abc_Clock() - clk2;
+ timeInside += Abc_Clock() - clk2;
+ if ( nReorders < Cudd_ReadReorderings(dd) )
+ Llb_NonlinRecomputeScores( p );
+// else
+// Llb_NonlinVerifyScores( p );
+ }
+ // load partitions
+ bFunc = Cudd_ReadOne(p->dd); Cudd_Ref( bFunc );
+ Llb_MgrForEachPart( p, pPart, i )
+ {
+ bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ nSuppMax = p->nSuppMax;
+ Llb_NonlinFree( p );
+ // reorder variables
+ if ( fReorder )
+ Llb_NonlinReorder( dd, 0, fVerbose );
+ timeOther += Abc_Clock() - clk - timeInside;
+ // return
+ Cudd_Deref( bFunc );
+ return bFunc;
+}
+
+
+
+static Llb_Mgr_t * p = NULL;
+
+/**Function*************************************************************
+
+ Synopsis [Starts image computation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdManager * Llb_NonlinImageStart( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, int * pOrder, int fFirst, abctime TimeTarget )
+{
+ DdManager * dd;
+ abctime clk = Abc_Clock();
+ assert( p == NULL );
+ // start a new manager (disable reordering)
+ dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ dd->TimeStop = TimeTarget;
+ Cudd_ShuffleHeap( dd, pOrder );
+// if ( fFirst )
+ Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+ // start the manager
+ p = Llb_NonlinAlloc( pAig, vLeaves, vRoots, pVars2Q, dd );
+ if ( !Llb_NonlinStart( p ) )
+ {
+ Llb_NonlinFree( p );
+ p = NULL;
+ return NULL;
+ }
+ timeBuild += Abc_Clock() - clk;
+// if ( !fFirst )
+// Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+ return dd;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs image computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_NonlinImageCompute( DdNode * bCurrent, int fReorder, int fDrop, int fVerbose, int * pOrder )
+{
+ Llb_Prt_t * pPart, * pPart1, * pPart2;
+ DdNode * bFunc, * bTemp;
+ int i, nReorders, timeInside = 0;
+ abctime clk = Abc_Clock(), clk2;
+
+ // add partition
+ Llb_NonlinAddPartition( p, p->iPartFree++, bCurrent );
+ // remove singles
+ Llb_MgrForEachPart( p, pPart, i )
+ if ( Llb_NonlinHasSingletonVars(p, pPart) )
+ Llb_NonlinQuantify1( p, pPart, 0 );
+ // reorder
+ if ( fReorder )
+ Llb_NonlinReorder( p->dd, 0, 0 );
+ // save permutation
+ memcpy( pOrder, p->dd->invperm, sizeof(int) * p->dd->size );
+
+ // compute scores
+ Llb_NonlinRecomputeScores( p );
+ // iteratively quantify variables
+ while ( Llb_NonlinNextPartitions(p, &pPart1, &pPart2) )
+ {
+ clk2 = Abc_Clock();
+ nReorders = Cudd_ReadReorderings(p->dd);
+ if ( !Llb_NonlinQuantify2( p, pPart1, pPart2 ) )
+ {
+ Llb_NonlinFree( p );
+ return NULL;
+ }
+ timeAndEx += Abc_Clock() - clk2;
+ timeInside += Abc_Clock() - clk2;
+ if ( nReorders < Cudd_ReadReorderings(p->dd) )
+ Llb_NonlinRecomputeScores( p );
+// else
+// Llb_NonlinVerifyScores( p );
+ }
+ // load partitions
+ bFunc = Cudd_ReadOne(p->dd); Cudd_Ref( bFunc );
+ Llb_MgrForEachPart( p, pPart, i )
+ {
+ bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc );
+ if ( bFunc == NULL )
+ {
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Llb_NonlinFree( p );
+ return NULL;
+ }
+ Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ nSuppMax = p->nSuppMax;
+ // reorder variables
+// if ( fReorder )
+// Llb_NonlinReorder( p->dd, 0, fVerbose );
+ // save permutation
+// memcpy( pOrder, p->dd->invperm, sizeof(int) * Cudd_ReadSize(p->dd) );
+
+ timeOther += Abc_Clock() - clk - timeInside;
+ // return
+ Cudd_Deref( bFunc );
+ return bFunc;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Quits image computation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinImageQuit()
+{
+ DdManager * dd;
+ if ( p == NULL )
+ return;
+ dd = p->dd;
+ Llb_NonlinFree( p );
+ if ( dd->bFunc )
+ Cudd_RecursiveDeref( dd, dd->bFunc );
+ Extra_StopManager( dd );
+// Cudd_Quit ( dd );
+ p = NULL;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/bdd/llb/llb3Nonlin.c b/src/bdd/llb/llb3Nonlin.c
new file mode 100644
index 00000000..94a48bbf
--- /dev/null
+++ b/src/bdd/llb/llb3Nonlin.c
@@ -0,0 +1,872 @@
+/**CFile****************************************************************
+
+ FileName [llb2Nonlin.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Non-linear quantification scheduling.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb2Nonlin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Llb_Mnn_t_ Llb_Mnn_t;
+struct Llb_Mnn_t_
+{
+ Aig_Man_t * pInit; // AIG manager
+ Aig_Man_t * pAig; // AIG manager
+ Gia_ParLlb_t * pPars; // parameters
+
+ DdManager * dd; // BDD manager
+ DdManager * ddG; // BDD manager
+ DdManager * ddR; // BDD manager
+ Vec_Ptr_t * vRings; // onion rings in ddR
+
+ Vec_Ptr_t * vLeaves;
+ Vec_Ptr_t * vRoots;
+ int * pVars2Q;
+ int * pOrderL;
+ int * pOrderL2;
+ int * pOrderG;
+
+ Vec_Int_t * vCs2Glo; // cur state variables into global variables
+ Vec_Int_t * vNs2Glo; // next state variables into global variables
+ Vec_Int_t * vGlo2Cs; // global variables into cur state variables
+ Vec_Int_t * vGlo2Ns; // global variables into next state variables
+
+ int ddLocReos;
+ int ddLocGrbs;
+
+ abctime timeImage;
+ abctime timeTran1;
+ abctime timeTran2;
+ abctime timeGloba;
+ abctime timeOther;
+ abctime timeTotal;
+ abctime timeReo;
+ abctime timeReoG;
+
+};
+
+extern abctime timeBuild, timeAndEx, timeOther;
+extern int nSuppMax;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Finds variable whose 0-cofactor is the smallest.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_NonlinFindBestVar( DdManager * dd, DdNode * bFunc, Aig_Man_t * pAig )
+{
+ int fVerbose = 0;
+ Aig_Obj_t * pObj;
+ DdNode * bCof, * bVar;
+ int i, iVar, iVarBest = -1, iValue, iValueBest = ABC_INFINITY, Size0Best = -1;
+ int Size, Size0, Size1;
+ abctime clk = Abc_Clock();
+ Size = Cudd_DagSize(bFunc);
+// printf( "Original = %6d. SuppSize = %3d. Vars = %3d.\n",
+// Size = Cudd_DagSize(bFunc), Cudd_SupportSize(dd, bFunc), Aig_ManRegNum(pAig) );
+ Saig_ManForEachLo( pAig, pObj, i )
+ {
+ iVar = Aig_ObjId(pObj);
+
+if ( fVerbose )
+printf( "Var =%3d : ", iVar );
+ bVar = Cudd_bddIthVar(dd, iVar);
+
+ bCof = Cudd_bddAnd( dd, bFunc, Cudd_Not(bVar) ); Cudd_Ref( bCof );
+ Size0 = Cudd_DagSize(bCof);
+if ( fVerbose )
+printf( "Supp0 =%3d ", Cudd_SupportSize(dd, bCof) );
+if ( fVerbose )
+printf( "Size0 =%6d ", Size0 );
+ Cudd_RecursiveDeref( dd, bCof );
+
+ bCof = Cudd_bddAnd( dd, bFunc, bVar ); Cudd_Ref( bCof );
+ Size1 = Cudd_DagSize(bCof);
+if ( fVerbose )
+printf( "Supp1 =%3d ", Cudd_SupportSize(dd, bCof) );
+if ( fVerbose )
+printf( "Size1 =%6d ", Size1 );
+ Cudd_RecursiveDeref( dd, bCof );
+
+ iValue = Abc_MaxInt(Size0, Size1) - Abc_MinInt(Size0, Size1) + Size0 + Size1 - Size;
+if ( fVerbose )
+printf( "D =%6d ", Size0 + Size1 - Size );
+if ( fVerbose )
+printf( "B =%6d ", Abc_MaxInt(Size0, Size1) - Abc_MinInt(Size0, Size1) );
+if ( fVerbose )
+printf( "S =%6d\n", iValue );
+ if ( Size0 > 1 && Size1 > 1 && iValueBest > iValue )
+ {
+ iValueBest = iValue;
+ iVarBest = i;
+ Size0Best = Size0;
+ }
+ }
+ printf( "BestVar = %4d/%4d. Value =%6d. Orig =%6d. Size0 =%6d. ",
+ iVarBest, Aig_ObjId(Saig_ManLo(pAig,iVarBest)), iValueBest, Size, Size0Best );
+ Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+ return iVarBest;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds variable whose 0-cofactor is the smallest.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinTrySubsetting( DdManager * dd, DdNode * bFunc )
+{
+ DdNode * bNew;
+ printf( "Original = %6d. SuppSize = %3d. ",
+ Cudd_DagSize(bFunc), Cudd_SupportSize(dd, bFunc) );
+ bNew = Cudd_SubsetHeavyBranch( dd, bFunc, Cudd_SupportSize(dd, bFunc), 1000 ); Cudd_Ref( bNew );
+ printf( "Result = %6d. SuppSize = %3d.\n",
+ Cudd_DagSize(bNew), Cudd_SupportSize(dd, bNew) );
+ Cudd_RecursiveDeref( dd, bNew );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinPrepareVarMap( Llb_Mnn_t * p )
+{
+ Aig_Obj_t * pObjLi, * pObjLo, * pObj;
+ int i, iVarLi, iVarLo;
+ p->vCs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) );
+ p->vNs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) );
+ p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) );
+ p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) );
+ Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+ {
+ iVarLi = Aig_ObjId(pObjLi);
+ iVarLo = Aig_ObjId(pObjLo);
+ assert( iVarLi >= 0 && iVarLi < Aig_ManObjNumMax(p->pAig) );
+ assert( iVarLo >= 0 && iVarLo < Aig_ManObjNumMax(p->pAig) );
+ Vec_IntWriteEntry( p->vCs2Glo, iVarLo, i );
+ Vec_IntWriteEntry( p->vNs2Glo, iVarLi, i );
+ Vec_IntWriteEntry( p->vGlo2Cs, i, iVarLo );
+ Vec_IntWriteEntry( p->vGlo2Ns, i, iVarLi );
+ }
+ // add mapping of the PIs
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ {
+ Vec_IntWriteEntry( p->vCs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i );
+ Vec_IntWriteEntry( p->vNs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i );
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_NonlinComputeInitState( Aig_Man_t * pAig, DdManager * dd )
+{
+ Aig_Obj_t * pObj;
+ DdNode * bRes, * bVar, * bTemp;
+ int i, iVar;
+ abctime TimeStop;
+ TimeStop = dd->TimeStop; dd->TimeStop = 0;
+ bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes );
+ Saig_ManForEachLo( pAig, pObj, i )
+ {
+ iVar = (Cudd_ReadSize(dd) == Aig_ManRegNum(pAig)) ? i : Aig_ObjId(pObj);
+ bVar = Cudd_bddIthVar( dd, iVar );
+ bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bRes );
+ dd->TimeStop = TimeStop;
+ return bRes;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Derives counter-example by backward reachability.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Cex_t * Llb_NonlinDeriveCex( Llb_Mnn_t * p )
+{
+ Abc_Cex_t * pCex;
+ Aig_Obj_t * pObj;
+ Vec_Int_t * vVarsNs;
+ DdNode * bState = NULL, * bImage, * bOneCube, * bTemp, * bRing;
+ int i, v, RetValue, nPiOffset;
+ char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) );
+ assert( Vec_PtrSize(p->vRings) > 0 );
+
+ p->dd->TimeStop = 0;
+ p->ddR->TimeStop = 0;
+
+ // update quantifiable vars
+ memset( p->pVars2Q, 0, sizeof(int) * Cudd_ReadSize(p->dd) );
+ vVarsNs = Vec_IntAlloc( Aig_ManRegNum(p->pAig) );
+ Saig_ManForEachLi( p->pAig, pObj, i )
+ {
+ p->pVars2Q[Aig_ObjId(pObj)] = 1;
+ Vec_IntPush( vVarsNs, Aig_ObjId(pObj) );
+ }
+/*
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ printf( "%d ", pObj->Id );
+ printf( "\n" );
+ Saig_ManForEachLi( p->pAig, pObj, i )
+ printf( "%d(%d) ", pObj->Id, Aig_ObjFaninId0(pObj) );
+ printf( "\n" );
+*/
+ // allocate room for the counter-example
+ pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) );
+ pCex->iFrame = Vec_PtrSize(p->vRings) - 1;
+ pCex->iPo = -1;
+
+ // get the last cube
+ bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc ); Cudd_Ref( bOneCube );
+ RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues );
+ Cudd_RecursiveDeref( p->ddR, bOneCube );
+ assert( RetValue );
+
+ // write PIs of counter-example
+ nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1);
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 )
+ Abc_InfoSetBit( pCex->pData, nPiOffset + i );
+
+ // write state in terms of NS variables
+ if ( Vec_PtrSize(p->vRings) > 1 )
+ {
+ bState = Llb_CoreComputeCube( p->dd, vVarsNs, 1, pValues ); Cudd_Ref( bState );
+ }
+ // perform backward analysis
+ Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v )
+ {
+ if ( v == Vec_PtrSize(p->vRings) - 1 )
+ continue;
+//Extra_bddPrintSupport( p->dd, bState ); printf( "\n" );
+//Extra_bddPrintSupport( p->dd, bRing ); printf( "\n" );
+ // compute the next states
+ bImage = Llb_NonlinImage( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->dd, bState,
+ p->pPars->fReorder, p->pPars->fVeryVerbose, NULL ); // consumed reference
+ assert( bImage != NULL );
+ Cudd_Ref( bImage );
+//Extra_bddPrintSupport( p->dd, bImage ); printf( "\n" );
+
+ // move reached states into ring manager
+ bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) ); Cudd_Ref( bImage );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+
+ // intersect with the previous set
+ bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing ); Cudd_Ref( bOneCube );
+ Cudd_RecursiveDeref( p->ddR, bImage );
+
+ // find any assignment of the BDD
+ RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues );
+ Cudd_RecursiveDeref( p->ddR, bOneCube );
+ assert( RetValue );
+
+ // write PIs of counter-example
+ nPiOffset -= Saig_ManPiNum(p->pAig);
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 )
+ Abc_InfoSetBit( pCex->pData, nPiOffset + i );
+
+ // check that we get the init state
+ if ( v == 0 )
+ {
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ assert( pValues[i] == 0 );
+ break;
+ }
+
+ // write state in terms of NS variables
+ bState = Llb_CoreComputeCube( p->dd, vVarsNs, 1, pValues ); Cudd_Ref( bState );
+ }
+ assert( nPiOffset == Saig_ManRegNum(p->pAig) );
+ // update the output number
+//Abc_CexPrint( pCex );
+ RetValue = Saig_ManFindFailedPoCex( p->pInit, pCex );
+ assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pInit) ); // invalid CEX!!!
+ pCex->iPo = RetValue;
+ // cleanup
+ ABC_FREE( pValues );
+ Vec_IntFree( vVarsNs );
+ return pCex;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Perform reachability with hints.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_NonlinReoHook( DdManager * dd, char * Type, void * Method )
+{
+ Aig_Man_t * pAig = (Aig_Man_t *)dd->bFunc;
+ Aig_Obj_t * pObj;
+ int i;
+ printf( "Order: " );
+ for ( i = 0; i < Cudd_ReadSize(dd); i++ )
+ {
+ pObj = Aig_ManObj( pAig, i );
+ if ( pObj == NULL )
+ continue;
+ if ( Saig_ObjIsPi(pAig, pObj) )
+ printf( "pi" );
+ else if ( Saig_ObjIsLo(pAig, pObj) )
+ printf( "lo" );
+ else if ( Saig_ObjIsPo(pAig, pObj) )
+ printf( "po" );
+ else if ( Saig_ObjIsLi(pAig, pObj) )
+ printf( "li" );
+ else continue;
+ printf( "%d=%d ", i, dd->perm[i] );
+ }
+ printf( "\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Perform reachability with hints.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_NonlinCompPerms( DdManager * dd, int * pVar2Lev )
+{
+ DdSubtable * pSubt;
+ int i, Sum = 0, Entry;
+ for ( i = 0; i < dd->size; i++ )
+ {
+ pSubt = &(dd->subtables[dd->perm[i]]);
+ if ( pSubt->keys == pSubt->dead + 1 )
+ continue;
+ Entry = Abc_MaxInt(dd->perm[i], pVar2Lev[i]) - Abc_MinInt(dd->perm[i], pVar2Lev[i]);
+ Sum += Entry;
+//printf( "%d-%d(%d) ", dd->perm[i], pV2L[i], Entry );
+ }
+ return Sum;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Perform reachability with hints.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_NonlinReachability( Llb_Mnn_t * p )
+{
+ DdNode * bTemp, * bNext;
+ int nIters, nBddSize0, nBddSize = -1, NumCmp;//, Limit = p->pPars->nBddMax;
+ abctime clk2, clk3, clk = Abc_Clock();
+ assert( Aig_ManRegNum(p->pAig) > 0 );
+
+ // compute time to stop
+ p->pPars->TimeTarget = p->pPars->TimeLimit ? p->pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0;
+
+ // set the stop time parameter
+ p->dd->TimeStop = p->pPars->TimeTarget;
+ p->ddG->TimeStop = p->pPars->TimeTarget;
+ p->ddR->TimeStop = p->pPars->TimeTarget;
+
+ // set reordering hooks
+ assert( p->dd->bFunc == NULL );
+// p->dd->bFunc = (DdNode *)p->pAig;
+// Cudd_AddHook( p->dd, Llb_NonlinReoHook, CUDD_POST_REORDERING_HOOK );
+
+ // create bad state in the ring manager
+ p->ddR->bFunc = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget );
+ if ( p->ddR->bFunc == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = -1;
+ return -1;
+ }
+ Cudd_Ref( p->ddR->bFunc );
+ // compute the starting set of states
+ Cudd_Quit( p->dd );
+ p->dd = Llb_NonlinImageStart( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->pOrderL, 1, p->pPars->TimeTarget );
+ if ( p->dd == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = -1;
+ return -1;
+ }
+ p->dd->bFunc = Llb_NonlinComputeInitState( p->pAig, p->dd ); Cudd_Ref( p->dd->bFunc ); // current
+ p->ddG->bFunc = Llb_NonlinComputeInitState( p->pAig, p->ddG ); Cudd_Ref( p->ddG->bFunc ); // reached
+ p->ddG->bFunc2 = Llb_NonlinComputeInitState( p->pAig, p->ddG ); Cudd_Ref( p->ddG->bFunc2 ); // frontier
+ for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ )
+ {
+ // check the runtime limit
+ clk2 = Abc_Clock();
+ if ( p->pPars->TimeLimit && Abc_Clock() > p->pPars->TimeTarget )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Llb_NonlinImageQuit();
+ return -1;
+ }
+
+ // save the onion ring
+ bTemp = Extra_TransferPermute( p->dd, p->ddR, p->dd->bFunc, Vec_IntArray(p->vCs2Glo) );
+ if ( bTemp == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during ring transfer.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Llb_NonlinImageQuit();
+ return -1;
+ }
+ Cudd_Ref( bTemp );
+ Vec_PtrPush( p->vRings, bTemp );
+
+ // check it for bad states
+ if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) )
+ {
+ assert( p->pInit->pSeqModel == NULL );
+ if ( !p->pPars->fBackward )
+ p->pInit->pSeqModel = Llb_NonlinDeriveCex( p );
+ if ( !p->pPars->fSilent )
+ {
+ if ( !p->pPars->fBackward )
+ Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", p->pInit->pSeqModel->iPo, nIters );
+ else
+ Abc_Print( 1, "Output ??? was asserted in frame %d (counter-example is not produced). ", nIters );
+ Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+ }
+ p->pPars->iFrame = nIters - 1;
+ Llb_NonlinImageQuit();
+ return 0;
+ }
+
+ // compute the next states
+ clk3 = Abc_Clock();
+ nBddSize0 = Cudd_DagSize( p->dd->bFunc );
+ bNext = Llb_NonlinImageCompute( p->dd->bFunc, p->pPars->fReorder, 0, 1, p->pOrderL ); // consumes ref
+// bNext = Llb_NonlinImage( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->dd, bCurrent,
+// p->pPars->fReorder, p->pPars->fVeryVerbose, NULL, ABC_INFINITY, p->pPars->TimeTarget );
+ if ( bNext == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation in quantification.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Llb_NonlinImageQuit();
+ return -1;
+ }
+ Cudd_Ref( bNext );
+ nBddSize = Cudd_DagSize( bNext );
+ p->timeImage += Abc_Clock() - clk3;
+
+
+ // transfer to the state manager
+ clk3 = Abc_Clock();
+ Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc2 );
+ p->ddG->bFunc2 = Extra_TransferPermute( p->dd, p->ddG, bNext, Vec_IntArray(p->vNs2Glo) );
+// p->ddG->bFunc2 = Extra_bddAndPermute( p->ddG, Cudd_Not(p->ddG->bFunc), p->dd, bNext, Vec_IntArray(p->vNs2Glo) );
+ if ( p->ddG->bFunc2 == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->dd, bNext );
+ Llb_NonlinImageQuit();
+ return -1;
+ }
+ Cudd_Ref( p->ddG->bFunc2 );
+ Cudd_RecursiveDeref( p->dd, bNext );
+ p->timeTran1 += Abc_Clock() - clk3;
+
+ // save permutation
+ NumCmp = Llb_NonlinCompPerms( p->dd, p->pOrderL2 );
+ // save order before image computation
+ memcpy( p->pOrderL2, p->dd->perm, sizeof(int) * p->dd->size );
+ // update the image computation manager
+ p->timeReo += Cudd_ReadReorderingTime(p->dd);
+ p->ddLocReos += Cudd_ReadReorderings(p->dd);
+ p->ddLocGrbs += Cudd_ReadGarbageCollections(p->dd);
+ Llb_NonlinImageQuit();
+ p->dd = Llb_NonlinImageStart( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->pOrderL, 0, p->pPars->TimeTarget );
+ if ( p->dd == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ return -1;
+ }
+ //Extra_TestAndPerm( p->ddG, Cudd_Not(p->ddG->bFunc), p->ddG->bFunc2 );
+
+ // derive new states
+ clk3 = Abc_Clock();
+ p->ddG->bFunc2 = Cudd_bddAnd( p->ddG, bTemp = p->ddG->bFunc2, Cudd_Not(p->ddG->bFunc) );
+ if ( p->ddG->bFunc2 == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->ddG, bTemp );
+ Llb_NonlinImageQuit();
+ return -1;
+ }
+ Cudd_Ref( p->ddG->bFunc2 );
+ Cudd_RecursiveDeref( p->ddG, bTemp );
+ p->timeGloba += Abc_Clock() - clk3;
+
+ if ( Cudd_IsConstant(p->ddG->bFunc2) )
+ break;
+ // add to the reached set
+ clk3 = Abc_Clock();
+ p->ddG->bFunc = Cudd_bddOr( p->ddG, bTemp = p->ddG->bFunc, p->ddG->bFunc2 );
+ if ( p->ddG->bFunc == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->ddG, bTemp );
+ Llb_NonlinImageQuit();
+ return -1;
+ }
+ Cudd_Ref( p->ddG->bFunc );
+ Cudd_RecursiveDeref( p->ddG, bTemp );
+ p->timeGloba += Abc_Clock() - clk3;
+
+ // reset permutation
+// RetValue = Cudd_CheckZeroRef( dd );
+// assert( RetValue == 0 );
+// Cudd_ShuffleHeap( dd, pOrderG );
+
+ // move new states to the working manager
+ clk3 = Abc_Clock();
+ p->dd->bFunc = Extra_TransferPermute( p->ddG, p->dd, p->ddG->bFunc2, Vec_IntArray(p->vGlo2Cs) );
+ if ( p->dd->bFunc == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Llb_NonlinImageQuit();
+ return -1;
+ }
+ Cudd_Ref( p->dd->bFunc );
+ p->timeTran2 += Abc_Clock() - clk3;
+
+ // report the results
+ if ( p->pPars->fVerbose )
+ {
+ printf( "I =%3d : ", nIters );
+ printf( "Fr =%7d ", nBddSize0 );
+ printf( "Im =%7d ", nBddSize );
+ printf( "(%4d %4d) ", p->ddLocReos, p->ddLocGrbs );
+ printf( "Rea =%6d ", Cudd_DagSize(p->ddG->bFunc) );
+ printf( "(%4d %4d) ", Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) );
+ printf( "S =%4d ", nSuppMax );
+ printf( "cL =%5d ", NumCmp );
+ printf( "cG =%5d ", Llb_NonlinCompPerms( p->ddG, p->pOrderG ) );
+ Abc_PrintTime( 1, "T", Abc_Clock() - clk2 );
+ memcpy( p->pOrderG, p->ddG->perm, sizeof(int) * p->ddG->size );
+ }
+/*
+ if ( pPars->fVerbose )
+ {
+ double nMints = Cudd_CountMinterm(ddG, bReached, Saig_ManRegNum(pAig) );
+// Extra_bddPrint( ddG, bReached );printf( "\n" );
+ printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(pAig)) );
+ fflush( stdout );
+ }
+*/
+ if ( nIters == p->pPars->nIterMax - 1 )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nIterMax );
+ p->pPars->iFrame = nIters;
+ Llb_NonlinImageQuit();
+ return -1;
+ }
+ }
+ Llb_NonlinImageQuit();
+
+ // report the stats
+ if ( p->pPars->fVerbose )
+ {
+ double nMints = Cudd_CountMinterm(p->ddG, p->ddG->bFunc, Saig_ManRegNum(p->pAig) );
+ if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax )
+ printf( "Reachability analysis is stopped after %d frames.\n", nIters );
+ else
+ printf( "Reachability analysis completed after %d frames.\n", nIters );
+ printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) );
+ fflush( stdout );
+ }
+ if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Verified only for states reachable in %d frames. ", nIters );
+ p->pPars->iFrame = p->pPars->nIterMax;
+ return -1; // undecided
+ }
+ // report
+ if ( !p->pPars->fSilent )
+ printf( "The miter is proved unreachable after %d iterations. ", nIters );
+ p->pPars->iFrame = nIters - 1;
+ Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+ return 1; // unreachable
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Mnn_t * Llb_MnnStart( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars )
+{
+ Llb_Mnn_t * p;
+ Aig_Obj_t * pObj;
+ int i;
+ p = ABC_CALLOC( Llb_Mnn_t, 1 );
+ p->pInit = pInit;
+ p->pAig = pAig;
+ p->pPars = pPars;
+ p->dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ p->ddG = Cudd_Init( Aig_ManRegNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ p->ddR = Cudd_Init( Aig_ManCiNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT );
+ Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT );
+ Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT );
+ p->vRings = Vec_PtrAlloc( 100 );
+ // create leaves
+ p->vLeaves = Vec_PtrAlloc( Aig_ManCiNum(pAig) );
+ Aig_ManForEachCi( pAig, pObj, i )
+ Vec_PtrPush( p->vLeaves, pObj );
+ // create roots
+ p->vRoots = Vec_PtrAlloc( Aig_ManCoNum(pAig) );
+ Saig_ManForEachLi( pAig, pObj, i )
+ Vec_PtrPush( p->vRoots, pObj );
+ // variables to quantify
+ p->pOrderL = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) );
+ p->pOrderL2= ABC_CALLOC( int, Aig_ManObjNumMax(pAig) );
+ p->pOrderG = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) );
+ p->pVars2Q = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) );
+ Aig_ManForEachCi( pAig, pObj, i )
+ p->pVars2Q[Aig_ObjId(pObj)] = 1;
+ for ( i = 0; i < Aig_ManObjNumMax(pAig); i++ )
+ p->pOrderL[i] = p->pOrderL2[i] = p->pOrderG[i] = i;
+ Llb_NonlinPrepareVarMap( p );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MnnStop( Llb_Mnn_t * p )
+{
+ DdNode * bTemp;
+ int i;
+ if ( p->pPars->fVerbose )
+ {
+ p->timeOther = p->timeTotal - p->timeImage - p->timeTran1 - p->timeTran2 - p->timeGloba;
+ p->timeReoG = Cudd_ReadReorderingTime(p->ddG);
+ ABC_PRTP( "Image ", p->timeImage, p->timeTotal );
+ ABC_PRTP( " build ", timeBuild, p->timeTotal );
+ ABC_PRTP( " and-ex ", timeAndEx, p->timeTotal );
+ ABC_PRTP( " other ", timeOther, p->timeTotal );
+ ABC_PRTP( "Transfer1", p->timeTran1, p->timeTotal );
+ ABC_PRTP( "Transfer2", p->timeTran2, p->timeTotal );
+ ABC_PRTP( "Global ", p->timeGloba, p->timeTotal );
+ ABC_PRTP( "Other ", p->timeOther, p->timeTotal );
+ ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal );
+ ABC_PRTP( " reo ", p->timeReo, p->timeTotal );
+ ABC_PRTP( " reoG ", p->timeReoG, p->timeTotal );
+ }
+ if ( p->ddR->bFunc )
+ Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc );
+ Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i )
+ Cudd_RecursiveDeref( p->ddR, bTemp );
+ Vec_PtrFree( p->vRings );
+ if ( p->ddG->bFunc )
+ Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc );
+ if ( p->ddG->bFunc2 )
+ Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc2 );
+// printf( "manager1\n" );
+// Extra_StopManager( p->dd );
+// printf( "manager2\n" );
+ Extra_StopManager( p->ddG );
+// printf( "manager3\n" );
+ Extra_StopManager( p->ddR );
+ Vec_IntFreeP( &p->vCs2Glo );
+ Vec_IntFreeP( &p->vNs2Glo );
+ Vec_IntFreeP( &p->vGlo2Cs );
+ Vec_IntFreeP( &p->vGlo2Ns );
+ Vec_PtrFree( p->vLeaves );
+ Vec_PtrFree( p->vRoots );
+ ABC_FREE( p->pVars2Q );
+ ABC_FREE( p->pOrderL );
+ ABC_FREE( p->pOrderL2 );
+ ABC_FREE( p->pOrderG );
+ ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds balanced cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinExperiment( Aig_Man_t * pAig, int Num )
+{
+ Llb_Mnn_t * pMnn;
+ Gia_ParLlb_t Pars, * pPars = &Pars;
+ Aig_Man_t * p;
+ abctime clk = Abc_Clock();
+
+ Llb_ManSetDefaultParams( pPars );
+ pPars->fVerbose = 1;
+
+ p = Aig_ManDupFlopsOnly( pAig );
+//Aig_ManShow( p, 0, NULL );
+ Aig_ManPrintStats( pAig );
+ Aig_ManPrintStats( p );
+
+ pMnn = Llb_MnnStart( pAig, p, pPars );
+ Llb_NonlinReachability( pMnn );
+ pMnn->timeTotal = Abc_Clock() - clk;
+ Llb_MnnStop( pMnn );
+
+ Aig_ManStop( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds balanced cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_NonlinCoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars )
+{
+ Llb_Mnn_t * pMnn;
+ Aig_Man_t * p;
+ int RetValue = -1;
+
+ p = Aig_ManDupFlopsOnly( pAig );
+//Aig_ManShow( p, 0, NULL );
+ if ( pPars->fVerbose )
+ Aig_ManPrintStats( pAig );
+ if ( pPars->fVerbose )
+ Aig_ManPrintStats( p );
+
+ if ( !pPars->fSkipReach )
+ {
+ abctime clk = Abc_Clock();
+ pMnn = Llb_MnnStart( pAig, p, pPars );
+ RetValue = Llb_NonlinReachability( pMnn );
+ pMnn->timeTotal = Abc_Clock() - clk;
+ Llb_MnnStop( pMnn );
+ }
+
+ Aig_ManStop( p );
+ return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/bdd/llb/llb4Cex.c b/src/bdd/llb/llb4Cex.c
new file mode 100644
index 00000000..18aeaf04
--- /dev/null
+++ b/src/bdd/llb/llb4Cex.c
@@ -0,0 +1,320 @@
+/**CFile****************************************************************
+
+ FileName [llb2Cex.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Non-linear quantification scheduling.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb2Cex.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+#include "sat/cnf/cnf.h"
+#include "sat/bsat/satSolver.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Translates a sequence of states into a counter-example.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Cex_t * Llb4_Nonlin4TransformCex( Aig_Man_t * pAig, Vec_Ptr_t * vStates, int iCexPo, int fVerbose )
+{
+ Abc_Cex_t * pCex;
+ Cnf_Dat_t * pCnf;
+ Vec_Int_t * vAssumps;
+ sat_solver * pSat;
+ Aig_Obj_t * pObj;
+ unsigned * pNext, * pThis;
+ int i, k, iBit, status, nRegs;//, clk = Abc_Clock();
+/*
+ Vec_PtrForEachEntry( unsigned *, vStates, pNext, i )
+ {
+ printf( "%4d : ", i );
+ Extra_PrintBinary( stdout, pNext, Aig_ManRegNum(pAig) );
+ printf( "\n" );
+ }
+*/
+ // derive SAT solver
+ nRegs = Aig_ManRegNum(pAig); pAig->nRegs = 0;
+ pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) );
+ pAig->nRegs = nRegs;
+// Cnf_DataTranformPolarity( pCnf, 0 );
+ // convert into SAT solver
+ pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+ if ( pSat == NULL )
+ {
+ printf( "Llb4_Nonlin4TransformCex(): Counter-example generation has failed.\n" );
+ Cnf_DataFree( pCnf );
+ return NULL;
+ }
+ // simplify the problem
+ status = sat_solver_simplify(pSat);
+ if ( status == 0 )
+ {
+ printf( "Llb4_Nonlin4TransformCex(): SAT solver is invalid.\n" );
+ sat_solver_delete( pSat );
+ Cnf_DataFree( pCnf );
+ return NULL;
+ }
+ // start the counter-example
+ pCex = Abc_CexAlloc( Saig_ManRegNum(pAig), Saig_ManPiNum(pAig), Vec_PtrSize(vStates) );
+ pCex->iFrame = Vec_PtrSize(vStates)-1;
+ pCex->iPo = -1;
+
+ // solve each time frame
+ iBit = Saig_ManRegNum(pAig);
+ pThis = (unsigned *)Vec_PtrEntry( vStates, 0 );
+ vAssumps = Vec_IntAlloc( 2 * Aig_ManRegNum(pAig) );
+ Vec_PtrForEachEntryStart( unsigned *, vStates, pNext, i, 1 )
+ {
+ // create assumptions
+ Vec_IntClear( vAssumps );
+ Saig_ManForEachLo( pAig, pObj, k )
+ Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Abc_InfoHasBit(pThis,k) ) );
+ Saig_ManForEachLi( pAig, pObj, k )
+ Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Abc_InfoHasBit(pNext,k) ) );
+ // solve SAT problem
+ status = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps),
+ (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+ // if the problem is SAT, get the counterexample
+ if ( status != l_True )
+ {
+ printf( "Llb4_Nonlin4TransformCex(): There is no transition between state %d and %d.\n", i-1, i );
+ Vec_IntFree( vAssumps );
+ sat_solver_delete( pSat );
+ Cnf_DataFree( pCnf );
+ ABC_FREE( pCex );
+ return NULL;
+ }
+ // get the assignment of PIs
+ Saig_ManForEachPi( pAig, pObj, k )
+ if ( sat_solver_var_value(pSat, pCnf->pVarNums[Aig_ObjId(pObj)]) )
+ Abc_InfoSetBit( pCex->pData, iBit + k );
+ // update the counter
+ iBit += Saig_ManPiNum(pAig);
+ pThis = pNext;
+ }
+
+ // add the last frame when the property fails
+ Vec_IntClear( vAssumps );
+ if ( iCexPo >= 0 )
+ {
+ Saig_ManForEachPo( pAig, pObj, k )
+ if ( k == iCexPo )
+ Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 ) );
+ }
+ else
+ {
+ Saig_ManForEachPo( pAig, pObj, k )
+ Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 ) );
+ }
+
+ // add clause
+ status = sat_solver_addclause( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps) );
+ if ( status == 0 )
+ {
+ printf( "Llb4_Nonlin4TransformCex(): The SAT solver is unsat after adding last clause.\n" );
+ Vec_IntFree( vAssumps );
+ sat_solver_delete( pSat );
+ Cnf_DataFree( pCnf );
+ ABC_FREE( pCex );
+ return NULL;
+ }
+ // create assumptions
+ Vec_IntClear( vAssumps );
+ Saig_ManForEachLo( pAig, pObj, k )
+ Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Abc_InfoHasBit(pThis,k) ) );
+ // solve the last frame
+ status = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps),
+ (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+ if ( status != l_True )
+ {
+ printf( "Llb4_Nonlin4TransformCex(): There is no last transition that makes the property fail.\n" );
+ Vec_IntFree( vAssumps );
+ sat_solver_delete( pSat );
+ Cnf_DataFree( pCnf );
+ ABC_FREE( pCex );
+ return NULL;
+ }
+ // get the assignment of PIs
+ Saig_ManForEachPi( pAig, pObj, k )
+ if ( sat_solver_var_value(pSat, pCnf->pVarNums[Aig_ObjId(pObj)]) )
+ Abc_InfoSetBit( pCex->pData, iBit + k );
+ iBit += Saig_ManPiNum(pAig);
+ assert( iBit == pCex->nBits );
+
+ // free the sat_solver
+ Vec_IntFree( vAssumps );
+ sat_solver_delete( pSat );
+ Cnf_DataFree( pCnf );
+
+ // verify counter-example
+ status = Saig_ManFindFailedPoCex( pAig, pCex );
+ if ( status >= 0 && status < Saig_ManPoNum(pAig) )
+ pCex->iPo = status;
+ else
+ {
+ printf( "Llb4_Nonlin4TransformCex(): Counter-example verification has FAILED.\n" );
+ ABC_FREE( pCex );
+ return NULL;
+ }
+ // report the results
+// if ( fVerbose )
+// Abc_PrintTime( 1, "SAT-based cex generation time", Abc_Clock() - clk );
+ return pCex;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Resimulates the counter-example.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb4_Nonlin4VerifyCex( Aig_Man_t * pAig, Abc_Cex_t * p )
+{
+ Vec_Ptr_t * vStates;
+ Aig_Obj_t * pObj, * pObjRi, * pObjRo;
+ int i, k, iBit = 0;
+ // create storage for states
+ vStates = Vec_PtrAllocSimInfo( p->iFrame+1, Abc_BitWordNum(Aig_ManRegNum(pAig)) );
+ Vec_PtrCleanSimInfo( vStates, 0, Abc_BitWordNum(Aig_ManRegNum(pAig)) );
+ // verify counter-example
+ Aig_ManCleanMarkB(pAig);
+ Aig_ManConst1(pAig)->fMarkB = 1;
+ Saig_ManForEachLo( pAig, pObj, i )
+ pObj->fMarkB = 0; //Abc_InfoHasBit(p->pData, iBit++);
+ // do not require equal flop count in the AIG and in the CEX
+ iBit = p->nRegs;
+ for ( i = 0; i <= p->iFrame; i++ )
+ {
+ // save current state
+ Saig_ManForEachLo( pAig, pObj, k )
+ if ( pObj->fMarkB )
+ Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(vStates, i), k );
+ // compute new state
+ Saig_ManForEachPi( pAig, pObj, k )
+ pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++);
+ Aig_ManForEachNode( pAig, pObj, k )
+ pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) &
+ (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj));
+ Aig_ManForEachCo( pAig, pObj, k )
+ pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj);
+ if ( i == p->iFrame )
+ break;
+ Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, k )
+ pObjRo->fMarkB = pObjRi->fMarkB;
+ }
+/*
+ {
+ unsigned * pNext;
+ Vec_PtrForEachEntry( unsigned *, vStates, pNext, i )
+ {
+ printf( "%4d : ", i );
+ Extra_PrintBinary( stdout, pNext, Aig_ManRegNum(pAig) );
+ printf( "\n" );
+ }
+ }
+*/
+ assert( iBit == p->nBits );
+// if ( Aig_ManCo(pAig, p->iPo)->fMarkB == 0 )
+// Vec_PtrFreeP( &vStates );
+ for ( i = Saig_ManPoNum(pAig) - 1; i >= 0; i-- )
+ {
+ if ( Aig_ManCo(pAig, i)->fMarkB )
+ {
+ p->iPo = i;
+ break;
+ }
+ }
+ if ( i == -1 )
+ Vec_PtrFreeP( &vStates );
+ Aig_ManCleanMarkB(pAig);
+ return vStates;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Translates a sequence of states into a counter-example.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Cex_t * Llb4_Nonlin4NormalizeCex( Aig_Man_t * pAigOrg, Aig_Man_t * pAigRpm, Abc_Cex_t * pCexRpm )
+{
+ Abc_Cex_t * pCexOrg;
+ Vec_Ptr_t * vStates;
+ // check parameters of the AIG
+ if ( Saig_ManRegNum(pAigOrg) != Saig_ManRegNum(pAigRpm) )
+ {
+ printf( "Llb4_Nonlin4NormalizeCex(): The number of flops in the original and reparametrized AIGs do not agree.\n" );
+ return NULL;
+ }
+/*
+ if ( Saig_ManRegNum(pAigRpm) != pCexRpm->nRegs )
+ {
+ printf( "Llb4_Nonlin4NormalizeCex(): The number of flops in the reparametrized AIG and in the CEX do not agree.\n" );
+ return NULL;
+ }
+*/
+ if ( Saig_ManPiNum(pAigRpm) != pCexRpm->nPis )
+ {
+ printf( "Llb4_Nonlin4NormalizeCex(): The number of PIs in the reparametrized AIG and in the CEX do not agree.\n" );
+ return NULL;
+ }
+ // get the sequence of states
+ vStates = Llb4_Nonlin4VerifyCex( pAigRpm, pCexRpm );
+ if ( vStates == NULL )
+ {
+ Abc_Print( 1, "Llb4_Nonlin4NormalizeCex(): The given CEX does not fail outputs of pAigRpm.\n" );
+ return NULL;
+ }
+ // derive updated counter-example
+ pCexOrg = Llb4_Nonlin4TransformCex( pAigOrg, vStates, pCexRpm->iPo, 0 );
+ Vec_PtrFree( vStates );
+ return pCexOrg;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/bdd/llb/llb4Cluster.c b/src/bdd/llb/llb4Cluster.c
new file mode 100644
index 00000000..7e325597
--- /dev/null
+++ b/src/bdd/llb/llb4Cluster.c
@@ -0,0 +1,452 @@
+/**CFile****************************************************************
+
+ FileName [llb2Cluster.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Non-linear quantification scheduling.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb2Cluster.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Find good static variable ordering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4FindOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter )
+{
+ Aig_Obj_t * pFanin0, * pFanin1;
+ if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+ return;
+ Aig_ObjSetTravIdCurrent( pAig, pObj );
+ assert( Llb_ObjBddVar(vOrder, pObj) < 0 );
+ if ( Aig_ObjIsCi(pObj) )
+ {
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ );
+ return;
+ }
+ // try fanins with higher level first
+ pFanin0 = Aig_ObjFanin0(pObj);
+ pFanin1 = Aig_ObjFanin1(pObj);
+// if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) )
+ if ( pFanin0->Level > pFanin1->Level )
+ {
+ Llb_Nonlin4FindOrder_rec( pAig, pFanin0, vOrder, pCounter );
+ Llb_Nonlin4FindOrder_rec( pAig, pFanin1, vOrder, pCounter );
+ }
+ else
+ {
+ Llb_Nonlin4FindOrder_rec( pAig, pFanin1, vOrder, pCounter );
+ Llb_Nonlin4FindOrder_rec( pAig, pFanin0, vOrder, pCounter );
+ }
+ if ( pObj->fMarkA )
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find good static variable ordering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_Nonlin4FindOrder( Aig_Man_t * pAig, int * pCounter )
+{
+ Vec_Int_t * vNodes = NULL;
+ Vec_Int_t * vOrder;
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ // mark nodes to exclude: AND with low level and CO drivers
+ Aig_ManCleanMarkA( pAig );
+ Aig_ManForEachNode( pAig, pObj, i )
+ if ( Aig_ObjLevel(pObj) > 3 )
+ pObj->fMarkA = 1;
+ Aig_ManForEachCo( pAig, pObj, i )
+ Aig_ObjFanin0(pObj)->fMarkA = 0;
+
+ // collect nodes in the order
+ vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) );
+ Aig_ManIncrementTravId( pAig );
+ Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) );
+// Aig_ManForEachCo( pAig, pObj, i )
+ Saig_ManForEachLi( pAig, pObj, i )
+ {
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ );
+ Llb_Nonlin4FindOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter );
+ }
+ Aig_ManForEachCi( pAig, pObj, i )
+ if ( Llb_ObjBddVar(vOrder, pObj) < 0 )
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ );
+ Aig_ManCleanMarkA( pAig );
+ Vec_IntFreeP( &vNodes );
+// assert( Counter == Aig_ManObjNum(pAig) - 1 );
+
+/*
+ Saig_ManForEachPi( pAig, pObj, i )
+ printf( "pi%d ", Llb_ObjBddVar(vOrder, pObj) );
+ printf( "\n" );
+ Saig_ManForEachLo( pAig, pObj, i )
+ printf( "lo%d ", Llb_ObjBddVar(vOrder, pObj) );
+ printf( "\n" );
+ Saig_ManForEachPo( pAig, pObj, i )
+ printf( "po%d ", Llb_ObjBddVar(vOrder, pObj) );
+ printf( "\n" );
+ Saig_ManForEachLi( pAig, pObj, i )
+ printf( "li%d ", Llb_ObjBddVar(vOrder, pObj) );
+ printf( "\n" );
+ Aig_ManForEachNode( pAig, pObj, i )
+ printf( "n%d ", Llb_ObjBddVar(vOrder, pObj) );
+ printf( "\n" );
+*/
+ if ( pCounter )
+ *pCounter = Counter;
+ return vOrder;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives BDDs for the partitions.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_Nonlin4FindPartitions_rec( DdManager * dd, Aig_Obj_t * pObj, Vec_Int_t * vOrder, Vec_Ptr_t * vRoots )
+{
+ DdNode * bBdd, * bBdd0, * bBdd1, * bPart, * vVar;
+ if ( Aig_ObjIsConst1(pObj) )
+ return Cudd_ReadOne(dd);
+ if ( Aig_ObjIsCi(pObj) )
+ return Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+ if ( pObj->pData )
+ return (DdNode *)pObj->pData;
+ if ( Aig_ObjIsCo(pObj) )
+ {
+ bBdd0 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) );
+ bPart = Cudd_bddXnor( dd, Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ), bBdd0 ); Cudd_Ref( bPart );
+ Vec_PtrPush( vRoots, bPart );
+ return NULL;
+ }
+ bBdd0 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) );
+ bBdd1 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin1(pObj), vOrder, vRoots), Aig_ObjFaninC1(pObj) );
+ bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bBdd );
+ if ( Llb_ObjBddVar(vOrder, pObj) >= 0 )
+ {
+ vVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+ bPart = Cudd_bddXnor( dd, vVar, bBdd ); Cudd_Ref( bPart );
+ Vec_PtrPush( vRoots, bPart );
+ Cudd_RecursiveDeref( dd, bBdd );
+ bBdd = vVar; Cudd_Ref( vVar );
+ }
+ pObj->pData = bBdd;
+ return bBdd;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives BDDs for the partitions.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_Nonlin4FindPartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fOutputs )
+{
+ Vec_Ptr_t * vRoots;
+ Aig_Obj_t * pObj;
+ int i;
+ Aig_ManCleanData( pAig );
+ vRoots = Vec_PtrAlloc( 100 );
+ if ( fOutputs )
+ {
+ Saig_ManForEachPo( pAig, pObj, i )
+ Llb_Nonlin4FindPartitions_rec( dd, pObj, vOrder, vRoots );
+ }
+ else
+ {
+ Saig_ManForEachLi( pAig, pObj, i )
+ Llb_Nonlin4FindPartitions_rec( dd, pObj, vOrder, vRoots );
+ }
+ Aig_ManForEachNode( pAig, pObj, i )
+ if ( pObj->pData )
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+ return vRoots;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates quantifiable variables for both types of traversal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_Nonlin4FindVars2Q( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder )
+{
+ Vec_Int_t * vVars2Q;
+ Aig_Obj_t * pObj;
+ int i;
+ vVars2Q = Vec_IntAlloc( 0 );
+ Vec_IntFill( vVars2Q, Cudd_ReadSize(dd), 1 );
+ Saig_ManForEachLo( pAig, pObj, i )
+ Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 );
+// Aig_ManForEachCo( pAig, pObj, i )
+ Saig_ManForEachLi( pAig, pObj, i )
+ Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 );
+ return vVars2Q;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates quantifiable variables for both types of traversal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_Nonlin4CountTerms( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, DdNode * bFunc, int fCo, int fFlop )
+{
+ DdNode * bSupp;
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp );
+ if ( !fCo && !fFlop )
+ {
+ Saig_ManForEachPi( pAig, pObj, i )
+ if ( Llb_ObjBddVar(vOrder, pObj) >= 0 )
+ Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) );
+ }
+ else if ( fCo && !fFlop )
+ {
+ Saig_ManForEachPo( pAig, pObj, i )
+ if ( Llb_ObjBddVar(vOrder, pObj) >= 0 )
+ Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) );
+ }
+ else if ( !fCo && fFlop )
+ {
+ Saig_ManForEachLo( pAig, pObj, i )
+ if ( Llb_ObjBddVar(vOrder, pObj) >= 0 )
+ Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) );
+ }
+ else if ( fCo && fFlop )
+ {
+ Saig_ManForEachLi( pAig, pObj, i )
+ if ( Llb_ObjBddVar(vOrder, pObj) >= 0 )
+ Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) );
+ }
+ Cudd_RecursiveDeref( dd, bSupp );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates quantifiable variables for both types of traversal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4PrintGroups( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups )
+{
+ DdNode * bTemp;
+ int i, nSuppAll, nSuppPi, nSuppPo, nSuppLi, nSuppLo, nSuppAnd;
+ Vec_PtrForEachEntry( DdNode *, vGroups, bTemp, i )
+ {
+//Extra_bddPrintSupport(dd, bTemp); printf("\n" );
+ nSuppAll = Cudd_SupportSize(dd,bTemp);
+ nSuppPi = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 0, 0);
+ nSuppPo = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 1, 0);
+ nSuppLi = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 0, 1);
+ nSuppLo = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 1, 1);
+ nSuppAnd = nSuppAll - (nSuppPi+nSuppPo+nSuppLi+nSuppLo);
+
+ if ( Cudd_DagSize(bTemp) <= 10 )
+ continue;
+
+ printf( "%4d : bdd =%6d supp =%3d ", i, Cudd_DagSize(bTemp), nSuppAll );
+ printf( "pi =%3d ", nSuppPi );
+ printf( "po =%3d ", nSuppPo );
+ printf( "lo =%3d ", nSuppLo );
+ printf( "li =%3d ", nSuppLi );
+ printf( "and =%3d", nSuppAnd );
+ printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates quantifiable variables for both types of traversal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4PrintSuppProfile( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups )
+{
+ Aig_Obj_t * pObj;
+ int i, * pSupp;
+ int nSuppAll = 0, nSuppPi = 0, nSuppPo = 0, nSuppLi = 0, nSuppLo = 0, nSuppAnd = 0;
+
+ pSupp = ABC_CALLOC( int, Cudd_ReadSize(dd) );
+ Extra_VectorSupportArray( dd, (DdNode **)Vec_PtrArray(vGroups), Vec_PtrSize(vGroups), pSupp );
+
+ Aig_ManForEachObj( pAig, pObj, i )
+ {
+ if ( Llb_ObjBddVar(vOrder, pObj) < 0 )
+ continue;
+ // remove variables that do not participate
+ if ( pSupp[Llb_ObjBddVar(vOrder, pObj)] == 0 )
+ {
+ if ( Aig_ObjIsNode(pObj) )
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), -1 );
+ continue;
+ }
+ nSuppAll++;
+ if ( Saig_ObjIsPi(pAig, pObj) )
+ nSuppPi++;
+ else if ( Saig_ObjIsLo(pAig, pObj) )
+ nSuppLo++;
+ else if ( Saig_ObjIsPo(pAig, pObj) )
+ nSuppPo++;
+ else if ( Saig_ObjIsLi(pAig, pObj) )
+ nSuppLi++;
+ else
+ nSuppAnd++;
+ }
+ ABC_FREE( pSupp );
+
+ printf( "Groups =%3d ", Vec_PtrSize(vGroups) );
+ printf( "Variables: all =%4d ", nSuppAll );
+ printf( "pi =%4d ", nSuppPi );
+ printf( "po =%4d ", nSuppPo );
+ printf( "lo =%4d ", nSuppLo );
+ printf( "li =%4d ", nSuppLi );
+ printf( "and =%4d", nSuppAnd );
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4Cluster( Aig_Man_t * pAig, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int nBddMax, int fVerbose )
+{
+ DdManager * dd;
+ Vec_Int_t * vOrder, * vVars2Q;
+ Vec_Ptr_t * vParts, * vGroups;
+ DdNode * bTemp;
+ int i, nVarNum;
+
+ // create the BDD manager
+ vOrder = Llb_Nonlin4FindOrder( pAig, &nVarNum );
+ dd = Cudd_Init( nVarNum, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+// Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+
+ vVars2Q = Llb_Nonlin4FindVars2Q( dd, pAig, vOrder );
+ vParts = Llb_Nonlin4FindPartitions( dd, pAig, vOrder, 0 );
+
+ vGroups = Llb_Nonlin4Group( dd, vParts, vVars2Q, nBddMax );
+ Vec_IntFree( vVars2Q );
+
+ Vec_PtrForEachEntry( DdNode *, vParts, bTemp, i )
+ Cudd_RecursiveDeref( dd, bTemp );
+ Vec_PtrFree( vParts );
+
+
+// if ( fVerbose )
+ Llb_Nonlin4PrintSuppProfile( dd, pAig, vOrder, vGroups );
+ if ( fVerbose )
+ printf( "Before reordering\n" );
+ if ( fVerbose )
+ Llb_Nonlin4PrintGroups( dd, pAig, vOrder, vGroups );
+
+// Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 );
+// printf( "After reordering\n" );
+// Llb_Nonlin4PrintGroups( dd, pAig, vOrder, vGroups );
+
+ if ( pvOrder )
+ *pvOrder = vOrder;
+ else
+ Vec_IntFree( vOrder );
+
+ if ( pvGroups )
+ *pvGroups = vGroups;
+ else
+ {
+ Vec_PtrForEachEntry( DdNode *, vGroups, bTemp, i )
+ Cudd_RecursiveDeref( dd, bTemp );
+ Vec_PtrFree( vGroups );
+ }
+
+ if ( pdd )
+ *pdd = dd;
+ else
+ Extra_StopManager( dd );
+// Cudd_Quit( dd );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/bdd/llb/llb4Image.c b/src/bdd/llb/llb4Image.c
new file mode 100644
index 00000000..2ba4fcfd
--- /dev/null
+++ b/src/bdd/llb/llb4Image.c
@@ -0,0 +1,863 @@
+/**CFile****************************************************************
+
+ FileName [llb3Image.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Computes image using partitioned structure.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb3Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Llb_Var_t_ Llb_Var_t;
+struct Llb_Var_t_
+{
+ int iVar; // variable number
+ int nScore; // variable score
+ Vec_Int_t * vParts; // partitions
+};
+
+typedef struct Llb_Prt_t_ Llb_Prt_t;
+struct Llb_Prt_t_
+{
+ int iPart; // partition number
+ int nSize; // the number of BDD nodes
+ DdNode * bFunc; // the partition
+ Vec_Int_t * vVars; // support
+};
+
+typedef struct Llb_Mgr_t_ Llb_Mgr_t;
+struct Llb_Mgr_t_
+{
+ DdManager * dd; // working BDD manager
+ Vec_Int_t * vVars2Q; // variables to quantify
+ int nSizeMax; // maximum size of the cluster
+ // internal
+ Llb_Prt_t ** pParts; // partitions
+ Llb_Var_t ** pVars; // variables
+ int iPartFree; // next free partition
+ int nVars; // the number of BDD variables
+ int nSuppMax; // maximum support size
+ // temporary
+ int * pSupp; // temporary support storage
+};
+
+static inline Llb_Var_t * Llb_MgrVar( Llb_Mgr_t * p, int i ) { return p->pVars[i]; }
+static inline Llb_Prt_t * Llb_MgrPart( Llb_Mgr_t * p, int i ) { return p->pParts[i]; }
+
+// iterator over vars
+#define Llb_MgrForEachVar( p, pVar, i ) \
+ for ( i = 0; (i < p->nVars) && (((pVar) = Llb_MgrVar(p, i)), 1); i++ ) if ( pVar == NULL ) {} else
+// iterator over parts
+#define Llb_MgrForEachPart( p, pPart, i ) \
+ for ( i = 0; (i < p->iPartFree) && (((pPart) = Llb_MgrPart(p, i)), 1); i++ ) if ( pPart == NULL ) {} else
+
+// iterator over vars of one partition
+#define Llb_PartForEachVar( p, pPart, pVar, i ) \
+ for ( i = 0; (i < Vec_IntSize(pPart->vVars)) && (((pVar) = Llb_MgrVar(p, Vec_IntEntry(pPart->vVars,i))), 1); i++ )
+// iterator over parts of one variable
+#define Llb_VarForEachPart( p, pVar, pPart, i ) \
+ for ( i = 0; (i < Vec_IntSize(pVar->vParts)) && (((pPart) = Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,i))), 1); i++ )
+
+// statistics
+//abctime timeBuild, timeAndEx, timeOther;
+//int nSuppMax;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Removes one variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4RemoveVar( Llb_Mgr_t * p, Llb_Var_t * pVar )
+{
+ assert( p->pVars[pVar->iVar] == pVar );
+ p->pVars[pVar->iVar] = NULL;
+ Vec_IntFree( pVar->vParts );
+ ABC_FREE( pVar );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes one partition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4RemovePart( Llb_Mgr_t * p, Llb_Prt_t * pPart )
+{
+//printf( "Removing %d\n", pPart->iPart );
+ assert( p->pParts[pPart->iPart] == pPart );
+ p->pParts[pPart->iPart] = NULL;
+ Vec_IntFree( pPart->vVars );
+ Cudd_RecursiveDeref( p->dd, pPart->bFunc );
+ ABC_FREE( pPart );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create cube with singleton variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_Nonlin4CreateCube1( Llb_Mgr_t * p, Llb_Prt_t * pPart )
+{
+ DdNode * bCube, * bTemp;
+ Llb_Var_t * pVar;
+ int i;
+ abctime TimeStop;
+ TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
+ bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube );
+ Llb_PartForEachVar( p, pPart, pVar, i )
+ {
+ assert( Vec_IntSize(pVar->vParts) > 0 );
+ if ( Vec_IntSize(pVar->vParts) != 1 )
+ continue;
+ assert( Vec_IntEntry(pVar->vParts, 0) == pPart->iPart );
+ bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ Cudd_Deref( bCube );
+ p->dd->TimeStop = TimeStop;
+ return bCube;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create cube of variables appearing only in two partitions.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_Nonlin4CreateCube2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 )
+{
+ DdNode * bCube, * bTemp;
+ Llb_Var_t * pVar;
+ int i;
+ abctime TimeStop;
+ TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
+ bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube );
+ Llb_PartForEachVar( p, pPart1, pVar, i )
+ {
+ assert( Vec_IntSize(pVar->vParts) > 0 );
+ if ( Vec_IntSize(pVar->vParts) != 2 )
+ continue;
+ if ( (Vec_IntEntry(pVar->vParts, 0) == pPart1->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart2->iPart) ||
+ (Vec_IntEntry(pVar->vParts, 0) == pPart2->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart1->iPart) )
+ {
+ bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ }
+ Cudd_Deref( bCube );
+ p->dd->TimeStop = TimeStop;
+ return bCube;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if partition has singleton variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_Nonlin4HasSingletonVars( Llb_Mgr_t * p, Llb_Prt_t * pPart )
+{
+ Llb_Var_t * pVar;
+ int i;
+ Llb_PartForEachVar( p, pPart, pVar, i )
+ if ( Vec_IntSize(pVar->vParts) == 1 )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if partition has singleton variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4Print( Llb_Mgr_t * p )
+{
+ Llb_Prt_t * pPart;
+ Llb_Var_t * pVar;
+ int i, k;
+ printf( "\n" );
+ Llb_MgrForEachVar( p, pVar, i )
+ {
+ printf( "Var %3d : ", i );
+ Llb_VarForEachPart( p, pVar, pPart, k )
+ printf( "%d ", pPart->iPart );
+ printf( "\n" );
+ }
+ Llb_MgrForEachPart( p, pPart, i )
+ {
+ printf( "Part %3d : ", i );
+ Llb_PartForEachVar( p, pPart, pVar, k )
+ printf( "%d ", pVar->iVar );
+ printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Quantifies singles belonging to one partition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_Nonlin4Quantify1( Llb_Mgr_t * p, Llb_Prt_t * pPart )
+{
+ Llb_Var_t * pVar;
+ Llb_Prt_t * pTemp;
+ Vec_Ptr_t * vSingles;
+ DdNode * bCube, * bTemp;
+ int i, RetValue, nSizeNew;
+ // create cube to be quantified
+ bCube = Llb_Nonlin4CreateCube1( p, pPart ); Cudd_Ref( bCube );
+// assert( !Cudd_IsConstant(bCube) );
+ // derive new function
+ pPart->bFunc = Cudd_bddExistAbstract( p->dd, bTemp = pPart->bFunc, bCube ); Cudd_Ref( pPart->bFunc );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->dd, bCube );
+ // get support
+ vSingles = Vec_PtrAlloc( 0 );
+ nSizeNew = Cudd_DagSize(pPart->bFunc);
+ Extra_SupportArray( p->dd, pPart->bFunc, p->pSupp );
+ Llb_PartForEachVar( p, pPart, pVar, i )
+ if ( p->pSupp[pVar->iVar] )
+ {
+ assert( Vec_IntSize(pVar->vParts) > 1 );
+ pVar->nScore -= pPart->nSize - nSizeNew;
+ }
+ else
+ {
+ RetValue = Vec_IntRemove( pVar->vParts, pPart->iPart );
+ assert( RetValue );
+ pVar->nScore -= pPart->nSize;
+ if ( Vec_IntSize(pVar->vParts) == 0 )
+ Llb_Nonlin4RemoveVar( p, pVar );
+ else if ( Vec_IntSize(pVar->vParts) == 1 )
+ Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) );
+ }
+
+ // update partition
+ pPart->nSize = nSizeNew;
+ Vec_IntClear( pPart->vVars );
+ for ( i = 0; i < p->nVars; i++ )
+ if ( p->pSupp[i] && Vec_IntEntry(p->vVars2Q, i) )
+ Vec_IntPush( pPart->vVars, i );
+ // remove other variables
+ Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i )
+ Llb_Nonlin4Quantify1( p, pTemp );
+ Vec_PtrFree( vSingles );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Quantifies singles belonging to one partition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_Nonlin4Quantify2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 )
+{
+ int fVerbose = 0;
+ Llb_Var_t * pVar;
+ Llb_Prt_t * pTemp;
+ Vec_Ptr_t * vSingles;
+ DdNode * bCube, * bFunc;
+ int i, RetValue, nSuppSize;
+// int iPart1 = pPart1->iPart;
+// int iPart2 = pPart2->iPart;
+ int liveBeg, liveEnd;
+
+ // create cube to be quantified
+ bCube = Llb_Nonlin4CreateCube2( p, pPart1, pPart2 ); Cudd_Ref( bCube );
+
+//printf( "Quantifying " ); Extra_bddPrintSupport( p->dd, bCube ); printf( "\n" );
+
+if ( fVerbose )
+{
+printf( "\n" );
+printf( "\n" );
+Llb_Nonlin4Print( p );
+printf( "Conjoining partitions %d and %d.\n", pPart1->iPart, pPart2->iPart );
+Extra_bddPrintSupport( p->dd, bCube ); printf( "\n" );
+}
+liveBeg = p->dd->keys - p->dd->dead;
+ bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube );
+liveEnd = p->dd->keys - p->dd->dead;
+//printf( "%d ", liveEnd-liveBeg );
+
+ if ( bFunc == NULL )
+ {
+ Cudd_RecursiveDeref( p->dd, bCube );
+ return 0;
+ }
+ Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( p->dd, bCube );
+
+//printf( "Creating part %d ", p->iPartFree ); Extra_bddPrintSupport( p->dd, bFunc ); printf( "\n" );
+
+//printf( "Creating %d\n", p->iPartFree );
+
+ // create new partition
+ pTemp = p->pParts[p->iPartFree] = ABC_CALLOC( Llb_Prt_t, 1 );
+ pTemp->iPart = p->iPartFree++;
+ pTemp->nSize = Cudd_DagSize(bFunc);
+ pTemp->bFunc = bFunc;
+ pTemp->vVars = Vec_IntAlloc( 8 );
+ // update variables
+ Llb_PartForEachVar( p, pPart1, pVar, i )
+ {
+ RetValue = Vec_IntRemove( pVar->vParts, pPart1->iPart );
+ assert( RetValue );
+ pVar->nScore -= pPart1->nSize;
+ }
+ // update variables
+ Llb_PartForEachVar( p, pPart2, pVar, i )
+ {
+ RetValue = Vec_IntRemove( pVar->vParts, pPart2->iPart );
+ assert( RetValue );
+ pVar->nScore -= pPart2->nSize;
+ }
+ // add variables to the new partition
+ nSuppSize = 0;
+ Extra_SupportArray( p->dd, bFunc, p->pSupp );
+ for ( i = 0; i < p->nVars; i++ )
+ {
+ nSuppSize += p->pSupp[i];
+ if ( p->pSupp[i] && Vec_IntEntry(p->vVars2Q, i) )
+ {
+ pVar = Llb_MgrVar( p, i );
+ pVar->nScore += pTemp->nSize;
+ Vec_IntPush( pVar->vParts, pTemp->iPart );
+ Vec_IntPush( pTemp->vVars, i );
+ }
+ }
+ p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize );
+ // remove variables and collect partitions with singleton variables
+ vSingles = Vec_PtrAlloc( 0 );
+ Llb_PartForEachVar( p, pPart1, pVar, i )
+ {
+ if ( Vec_IntSize(pVar->vParts) == 0 )
+ Llb_Nonlin4RemoveVar( p, pVar );
+ else if ( Vec_IntSize(pVar->vParts) == 1 )
+ {
+ if ( fVerbose )
+ printf( "Adding partition %d because of var %d.\n",
+ Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar );
+ Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) );
+ }
+ }
+ Llb_PartForEachVar( p, pPart2, pVar, i )
+ {
+ if ( pVar == NULL )
+ continue;
+ if ( Vec_IntSize(pVar->vParts) == 0 )
+ Llb_Nonlin4RemoveVar( p, pVar );
+ else if ( Vec_IntSize(pVar->vParts) == 1 )
+ {
+ if ( fVerbose )
+ printf( "Adding partition %d because of var %d.\n",
+ Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar );
+ Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) );
+ }
+ }
+ // remove partitions
+ Llb_Nonlin4RemovePart( p, pPart1 );
+ Llb_Nonlin4RemovePart( p, pPart2 );
+ // remove other variables
+if ( fVerbose )
+Llb_Nonlin4Print( p );
+ Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i )
+ {
+if ( fVerbose )
+printf( "Updating partitiong %d with singlton vars.\n", pTemp->iPart );
+ Llb_Nonlin4Quantify1( p, pTemp );
+ }
+if ( fVerbose )
+Llb_Nonlin4Print( p );
+ Vec_PtrFree( vSingles );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes volume of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4CutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ return;
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ if ( Saig_ObjIsLi(p, pObj) )
+ {
+ Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes);
+ return;
+ }
+ if ( Aig_ObjIsConst1(pObj) )
+ return;
+ assert( Aig_ObjIsNode(pObj) );
+ Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes);
+ Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes);
+ Vec_PtrPush( vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes volume of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_Nonlin4CutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper )
+{
+ Vec_Ptr_t * vNodes;
+ Aig_Obj_t * pObj;
+ int i;
+ // mark the lower cut with the traversal ID
+ Aig_ManIncrementTravId(p);
+ Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+ Aig_ObjSetTravIdCurrent( p, pObj );
+ // count the upper cut
+ vNodes = Vec_PtrAlloc( 100 );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i )
+ Llb_Nonlin4CutNodes_rec( p, pObj, vNodes );
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts non-linear quantification scheduling.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4AddPair( Llb_Mgr_t * p, int iPart, int iVar )
+{
+ if ( p->pVars[iVar] == NULL )
+ {
+ p->pVars[iVar] = ABC_CALLOC( Llb_Var_t, 1 );
+ p->pVars[iVar]->iVar = iVar;
+ p->pVars[iVar]->nScore = 0;
+ p->pVars[iVar]->vParts = Vec_IntAlloc( 8 );
+ }
+ Vec_IntPush( p->pVars[iVar]->vParts, iPart );
+ Vec_IntPush( p->pParts[iPart]->vVars, iVar );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts non-linear quantification scheduling.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4AddPartition( Llb_Mgr_t * p, int i, DdNode * bFunc )
+{
+ int k, nSuppSize;
+ assert( !Cudd_IsConstant(bFunc) );
+//printf( "Creating init %d\n", i );
+ // create partition
+ p->pParts[i] = ABC_CALLOC( Llb_Prt_t, 1 );
+ p->pParts[i]->iPart = i;
+ p->pParts[i]->bFunc = bFunc; Cudd_Ref( bFunc );
+ p->pParts[i]->vVars = Vec_IntAlloc( 8 );
+ // add support dependencies
+ nSuppSize = 0;
+ Extra_SupportArray( p->dd, bFunc, p->pSupp );
+ for ( k = 0; k < p->nVars; k++ )
+ {
+ nSuppSize += p->pSupp[k];
+ if ( p->pSupp[k] && Vec_IntEntry(p->vVars2Q, k) )
+ Llb_Nonlin4AddPair( p, i, k );
+ }
+ p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks that each var appears in at least one partition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+**********************************************************************/
+void Llb_Nonlin4CheckVars( Llb_Mgr_t * p )
+{
+ Llb_Var_t * pVar;
+ int i;
+ Llb_MgrForEachVar( p, pVar, i )
+ assert( Vec_IntSize(pVar->vParts) > 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find next partition to quantify]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_Nonlin4NextPartitions( Llb_Mgr_t * p, Llb_Prt_t ** ppPart1, Llb_Prt_t ** ppPart2 )
+{
+ Llb_Var_t * pVar, * pVarBest = NULL;
+ Llb_Prt_t * pPart, * pPart1Best = NULL, * pPart2Best = NULL;
+ int i;
+ Llb_Nonlin4CheckVars( p );
+ // find variable with minimum score
+ Llb_MgrForEachVar( p, pVar, i )
+ {
+ if ( p->nSizeMax && pVar->nScore > p->nSizeMax )
+ continue;
+// if ( pVarBest == NULL || Vec_IntSize(pVarBest->vParts) * pVarBest->nScore > Vec_IntSize(pVar->vParts) * pVar->nScore )
+ if ( pVarBest == NULL || pVarBest->nScore > pVar->nScore )
+ pVarBest = pVar;
+// printf( "%d ", pVar->nScore );
+ }
+//printf( "\n" );
+ if ( pVarBest == NULL )
+ return 0;
+ // find two partitions with minimum size
+ Llb_VarForEachPart( p, pVarBest, pPart, i )
+ {
+ if ( pPart1Best == NULL )
+ pPart1Best = pPart;
+ else if ( pPart2Best == NULL )
+ pPart2Best = pPart;
+ else if ( pPart1Best->nSize > pPart->nSize || pPart2Best->nSize > pPart->nSize )
+ {
+ if ( pPart1Best->nSize > pPart2Best->nSize )
+ pPart1Best = pPart;
+ else
+ pPart2Best = pPart;
+ }
+ }
+//printf( "Selecting %d and parts %d and %d\n", pVarBest->iVar, pPart1Best->nSize, pPart2Best->nSize );
+//Extra_bddPrintSupport( p->dd, pPart1Best->bFunc ); printf( "\n" );
+//Extra_bddPrintSupport( p->dd, pPart2Best->bFunc ); printf( "\n" );
+
+ *ppPart1 = pPart1Best;
+ *ppPart2 = pPart2Best;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recomputes scores after variable reordering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4RecomputeScores( Llb_Mgr_t * p )
+{
+ Llb_Prt_t * pPart;
+ Llb_Var_t * pVar;
+ int i, k;
+ Llb_MgrForEachPart( p, pPart, i )
+ pPart->nSize = Cudd_DagSize(pPart->bFunc);
+ Llb_MgrForEachVar( p, pVar, i )
+ {
+ pVar->nScore = 0;
+ Llb_VarForEachPart( p, pVar, pPart, k )
+ pVar->nScore += pPart->nSize;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recomputes scores after variable reordering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4VerifyScores( Llb_Mgr_t * p )
+{
+ Llb_Prt_t * pPart;
+ Llb_Var_t * pVar;
+ int i, k, nScore;
+ Llb_MgrForEachPart( p, pPart, i )
+ assert( pPart->nSize == Cudd_DagSize(pPart->bFunc) );
+ Llb_MgrForEachVar( p, pVar, i )
+ {
+ nScore = 0;
+ Llb_VarForEachPart( p, pVar, pPart, k )
+ nScore += pPart->nSize;
+ assert( nScore == pVar->nScore );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts non-linear quantification scheduling.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Mgr_t * Llb_Nonlin4Alloc( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q, int nSizeMax )
+{
+ Llb_Mgr_t * p;
+ DdNode * bFunc;
+ int i;
+ p = ABC_CALLOC( Llb_Mgr_t, 1 );
+ p->dd = dd;
+ p->nSizeMax = nSizeMax;
+ p->vVars2Q = vVars2Q;
+ p->nVars = Cudd_ReadSize(dd);
+ p->iPartFree = Vec_PtrSize(vParts);
+ p->pVars = ABC_CALLOC( Llb_Var_t *, p->nVars );
+ p->pParts = ABC_CALLOC( Llb_Prt_t *, 2 * p->iPartFree + 2 );
+ p->pSupp = ABC_ALLOC( int, Cudd_ReadSize(dd) );
+ // add pairs (refs are consumed inside)
+ Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i )
+ Llb_Nonlin4AddPartition( p, i, bFunc );
+ // add partition
+ if ( bCurrent )
+ Llb_Nonlin4AddPartition( p, p->iPartFree++, bCurrent );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops non-linear quantification scheduling.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4Free( Llb_Mgr_t * p )
+{
+ Llb_Prt_t * pPart;
+ Llb_Var_t * pVar;
+ int i;
+ Llb_MgrForEachVar( p, pVar, i )
+ Llb_Nonlin4RemoveVar( p, pVar );
+ Llb_MgrForEachPart( p, pPart, i )
+ Llb_Nonlin4RemovePart( p, pPart );
+ ABC_FREE( p->pVars );
+ ABC_FREE( p->pParts );
+ ABC_FREE( p->pSupp );
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_Nonlin4Image( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q )
+{
+ Llb_Prt_t * pPart, * pPart1, * pPart2;
+ Llb_Mgr_t * p;
+ DdNode * bFunc, * bTemp;
+ int i, nReorders;
+ // start the manager
+ p = Llb_Nonlin4Alloc( dd, vParts, bCurrent, vVars2Q, 0 );
+ // remove singles
+ Llb_MgrForEachPart( p, pPart, i )
+ if ( Llb_Nonlin4HasSingletonVars(p, pPart) )
+ Llb_Nonlin4Quantify1( p, pPart );
+ // compute scores
+ Llb_Nonlin4RecomputeScores( p );
+ // iteratively quantify variables
+ while ( Llb_Nonlin4NextPartitions(p, &pPart1, &pPart2) )
+ {
+ nReorders = Cudd_ReadReorderings(dd);
+ if ( !Llb_Nonlin4Quantify2( p, pPart1, pPart2 ) )
+ {
+ Llb_Nonlin4Free( p );
+ return NULL;
+ }
+ if ( nReorders < Cudd_ReadReorderings(dd) )
+ Llb_Nonlin4RecomputeScores( p );
+// else
+// Llb_Nonlin4VerifyScores( p );
+ }
+ // load partitions
+ bFunc = Cudd_ReadOne(p->dd); Cudd_Ref( bFunc );
+ Llb_MgrForEachPart( p, pPart, i )
+ {
+ bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+// nSuppMax = p->nSuppMax;
+ Llb_Nonlin4Free( p );
+//printf( "\n" );
+ // return
+ Cudd_Deref( bFunc );
+ return bFunc;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_Nonlin4Group( DdManager * dd, Vec_Ptr_t * vParts, Vec_Int_t * vVars2Q, int nSizeMax )
+{
+ Vec_Ptr_t * vGroups;
+ Llb_Prt_t * pPart, * pPart1, * pPart2;
+ Llb_Mgr_t * p;
+ int i, nReorders;//, clk = Abc_Clock();
+ // start the manager
+ p = Llb_Nonlin4Alloc( dd, vParts, NULL, vVars2Q, nSizeMax );
+ // remove singles
+ Llb_MgrForEachPart( p, pPart, i )
+ if ( Llb_Nonlin4HasSingletonVars(p, pPart) )
+ Llb_Nonlin4Quantify1( p, pPart );
+ // compute scores
+ Llb_Nonlin4RecomputeScores( p );
+ // iteratively quantify variables
+ while ( Llb_Nonlin4NextPartitions(p, &pPart1, &pPart2) )
+ {
+ nReorders = Cudd_ReadReorderings(dd);
+ if ( !Llb_Nonlin4Quantify2( p, pPart1, pPart2 ) )
+ {
+ Llb_Nonlin4Free( p );
+ return NULL;
+ }
+ if ( nReorders < Cudd_ReadReorderings(dd) )
+ Llb_Nonlin4RecomputeScores( p );
+// else
+// Llb_Nonlin4VerifyScores( p );
+ }
+ // load partitions
+ vGroups = Vec_PtrAlloc( 1000 );
+ Llb_MgrForEachPart( p, pPart, i )
+ {
+//printf( "Iteration %d ", pPart->iPart );
+ if ( Cudd_IsConstant(pPart->bFunc) )
+ {
+//printf( "Constant\n" );
+ assert( !Cudd_IsComplement(pPart->bFunc) );
+ continue;
+ }
+//printf( "\n" );
+ Vec_PtrPush( vGroups, pPart->bFunc );
+ Cudd_Ref( pPart->bFunc );
+//printf( "Part %d ", pPart->iPart );
+//Extra_bddPrintSupport( p->dd, pPart->bFunc ); printf( "\n" );
+ }
+ Llb_Nonlin4Free( p );
+//Abc_PrintTime( 1, "Reparametrization time", Abc_Clock() - clk );
+ return vGroups;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/bdd/llb/llb4Map.c b/src/bdd/llb/llb4Map.c
new file mode 100644
index 00000000..4487ce25
--- /dev/null
+++ b/src/bdd/llb/llb4Map.c
@@ -0,0 +1,123 @@
+/**CFile****************************************************************
+
+ FileName [llb2Map.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Non-linear quantification scheduling.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb2Map.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+#include "base/abc/abc.h"
+#include "map/if/if.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Returns internal nodes used in the mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_AigMap( Aig_Man_t * pAig, int nLutSize, int nLutMin )
+{
+ extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan );
+ extern If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars );
+ extern void Gia_ManSetIfParsDefault( void * pPars );
+ If_Par_t Pars, * pPars = &Pars;
+ If_Man_t * pIfMan;
+ If_Obj_t * pAnd;
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pNode;
+ Vec_Int_t * vNodes;
+ Aig_Obj_t * pObj;
+ int i;
+
+ // create ABC network
+ pNtk = Abc_NtkFromAigPhase( pAig );
+ assert( Abc_NtkIsStrash(pNtk) );
+
+ // derive mapping parameters
+ Gia_ManSetIfParsDefault( pPars );
+ pPars->nLutSize = nLutSize;
+
+ // get timing information
+ pPars->pTimesArr = Abc_NtkGetCiArrivalFloats(pNtk);
+ pPars->pTimesReq = Abc_NtkGetCoRequiredFloats(pNtk);
+
+ // perform LUT mapping
+ pIfMan = Abc_NtkToIf( pNtk, pPars );
+ if ( pIfMan == NULL )
+ {
+ Abc_NtkDelete( pNtk );
+ return NULL;
+ }
+ if ( !If_ManPerformMapping( pIfMan ) )
+ {
+ Abc_NtkDelete( pNtk );
+ If_ManStop( pIfMan );
+ return NULL;
+ }
+
+ // mark nodes in the AIG used in the mapping
+ Aig_ManCleanMarkA( pAig );
+ Aig_ManForEachNode( pAig, pObj, i )
+ {
+ pNode = (Abc_Obj_t *)pObj->pData;
+ if ( pNode == NULL )
+ continue;
+ pAnd = (If_Obj_t *)pNode->pCopy;
+ if ( pAnd == NULL )
+ continue;
+ if ( pAnd->nRefs > 0 && (int)If_ObjCutBest(pAnd)->nLeaves >= nLutMin )
+ pObj->fMarkA = 1;
+ }
+ Abc_NtkDelete( pNtk );
+ If_ManStop( pIfMan );
+
+ // unmark flop drivers
+ Saig_ManForEachLi( pAig, pObj, i )
+ Aig_ObjFanin0(pObj)->fMarkA = 0;
+
+ // collect mapping
+ vNodes = Vec_IntAlloc( 100 );
+ Aig_ManForEachNode( pAig, pObj, i )
+ if ( pObj->fMarkA )
+ Vec_IntPush( vNodes, Aig_ObjId(pObj) );
+ Aig_ManCleanMarkA( pAig );
+ return vNodes;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/bdd/llb/llb4Nonlin.c b/src/bdd/llb/llb4Nonlin.c
new file mode 100644
index 00000000..a9421358
--- /dev/null
+++ b/src/bdd/llb/llb4Nonlin.c
@@ -0,0 +1,1185 @@
+/**CFile****************************************************************
+
+ FileName [llb2Nonlin.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Non-linear quantification scheduling.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb2Nonlin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+#include "base/abc/abc.h"
+#include "aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Llb_Mnx_t_ Llb_Mnx_t;
+struct Llb_Mnx_t_
+{
+ // user info
+ Aig_Man_t * pAig; // AIG manager
+ Gia_ParLlb_t * pPars; // parameters
+
+ // intermediate BDDs
+ DdManager * dd; // BDD manager
+ DdNode * bBad; // bad states in terms of CIs
+ DdNode * bReached; // reached states
+ DdNode * bCurrent; // from states
+ DdNode * bNext; // to states
+ Vec_Ptr_t * vRings; // onion rings in ddR
+ Vec_Ptr_t * vRoots; // BDDs for partitions
+
+ // structural info
+ Vec_Int_t * vOrder; // for each object ID, its BDD variable number or -1
+ Vec_Int_t * vVars2Q; // 1 if variable is quantifiable; 0 othervise
+
+ abctime timeImage;
+ abctime timeRemap;
+ abctime timeReo;
+ abctime timeOther;
+ abctime timeTotal;
+};
+
+//extern int timeBuild, timeAndEx, timeOther;
+//extern int nSuppMax;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes bad in working manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_Nonlin4ComputeBad( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder )
+{
+ Vec_Ptr_t * vNodes;
+ DdNode * bBdd, * bBdd0, * bBdd1, * bTemp, * bResult, * bCube;
+ Aig_Obj_t * pObj;
+ int i;
+ Aig_ManCleanData( pAig );
+ // assign elementary variables
+ Aig_ManConst1(pAig)->pData = Cudd_ReadOne(dd);
+ Aig_ManForEachCi( pAig, pObj, i )
+ pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+ // compute internal nodes
+ vNodes = Aig_ManDfsNodes( pAig, (Aig_Obj_t **)Vec_PtrArray(pAig->vCos), Saig_ManPoNum(pAig) );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+ {
+ if ( !Aig_ObjIsNode(pObj) )
+ continue;
+ bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+ bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 );
+ if ( bBdd == NULL )
+ {
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+ if ( Aig_ObjIsNode(pObj) && pObj->pData != NULL )
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+ Vec_PtrFree( vNodes );
+ return NULL;
+ }
+ Cudd_Ref( bBdd );
+ pObj->pData = bBdd;
+ }
+ // quantify PIs of each PO
+ bResult = Cudd_ReadLogicZero( dd ); Cudd_Ref( bResult );
+ Saig_ManForEachPo( pAig, pObj, i )
+ {
+ bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bResult = Cudd_bddOr( dd, bTemp = bResult, bBdd0 );
+ if ( bResult == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bTemp );
+ break;
+ }
+ Cudd_Ref( bResult );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ // deref
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+ if ( Aig_ObjIsNode(pObj) && pObj->pData != NULL )
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+ Vec_PtrFree( vNodes );
+ if ( bResult )
+ {
+ bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube );
+ Saig_ManForEachPi( pAig, pObj, i )
+ {
+ bCube = Cudd_bddAnd( dd, bTemp = bCube, (DdNode *)pObj->pData );
+ if ( bCube == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bResult );
+ bResult = NULL;
+ break;
+ }
+ Cudd_Ref( bCube );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ if ( bResult != NULL )
+ {
+ bResult = Cudd_bddExistAbstract( dd, bTemp = bResult, bCube ); Cudd_Ref( bResult );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bCube );
+ Cudd_Deref( bResult );
+ }
+ }
+//if ( bResult )
+//printf( "Bad state = %d.\n", Cudd_DagSize(bResult) );
+ return bResult;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives BDDs for the partitions.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_Nonlin4DerivePartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder )
+{
+ Vec_Ptr_t * vRoots;
+ Aig_Obj_t * pObj;
+ DdNode * bBdd, * bBdd0, * bBdd1, * bPart;
+ int i;
+ Aig_ManCleanData( pAig );
+ // assign elementary variables
+ Aig_ManConst1(pAig)->pData = Cudd_ReadOne(dd);
+ Aig_ManForEachCi( pAig, pObj, i )
+ pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+ Aig_ManForEachNode( pAig, pObj, i )
+ if ( Llb_ObjBddVar(vOrder, pObj) >= 0 )
+ {
+ pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+ Cudd_Ref( (DdNode *)pObj->pData );
+ }
+ Saig_ManForEachLi( pAig, pObj, i )
+ pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+ // compute intermediate BDDs
+ vRoots = Vec_PtrAlloc( 100 );
+ Aig_ManForEachNode( pAig, pObj, i )
+ {
+ bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+ bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 );
+ if ( bBdd == NULL )
+ goto finish;
+ Cudd_Ref( bBdd );
+ if ( pObj->pData == NULL )
+ {
+ pObj->pData = bBdd;
+ continue;
+ }
+ // create new partition
+ bPart = Cudd_bddXnor( dd, (DdNode *)pObj->pData, bBdd );
+ if ( bPart == NULL )
+ goto finish;
+ Cudd_Ref( bPart );
+ Cudd_RecursiveDeref( dd, bBdd );
+ Vec_PtrPush( vRoots, bPart );
+//printf( "%d ", Cudd_DagSize(bPart) );
+ }
+ // compute register output BDDs
+ Saig_ManForEachLi( pAig, pObj, i )
+ {
+ bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bPart = Cudd_bddXnor( dd, (DdNode *)pObj->pData, bBdd0 );
+ if ( bPart == NULL )
+ goto finish;
+ Cudd_Ref( bPart );
+ Vec_PtrPush( vRoots, bPart );
+//printf( "%d ", Cudd_DagSize(bPart) );
+ }
+//printf( "\n" );
+ Aig_ManForEachNode( pAig, pObj, i )
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+ return vRoots;
+ // early termination
+finish:
+ Aig_ManForEachNode( pAig, pObj, i )
+ if ( pObj->pData )
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+ Vec_PtrForEachEntry( DdNode *, vRoots, bPart, i )
+ Cudd_RecursiveDeref( dd, bPart );
+ Vec_PtrFree( vRoots );
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find simple variable ordering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_Nonlin4CreateOrderSimple( Aig_Man_t * pAig )
+{
+ Vec_Int_t * vOrder;
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) );
+ Aig_ManForEachCi( pAig, pObj, i )
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ );
+ Saig_ManForEachLi( pAig, pObj, i )
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ );
+ return vOrder;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find good static variable ordering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4CreateOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter )
+{
+ Aig_Obj_t * pFanin0, * pFanin1;
+ if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+ return;
+ Aig_ObjSetTravIdCurrent( pAig, pObj );
+ assert( Llb_ObjBddVar(vOrder, pObj) < 0 );
+ if ( Aig_ObjIsCi(pObj) )
+ {
+// if ( Saig_ObjIsLo(pAig, pObj) )
+// Vec_IntWriteEntry( vOrder, Aig_ObjId(Saig_ObjLoToLi(pAig, pObj)), (*pCounter)++ );
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ );
+ return;
+ }
+ // try fanins with higher level first
+ pFanin0 = Aig_ObjFanin0(pObj);
+ pFanin1 = Aig_ObjFanin1(pObj);
+// if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) )
+ if ( pFanin0->Level > pFanin1->Level )
+ {
+ Llb_Nonlin4CreateOrder_rec( pAig, pFanin0, vOrder, pCounter );
+ Llb_Nonlin4CreateOrder_rec( pAig, pFanin1, vOrder, pCounter );
+ }
+ else
+ {
+ Llb_Nonlin4CreateOrder_rec( pAig, pFanin1, vOrder, pCounter );
+ Llb_Nonlin4CreateOrder_rec( pAig, pFanin0, vOrder, pCounter );
+ }
+ if ( pObj->fMarkA )
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collect nodes with the given fanout count.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_Nonlin4CollectHighRefNodes( Aig_Man_t * pAig, int nFans )
+{
+ Vec_Int_t * vNodes;
+ Aig_Obj_t * pObj;
+ int i;
+ Aig_ManCleanMarkA( pAig );
+ Aig_ManForEachNode( pAig, pObj, i )
+ if ( Aig_ObjRefs(pObj) >= nFans )
+ pObj->fMarkA = 1;
+ // unmark flop drivers
+ Saig_ManForEachLi( pAig, pObj, i )
+ Aig_ObjFanin0(pObj)->fMarkA = 0;
+ // collect mapping
+ vNodes = Vec_IntAlloc( 100 );
+ Aig_ManForEachNode( pAig, pObj, i )
+ if ( pObj->fMarkA )
+ Vec_IntPush( vNodes, Aig_ObjId(pObj) );
+ Aig_ManCleanMarkA( pAig );
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find good static variable ordering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_Nonlin4CreateOrder( Aig_Man_t * pAig )
+{
+ Vec_Int_t * vNodes = NULL;
+ Vec_Int_t * vOrder;
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+/*
+ // mark internal nodes to be used
+ Aig_ManCleanMarkA( pAig );
+ vNodes = Llb_Nonlin4CollectHighRefNodes( pAig, 4 );
+ Aig_ManForEachObjVec( vNodes, pAig, pObj, i )
+ pObj->fMarkA = 1;
+printf( "Techmapping added %d pivots.\n", Vec_IntSize(vNodes) );
+*/
+ // collect nodes in the order
+ vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) );
+ Aig_ManIncrementTravId( pAig );
+ Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) );
+ Saig_ManForEachLi( pAig, pObj, i )
+ {
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ );
+ Llb_Nonlin4CreateOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter );
+ }
+ Aig_ManForEachCi( pAig, pObj, i )
+ if ( Llb_ObjBddVar(vOrder, pObj) < 0 )
+ {
+// if ( Saig_ObjIsLo(pAig, pObj) )
+// Vec_IntWriteEntry( vOrder, Aig_ObjId(Saig_ObjLoToLi(pAig, pObj)), Counter++ );
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ );
+ }
+ assert( Counter <= Aig_ManCiNum(pAig) + Aig_ManRegNum(pAig) + (vNodes?Vec_IntSize(vNodes):0) );
+ Aig_ManCleanMarkA( pAig );
+ Vec_IntFreeP( &vNodes );
+ return vOrder;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Creates quantifiable varaibles for both types of traversal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_Nonlin4CreateVars2Q( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fBackward )
+{
+ Vec_Int_t * vVars2Q;
+ Aig_Obj_t * pObjLi, * pObjLo;
+ int i;
+ vVars2Q = Vec_IntAlloc( 0 );
+ Vec_IntFill( vVars2Q, Cudd_ReadSize(dd), 1 );
+ Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
+ Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, fBackward ? pObjLo : pObjLi), 0 );
+ return vVars2Q;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute initial state in terms of current state variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4SetupVarMap( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder )
+{
+ DdNode ** pVarsX, ** pVarsY;
+ Aig_Obj_t * pObjLo, * pObjLi;
+ int i;
+ pVarsX = ABC_ALLOC( DdNode *, Cudd_ReadSize(dd) );
+ pVarsY = ABC_ALLOC( DdNode *, Cudd_ReadSize(dd) );
+ Saig_ManForEachLiLo( pAig, pObjLo, pObjLi, i )
+ {
+ assert( Llb_ObjBddVar(vOrder, pObjLo) >= 0 );
+ assert( Llb_ObjBddVar(vOrder, pObjLi) >= 0 );
+ pVarsX[i] = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLo) );
+ pVarsY[i] = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLi) );
+ }
+ Cudd_SetVarMap( dd, pVarsX, pVarsY, Aig_ManRegNum(pAig) );
+ ABC_FREE( pVarsX );
+ ABC_FREE( pVarsY );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute initial state in terms of current state variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_Nonlin4ComputeInitState( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fBackward )
+{
+ Aig_Obj_t * pObjLi, * pObjLo;
+ DdNode * bRes, * bVar, * bTemp;
+ int i;
+ abctime TimeStop;
+ TimeStop = dd->TimeStop; dd->TimeStop = 0;
+ bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes );
+ Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
+ {
+ bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, fBackward? pObjLi : pObjLo) );
+ bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bRes );
+ dd->TimeStop = TimeStop;
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute initial state in terms of current state variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_Nonlin4ComputeCube( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, char * pValues, int Flag )
+{
+ Aig_Obj_t * pObjLo, * pObjLi, * pObjTemp;
+ DdNode * bRes, * bVar, * bTemp;
+ int i;
+ abctime TimeStop;
+ TimeStop = dd->TimeStop; dd->TimeStop = 0;
+ bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes );
+ Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
+ {
+ if ( Flag )
+ pObjTemp = pObjLo, pObjLo = pObjLi, pObjLi = pObjTemp;
+ // get the correspoding flop input variable
+ bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLi) );
+ if ( pValues[Llb_ObjBddVar(vOrder, pObjLo)] != 1 )
+ bVar = Cudd_Not(bVar);
+ // create cube
+ bRes = Cudd_bddAnd( dd, bTemp = bRes, bVar ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bRes );
+ dd->TimeStop = TimeStop;
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute initial state in terms of current state variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4RecordState( Aig_Man_t * pAig, Vec_Int_t * vOrder, unsigned * pState, char * pValues, int fBackward )
+{
+ Aig_Obj_t * pObjLo, * pObjLi;
+ int i;
+ Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
+ if ( pValues[Llb_ObjBddVar(vOrder, fBackward? pObjLi : pObjLo)] == 1 )
+ Abc_InfoSetBit( pState, i );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Multiply every partition by the cube.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_Nonlin4Multiply( DdManager * dd, DdNode * bCube, Vec_Ptr_t * vParts )
+{
+ Vec_Ptr_t * vNew;
+ DdNode * bTemp, * bFunc;
+ int i;
+ vNew = Vec_PtrAlloc( Vec_PtrSize(vParts) );
+ Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i )
+ {
+ bTemp = Cudd_bddAnd( dd, bFunc, bCube ); Cudd_Ref( bTemp );
+ Vec_PtrPush( vNew, bTemp );
+ }
+ return vNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Multiply every partition by the cube.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4Deref( DdManager * dd, Vec_Ptr_t * vParts )
+{
+ DdNode * bFunc;
+ int i;
+ Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i )
+ Cudd_RecursiveDeref( dd, bFunc );
+ Vec_PtrFree( vParts );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives counter-example by backward reachability.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_Nonlin4DeriveCex( Llb_Mnx_t * p, int fBackward, int fVerbose )
+{
+ Vec_Int_t * vVars2Q;
+ Vec_Ptr_t * vStates, * vRootsNew;
+ Aig_Obj_t * pObj;
+ DdNode * bState = NULL, * bImage, * bOneCube, * bRing;
+ int i, v, RetValue;//, clk = Abc_Clock();
+ char * pValues;
+ assert( Vec_PtrSize(p->vRings) > 0 );
+ // disable the timeout
+ p->dd->TimeStop = 0;
+
+ // start the state set
+ vStates = Vec_PtrAllocSimInfo( Vec_PtrSize(p->vRings), Abc_BitWordNum(Aig_ManRegNum(p->pAig)) );
+ Vec_PtrCleanSimInfo( vStates, 0, Abc_BitWordNum(Aig_ManRegNum(p->pAig)) );
+ if ( fBackward )
+ Vec_PtrReverseOrder( vStates );
+
+ // get the last cube
+ pValues = ABC_ALLOC( char, Cudd_ReadSize(p->dd) );
+ bOneCube = Cudd_bddIntersect( p->dd, (DdNode *)Vec_PtrEntryLast(p->vRings), p->bBad ); Cudd_Ref( bOneCube );
+ RetValue = Cudd_bddPickOneCube( p->dd, bOneCube, pValues );
+ Cudd_RecursiveDeref( p->dd, bOneCube );
+ assert( RetValue );
+
+ // record the cube
+ Llb_Nonlin4RecordState( p->pAig, p->vOrder, (unsigned *)Vec_PtrEntryLast(vStates), pValues, fBackward );
+
+ // write state in terms of NS variables
+ if ( Vec_PtrSize(p->vRings) > 1 )
+ {
+ bState = Llb_Nonlin4ComputeCube( p->dd, p->pAig, p->vOrder, pValues, fBackward ); Cudd_Ref( bState );
+ }
+ // perform backward analysis
+ vVars2Q = Llb_Nonlin4CreateVars2Q( p->dd, p->pAig, p->vOrder, !fBackward );
+ Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v )
+ {
+ if ( v == Vec_PtrSize(p->vRings) - 1 )
+ continue;
+
+ // preprocess partitions
+ vRootsNew = Llb_Nonlin4Multiply( p->dd, bState, p->vRoots );
+ Cudd_RecursiveDeref( p->dd, bState );
+
+ // compute the next states
+ bImage = Llb_Nonlin4Image( p->dd, vRootsNew, NULL, vVars2Q ); Cudd_Ref( bImage );
+ Llb_Nonlin4Deref( p->dd, vRootsNew );
+
+ // intersect with the previous set
+ bOneCube = Cudd_bddIntersect( p->dd, bImage, bRing ); Cudd_Ref( bOneCube );
+ Cudd_RecursiveDeref( p->dd, bImage );
+
+ // find any assignment of the BDD
+ RetValue = Cudd_bddPickOneCube( p->dd, bOneCube, pValues );
+ Cudd_RecursiveDeref( p->dd, bOneCube );
+ assert( RetValue );
+
+ // record the cube
+ Llb_Nonlin4RecordState( p->pAig, p->vOrder, (unsigned *)Vec_PtrEntry(vStates, v), pValues, fBackward );
+
+ // check that we get the init state
+ if ( v == 0 )
+ {
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ assert( fBackward || pValues[Llb_ObjBddVar(p->vOrder, pObj)] == 0 );
+ break;
+ }
+
+ // write state in terms of NS variables
+ bState = Llb_Nonlin4ComputeCube( p->dd, p->pAig, p->vOrder, pValues, fBackward ); Cudd_Ref( bState );
+ }
+ Vec_IntFree( vVars2Q );
+ ABC_FREE( pValues );
+ if ( fBackward )
+ Vec_PtrReverseOrder( vStates );
+// if ( fVerbose )
+// Abc_PrintTime( 1, "BDD-based cex generation time", Abc_Clock() - clk );
+ return vStates;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Perform reachability with hints.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_Nonlin4Reachability( Llb_Mnx_t * p )
+{
+ DdNode * bAux;
+ int nIters, nBddSizeFr = 0, nBddSizeTo = 0, nBddSizeTo2 = 0;
+ abctime clkTemp, clkIter, clk = Abc_Clock();
+ assert( Aig_ManRegNum(p->pAig) > 0 );
+
+ if ( p->pPars->fBackward )
+ {
+ // create bad state in the ring manager
+ if ( !p->pPars->fSkipOutCheck )
+ {
+ p->bBad = Llb_Nonlin4ComputeInitState( p->dd, p->pAig, p->vOrder, p->pPars->fBackward ); Cudd_Ref( p->bBad );
+ }
+ // create init state
+ if ( p->pPars->fCluster )
+ p->bCurrent = p->dd->bFunc, p->dd->bFunc = NULL;
+ else
+ {
+ p->bCurrent = Llb_Nonlin4ComputeBad( p->dd, p->pAig, p->vOrder );
+ if ( p->bCurrent == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = -1;
+ return -1;
+ }
+ Cudd_Ref( p->bCurrent );
+ }
+ // remap into the next states
+ p->bCurrent = Cudd_bddVarMap( p->dd, bAux = p->bCurrent );
+ if ( p->bCurrent == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during remapping bad states.\n", p->pPars->TimeLimit );
+ Cudd_RecursiveDeref( p->dd, bAux );
+ p->pPars->iFrame = -1;
+ return -1;
+ }
+ Cudd_Ref( p->bCurrent );
+ Cudd_RecursiveDeref( p->dd, bAux );
+ }
+ else
+ {
+ // create bad state in the ring manager
+ if ( !p->pPars->fSkipOutCheck )
+ {
+ if ( p->pPars->fCluster )
+ p->bBad = p->dd->bFunc, p->dd->bFunc = NULL;
+ else
+ {
+ p->bBad = Llb_Nonlin4ComputeBad( p->dd, p->pAig, p->vOrder );
+ if ( p->bBad == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = -1;
+ return -1;
+ }
+ Cudd_Ref( p->bBad );
+ }
+ }
+ else if ( p->dd->bFunc )
+ Cudd_RecursiveDeref( p->dd, p->dd->bFunc ), p->dd->bFunc = NULL;
+ // compute the starting set of states
+ p->bCurrent = Llb_Nonlin4ComputeInitState( p->dd, p->pAig, p->vOrder, p->pPars->fBackward ); Cudd_Ref( p->bCurrent );
+ }
+ // perform iterations
+ p->bReached = p->bCurrent; Cudd_Ref( p->bReached );
+ for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ )
+ {
+ clkIter = Abc_Clock();
+ // check the runtime limit
+ if ( p->pPars->TimeLimit && Abc_Clock() > p->pPars->TimeTarget )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ return -1;
+ }
+
+ // save the onion ring
+ Vec_PtrPush( p->vRings, p->bCurrent ); Cudd_Ref( p->bCurrent );
+
+ // check it for bad states
+ if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->dd, p->bCurrent, Cudd_Not(p->bBad) ) )
+ {
+ Vec_Ptr_t * vStates;
+ assert( p->pAig->pSeqModel == NULL );
+ vStates = Llb_Nonlin4DeriveCex( p, p->pPars->fBackward, p->pPars->fVerbose );
+ p->pAig->pSeqModel = Llb4_Nonlin4TransformCex( p->pAig, vStates, -1, p->pPars->fVerbose );
+ Vec_PtrFreeP( &vStates );
+ if ( !p->pPars->fSilent )
+ {
+ Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", p->pAig->pSeqModel->iPo, p->pAig->pName, nIters );
+ Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+ }
+ p->pPars->iFrame = nIters - 1;
+ return 0;
+ }
+
+ // compute the next states
+ clkTemp = Abc_Clock();
+ p->bNext = Llb_Nonlin4Image( p->dd, p->vRoots, p->bCurrent, p->vVars2Q );
+ if ( p->bNext == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation in quantification.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ return -1;
+ }
+ Cudd_Ref( p->bNext );
+ p->timeImage += Abc_Clock() - clkTemp;
+
+ // remap into current states
+ clkTemp = Abc_Clock();
+ p->bNext = Cudd_bddVarMap( p->dd, bAux = p->bNext );
+ if ( p->bNext == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during remapping next states.\n", p->pPars->TimeLimit );
+ Cudd_RecursiveDeref( p->dd, bAux );
+ p->pPars->iFrame = nIters - 1;
+ return -1;
+ }
+ Cudd_Ref( p->bNext );
+ Cudd_RecursiveDeref( p->dd, bAux );
+ p->timeRemap += Abc_Clock() - clkTemp;
+
+ // collect statistics
+ if ( p->pPars->fVerbose )
+ {
+ nBddSizeFr = Cudd_DagSize( p->bCurrent );
+ nBddSizeTo = Cudd_DagSize( bAux );
+ nBddSizeTo2 = Cudd_DagSize( p->bNext );
+ }
+ Cudd_RecursiveDeref( p->dd, p->bCurrent ); p->bCurrent = NULL;
+
+ // derive new states
+ p->bCurrent = Cudd_bddAnd( p->dd, p->bNext, Cudd_Not(p->bReached) );
+ if ( p->bCurrent == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ return -1;
+ }
+ Cudd_Ref( p->bCurrent );
+ Cudd_RecursiveDeref( p->dd, p->bNext ); p->bNext = NULL;
+ if ( Cudd_IsConstant(p->bCurrent) )
+ break;
+/*
+ // reduce BDD size using constrain // Cudd_bddRestrict
+ p->bCurrent = Cudd_bddRestrict( p->dd, bAux = p->bCurrent, Cudd_Not(p->bReached) );
+ Cudd_Ref( p->bCurrent );
+printf( "Before = %d. After = %d.\n", Cudd_DagSize(bAux), Cudd_DagSize(p->bCurrent) );
+ Cudd_RecursiveDeref( p->dd, bAux );
+*/
+
+ // add to the reached set
+ p->bReached = Cudd_bddOr( p->dd, bAux = p->bReached, p->bCurrent );
+ if ( p->bReached == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->dd, bAux );
+ return -1;
+ }
+ Cudd_Ref( p->bReached );
+ Cudd_RecursiveDeref( p->dd, bAux );
+
+
+ // report the results
+ if ( p->pPars->fVerbose )
+ {
+ printf( "I =%5d : ", nIters );
+ printf( "Fr =%7d ", nBddSizeFr );
+ printf( "ImNs =%7d ", nBddSizeTo );
+ printf( "ImCs =%7d ", nBddSizeTo2 );
+ printf( "Rea =%7d ", Cudd_DagSize(p->bReached) );
+ printf( "(%4d %4d) ", Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) );
+ Abc_PrintTime( 1, "T", Abc_Clock() - clkIter );
+ }
+/*
+ if ( pPars->fVerbose )
+ {
+ double nMints = Cudd_CountMinterm(p->dd, bReached, Saig_ManRegNum(p->pAig) );
+// Extra_bddPrint( p->dd, bReached );printf( "\n" );
+ printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) );
+ fflush( stdout );
+ }
+*/
+ if ( nIters == p->pPars->nIterMax - 1 )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nIterMax );
+ p->pPars->iFrame = nIters;
+ return -1;
+ }
+ }
+
+ // report the stats
+ if ( p->pPars->fVerbose )
+ {
+ double nMints = Cudd_CountMinterm(p->dd, p->bReached, Saig_ManRegNum(p->pAig) );
+ if ( p->bCurrent && Cudd_IsConstant(p->bCurrent) )
+ printf( "Reachability analysis completed after %d frames.\n", nIters );
+ else
+ printf( "Reachability analysis is stopped after %d frames.\n", nIters );
+ printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) );
+ fflush( stdout );
+ }
+ if ( p->bCurrent == NULL || !Cudd_IsConstant(p->bCurrent) )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Verified only for states reachable in %d frames. ", nIters );
+ p->pPars->iFrame = p->pPars->nIterMax;
+ return -1; // undecided
+ }
+ // report
+ if ( !p->pPars->fSilent )
+ printf( "The miter is proved unreachable after %d iterations. ", nIters );
+ if ( !p->pPars->fSilent )
+ Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+ p->pPars->iFrame = nIters - 1;
+ return 1; // unreachable
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reorders BDDs in the working manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4Reorder( DdManager * dd, int fTwice, int fVerbose )
+{
+ abctime clk = Abc_Clock();
+ if ( fVerbose )
+ Abc_Print( 1, "Reordering... Before =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+ Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+ if ( fVerbose )
+ Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+ if ( fTwice )
+ {
+ Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+ if ( fVerbose )
+ Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+ }
+ if ( fVerbose )
+ Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Mnx_t * Llb_MnxStart( Aig_Man_t * pAig, Gia_ParLlb_t * pPars )
+{
+ Llb_Mnx_t * p;
+
+ p = ABC_CALLOC( Llb_Mnx_t, 1 );
+ p->pAig = pAig;
+ p->pPars = pPars;
+
+ // compute time to stop
+ p->pPars->TimeTarget = p->pPars->TimeLimit ? p->pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0;
+
+ if ( pPars->fCluster )
+ {
+// Llb_Nonlin4Cluster( p->pAig, &p->dd, &p->vOrder, &p->vRoots, pPars->nBddMax, pPars->fVerbose );
+// Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT );
+ Llb4_Nonlin4Sweep( p->pAig, pPars->nBddMax, pPars->nClusterMax, &p->dd, &p->vOrder, &p->vRoots, pPars->fVerbose );
+ // set the stop time parameter
+ p->dd->TimeStop = p->pPars->TimeTarget;
+ }
+ else
+ {
+// p->vOrder = Llb_Nonlin4CreateOrderSimple( pAig );
+ p->vOrder = Llb_Nonlin4CreateOrder( pAig );
+ p->dd = Cudd_Init( Vec_IntCountPositive(p->vOrder) + 1, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT );
+ Cudd_SetMaxGrowth( p->dd, 1.05 );
+ // set the stop time parameter
+ p->dd->TimeStop = p->pPars->TimeTarget;
+ p->vRoots = Llb_Nonlin4DerivePartitions( p->dd, pAig, p->vOrder );
+ }
+
+ Llb_Nonlin4SetupVarMap( p->dd, pAig, p->vOrder );
+ p->vVars2Q = Llb_Nonlin4CreateVars2Q( p->dd, pAig, p->vOrder, p->pPars->fBackward );
+ p->vRings = Vec_PtrAlloc( 100 );
+
+ if ( pPars->fReorder )
+ Llb_Nonlin4Reorder( p->dd, 0, 1 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MnxStop( Llb_Mnx_t * p )
+{
+ DdNode * bTemp;
+ int i;
+ if ( p->pPars->fVerbose )
+ {
+ p->timeReo = Cudd_ReadReorderingTime(p->dd);
+ p->timeOther = p->timeTotal - p->timeImage - p->timeRemap;
+ ABC_PRTP( "Image ", p->timeImage, p->timeTotal );
+ ABC_PRTP( "Remap ", p->timeRemap, p->timeTotal );
+ ABC_PRTP( "Other ", p->timeOther, p->timeTotal );
+ ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal );
+ ABC_PRTP( " reo ", p->timeReo, p->timeTotal );
+ }
+ // remove BDDs
+ if ( p->bBad )
+ Cudd_RecursiveDeref( p->dd, p->bBad );
+ if ( p->bReached )
+ Cudd_RecursiveDeref( p->dd, p->bReached );
+ if ( p->bCurrent )
+ Cudd_RecursiveDeref( p->dd, p->bCurrent );
+ if ( p->bNext )
+ Cudd_RecursiveDeref( p->dd, p->bNext );
+ if ( p->vRings )
+ Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i )
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ if ( p->vRoots )
+ Vec_PtrForEachEntry( DdNode *, p->vRoots, bTemp, i )
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ // remove arrays
+ Vec_PtrFreeP( &p->vRings );
+ Vec_PtrFreeP( &p->vRoots );
+//Cudd_PrintInfo( p->dd, stdout );
+ Extra_StopManager( p->dd );
+ Vec_IntFreeP( &p->vOrder );
+ Vec_IntFreeP( &p->vVars2Q );
+ ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MnxCheckNextStateVars( Llb_Mnx_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i, Counter0 = 0, Counter1 = 0;
+ Saig_ManForEachLi( p->pAig, pObj, i )
+ if ( Saig_ObjIsLo(p->pAig, Aig_ObjFanin0(pObj)) )
+ {
+ if ( Aig_ObjFaninC0(pObj) )
+ Counter0++;
+ else
+ Counter1++;
+ }
+ printf( "Total = %d. Direct LO = %d. Compl LO = %d.\n", Aig_ManRegNum(p->pAig), Counter1, Counter0 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds balanced cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars )
+{
+ Llb_Mnx_t * pMnn;
+ int RetValue = -1;
+ if ( pPars->fVerbose )
+ Aig_ManPrintStats( pAig );
+ if ( pPars->fCluster && Aig_ManObjNum(pAig) >= (1 << 15) )
+ {
+ printf( "The number of objects is more than 2^15. Clustering cannot be used.\n" );
+ return RetValue;
+ }
+ {
+ abctime clk = Abc_Clock();
+ pMnn = Llb_MnxStart( pAig, pPars );
+//Llb_MnxCheckNextStateVars( pMnn );
+ if ( !pPars->fSkipReach )
+ RetValue = Llb_Nonlin4Reachability( pMnn );
+ pMnn->timeTotal = Abc_Clock() - clk;
+ Llb_MnxStop( pMnn );
+ }
+ return RetValue;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Takes an AIG and returns an AIG representing reachable states.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Llb_ReachableStates( Aig_Man_t * pAig )
+{
+ extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+ Vec_Int_t * vPermute;
+ Vec_Ptr_t * vNames;
+ Gia_ParLlb_t Pars, * pPars = &Pars;
+ DdManager * dd;
+ DdNode * bReached;
+ Llb_Mnx_t * pMnn;
+ Abc_Ntk_t * pNtk, * pNtkMuxes;
+ Aig_Obj_t * pObj;
+ int i, RetValue;
+ abctime clk = Abc_Clock();
+
+ // create parameters
+ Llb_ManSetDefaultParams( pPars );
+ pPars->fSkipOutCheck = 1;
+ pPars->fCluster = 0;
+ pPars->fReorder = 0;
+ pPars->fSilent = 1;
+ pPars->nBddMax = 100;
+ pPars->nClusterMax = 500;
+
+ // run reachability
+ pMnn = Llb_MnxStart( pAig, pPars );
+ RetValue = Llb_Nonlin4Reachability( pMnn );
+ assert( RetValue == 1 );
+
+ // print BDD
+// Extra_bddPrint( pMnn->dd, pMnn->bReached );
+// Extra_bddPrintSupport( pMnn->dd, pMnn->bReached );
+// printf( "\n" );
+
+ // collect flop output variables
+ vPermute = Vec_IntStartFull( Cudd_ReadSize(pMnn->dd) );
+ Saig_ManForEachLo( pAig, pObj, i )
+ Vec_IntWriteEntry( vPermute, Llb_ObjBddVar(pMnn->vOrder, pObj), i );
+
+ // transfer the reached state BDD into the new manager
+ dd = Cudd_Init( Saig_ManRegNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+ bReached = Extra_TransferPermute( pMnn->dd, dd, pMnn->bReached, Vec_IntArray(vPermute) ); Cudd_Ref( bReached );
+ Vec_IntFree( vPermute );
+ assert( Cudd_ReadSize(dd) == Saig_ManRegNum(pAig) );
+
+ // quit reachability engine
+ pMnn->timeTotal = Abc_Clock() - clk;
+ Llb_MnxStop( pMnn );
+
+ // derive the network
+ vNames = Abc_NodeGetFakeNames( Saig_ManRegNum(pAig) );
+ pNtk = Abc_NtkDeriveFromBdd( dd, bReached, "reached", vNames );
+ Abc_NodeFreeNames( vNames );
+ Cudd_RecursiveDeref( dd, bReached );
+ Cudd_Quit( dd );
+
+ // convert
+ pNtkMuxes = Abc_NtkBddToMuxes( pNtk );
+ Abc_NtkDelete( pNtk );
+ pNtk = Abc_NtkStrash( pNtkMuxes, 0, 1, 0 );
+ Abc_NtkDelete( pNtkMuxes );
+ pAig = Abc_NtkToDar( pNtk, 0, 0 );
+ Abc_NtkDelete( pNtk );
+ return pAig;
+}
+Gia_Man_t * Llb_ReachableStatesGia( Gia_Man_t * p )
+{
+ Gia_Man_t * pNew;
+ Aig_Man_t * pAig, * pReached;
+ pAig = Gia_ManToAigSimple( p );
+ pReached = Llb_ReachableStates( pAig );
+ Aig_ManStop( pAig );
+ pNew = Gia_ManFromAigSimple( pReached );
+ Aig_ManStop( pReached );
+ return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/bdd/llb/llb4Sweep.c b/src/bdd/llb/llb4Sweep.c
new file mode 100644
index 00000000..6b318572
--- /dev/null
+++ b/src/bdd/llb/llb4Sweep.c
@@ -0,0 +1,589 @@
+/**CFile****************************************************************
+
+ FileName [llb2Sweep.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Non-linear quantification scheduling.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb2Sweep.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Find good static variable ordering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4SweepOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter, int fSaveAll )
+{
+ Aig_Obj_t * pFanin0, * pFanin1;
+ if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+ return;
+ Aig_ObjSetTravIdCurrent( pAig, pObj );
+ assert( Llb_ObjBddVar(vOrder, pObj) < 0 );
+ if ( Aig_ObjIsCi(pObj) )
+ {
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ );
+ return;
+ }
+ // try fanins with higher level first
+ pFanin0 = Aig_ObjFanin0(pObj);
+ pFanin1 = Aig_ObjFanin1(pObj);
+// if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) )
+ if ( pFanin0->Level > pFanin1->Level )
+ {
+ Llb_Nonlin4SweepOrder_rec( pAig, pFanin0, vOrder, pCounter, fSaveAll );
+ Llb_Nonlin4SweepOrder_rec( pAig, pFanin1, vOrder, pCounter, fSaveAll );
+ }
+ else
+ {
+ Llb_Nonlin4SweepOrder_rec( pAig, pFanin1, vOrder, pCounter, fSaveAll );
+ Llb_Nonlin4SweepOrder_rec( pAig, pFanin0, vOrder, pCounter, fSaveAll );
+ }
+ if ( fSaveAll || pObj->fMarkA )
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find good static variable ordering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_Nonlin4SweepOrder( Aig_Man_t * pAig, int * pCounter, int fSaveAll )
+{
+ Vec_Int_t * vOrder;
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ // collect nodes in the order
+ vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) );
+ Aig_ManIncrementTravId( pAig );
+ Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) );
+ Aig_ManForEachCo( pAig, pObj, i )
+ {
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ );
+ Llb_Nonlin4SweepOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter, fSaveAll );
+ }
+ Aig_ManForEachCi( pAig, pObj, i )
+ if ( Llb_ObjBddVar(vOrder, pObj) < 0 )
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ );
+// assert( Counter == Aig_ManObjNum(pAig) - 1 ); // no dangling nodes
+ if ( pCounter )
+ *pCounter = Counter - Aig_ManCiNum(pAig) - Aig_ManCoNum(pAig);
+ return vOrder;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs BDD sweep on the netlist.]
+
+ Description [Returns AIG with internal cut points labeled with fMarkA.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb4_Nonlin4SweepCutpoints( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nBddLimit, int fVerbose )
+{
+ DdManager * dd;
+ DdNode * bFunc0, * bFunc1, * bFunc;
+ Aig_Obj_t * pObj;
+ int i, Counter = 0, Counter1 = 0;
+ dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ // assign elementary variables
+ Aig_ManCleanData( pAig );
+ Aig_ManForEachCi( pAig, pObj, i )
+ pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+ // sweep internal nodes
+ Aig_ManForEachNode( pAig, pObj, i )
+ {
+/*
+ if ( pObj->nRefs >= 4 )
+ {
+ bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); Cudd_Ref( bFunc );
+ pObj->pData = bFunc;
+ Counter1++;
+ continue;
+ }
+*/
+ bFunc0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bFunc1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+ bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
+ if ( Cudd_DagSize(bFunc) > nBddLimit )
+ {
+// if ( fVerbose )
+// printf( "Node %5d : Beg =%5d. ", i, Cudd_DagSize(bFunc) );
+
+ // add cutpoint at a larger one
+ Cudd_RecursiveDeref( dd, bFunc );
+ if ( Cudd_DagSize(bFunc0) >= Cudd_DagSize(bFunc1) )
+ {
+ Cudd_RecursiveDeref( dd, (DdNode *)Aig_ObjFanin0(pObj)->pData );
+ bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, Aig_ObjFanin0(pObj)) );
+ Aig_ObjFanin0(pObj)->pData = bFunc; Cudd_Ref( bFunc );
+ Aig_ObjFanin0(pObj)->fMarkA = 1;
+
+// if ( fVerbose )
+// printf( "Ref =%3d ", Aig_ObjFanin0(pObj)->nRefs );
+ }
+ else
+ {
+ Cudd_RecursiveDeref( dd, (DdNode *)Aig_ObjFanin1(pObj)->pData );
+ bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, Aig_ObjFanin1(pObj)) );
+ Aig_ObjFanin1(pObj)->pData = bFunc; Cudd_Ref( bFunc );
+ Aig_ObjFanin1(pObj)->fMarkA = 1;
+
+// if ( fVerbose )
+// printf( "Ref =%3d ", Aig_ObjFanin1(pObj)->nRefs );
+ }
+ // perform new operation
+ bFunc0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bFunc1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+ bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
+// assert( Cudd_DagSize(bFunc) <= nBddLimit );
+
+// if ( fVerbose )
+// printf( "End =%5d.\n", Cudd_DagSize(bFunc) );
+ Counter++;
+ }
+ pObj->pData = bFunc;
+//printf( "%d ", Cudd_DagSize(bFunc) );
+ }
+//printf( "\n" );
+ // clean up
+ Aig_ManForEachNode( pAig, pObj, i )
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+ Extra_StopManager( dd );
+// Aig_ManCleanMarkA( pAig );
+ if ( fVerbose )
+ printf( "Added %d cut points. Used %d high fanout points.\n", Counter, Counter1 );
+ return Counter + Counter1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives BDDs for the partitions.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_Nonlin4SweepPartitions_rec( DdManager * dd, Aig_Obj_t * pObj, Vec_Int_t * vOrder, Vec_Ptr_t * vRoots )
+{
+ DdNode * bBdd, * bBdd0, * bBdd1, * bPart, * vVar;
+ if ( Aig_ObjIsConst1(pObj) )
+ return Cudd_ReadOne(dd);
+ if ( Aig_ObjIsCi(pObj) )
+ return Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+ if ( pObj->pData )
+ return (DdNode *)pObj->pData;
+ if ( Aig_ObjIsCo(pObj) )
+ {
+ bBdd0 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) );
+ bPart = Cudd_bddXnor( dd, Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ), bBdd0 ); Cudd_Ref( bPart );
+ Vec_PtrPush( vRoots, bPart );
+ return NULL;
+ }
+ bBdd0 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) );
+ bBdd1 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin1(pObj), vOrder, vRoots), Aig_ObjFaninC1(pObj) );
+ bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bBdd );
+ if ( Llb_ObjBddVar(vOrder, pObj) >= 0 )
+ {
+ vVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+ bPart = Cudd_bddXnor( dd, vVar, bBdd ); Cudd_Ref( bPart );
+ Vec_PtrPush( vRoots, bPart );
+ Cudd_RecursiveDeref( dd, bBdd );
+ bBdd = vVar; Cudd_Ref( vVar );
+ }
+ pObj->pData = bBdd;
+ return bBdd;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives BDDs for the partitions.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_Nonlin4SweepPartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fTransition )
+{
+ Vec_Ptr_t * vRoots;
+ Aig_Obj_t * pObj;
+ int i;
+ Aig_ManCleanData( pAig );
+ vRoots = Vec_PtrAlloc( 100 );
+ if ( fTransition )
+ {
+ Saig_ManForEachLi( pAig, pObj, i )
+ Llb_Nonlin4SweepPartitions_rec( dd, pObj, vOrder, vRoots );
+ }
+ else
+ {
+ Saig_ManForEachPo( pAig, pObj, i )
+ Llb_Nonlin4SweepPartitions_rec( dd, pObj, vOrder, vRoots );
+ }
+ Aig_ManForEachNode( pAig, pObj, i )
+ if ( pObj->pData )
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+ return vRoots;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Get bad state monitor.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb4_Nonlin4SweepBadMonitor( Aig_Man_t * pAig, Vec_Int_t * vOrder, DdManager * dd )
+{
+ Aig_Obj_t * pObj;
+ DdNode * bRes, * bVar, * bTemp;
+ int i;
+ abctime TimeStop;
+ TimeStop = dd->TimeStop; dd->TimeStop = 0;
+ bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes );
+ Saig_ManForEachPo( pAig, pObj, i )
+ {
+ bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+ bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bRes );
+ dd->TimeStop = TimeStop;
+ return Cudd_Not(bRes);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates quantifiable variables for both types of traversal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_Nonlin4SweepVars2Q( Aig_Man_t * pAig, Vec_Int_t * vOrder, int fAddLis )
+{
+ Vec_Int_t * vVars2Q;
+ Aig_Obj_t * pObj;
+ int i;
+ vVars2Q = Vec_IntAlloc( 0 );
+ Vec_IntFill( vVars2Q, Aig_ManObjNumMax(pAig), 1 );
+ // add flop outputs
+ Saig_ManForEachLo( pAig, pObj, i )
+ Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 );
+ // add flop inputs
+ if ( fAddLis )
+ Saig_ManForEachLi( pAig, pObj, i )
+ Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 );
+ return vVars2Q;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Multiply every partition by the cube.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4SweepDeref( DdManager * dd, Vec_Ptr_t * vParts )
+{
+ DdNode * bFunc;
+ int i;
+ Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i )
+ Cudd_RecursiveDeref( dd, bFunc );
+ Vec_PtrFree( vParts );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Multiply every partition by the cube.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4SweepPrint( Vec_Ptr_t * vFuncs )
+{
+ DdNode * bFunc;
+ int i;
+ printf( "(%d) ", Vec_PtrSize(vFuncs) );
+ Vec_PtrForEachEntry( DdNode *, vFuncs, bFunc, i )
+ printf( "%d ", Cudd_DagSize(bFunc) );
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes bad states.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdManager * Llb4_Nonlin4SweepBadStates( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nVars )
+{
+ DdManager * dd;
+ Vec_Ptr_t * vParts;
+ Vec_Int_t * vVars2Q;
+ DdNode * bMonitor, * bImage;
+ // get quantifiable variables
+ vVars2Q = Llb_Nonlin4SweepVars2Q( pAig, vOrder, 0 );
+ // start BDD manager and create partitions
+ dd = Cudd_Init( nVars, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ vParts = Llb_Nonlin4SweepPartitions( dd, pAig, vOrder, 0 );
+//printf( "Outputs: " );
+//Llb_Nonlin4SweepPrint( vParts );
+ // compute image of the partitions
+ bMonitor = Llb4_Nonlin4SweepBadMonitor( pAig, vOrder, dd ); Cudd_Ref( bMonitor );
+ Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+ bImage = Llb_Nonlin4Image( dd, vParts, bMonitor, vVars2Q ); Cudd_Ref( bImage );
+ Cudd_RecursiveDeref( dd, bMonitor );
+ Llb_Nonlin4SweepDeref( dd, vParts );
+ Vec_IntFree( vVars2Q );
+ // save image and return
+ dd->bFunc = bImage;
+ return dd;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes clusters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdManager * Llb4_Nonlin4SweepGroups( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nVars, Vec_Ptr_t ** pvGroups, int nBddLimitClp, int fVerbose )
+{
+ DdManager * dd;
+ Vec_Ptr_t * vParts;
+ Vec_Int_t * vVars2Q;
+ // get quantifiable variables
+ vVars2Q = Llb_Nonlin4SweepVars2Q( pAig, vOrder, 1 );
+ // start BDD manager and create partitions
+ dd = Cudd_Init( nVars, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ vParts = Llb_Nonlin4SweepPartitions( dd, pAig, vOrder, 1 );
+//printf( "Transitions: " );
+//Llb_Nonlin4SweepPrint( vParts );
+ // compute image of the partitions
+
+ Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+ *pvGroups = Llb_Nonlin4Group( dd, vParts, vVars2Q, nBddLimitClp );
+ Llb_Nonlin4SweepDeref( dd, vParts );
+// *pvGroups = vParts;
+
+if ( fVerbose )
+{
+printf( "Groups: " );
+Llb_Nonlin4SweepPrint( *pvGroups );
+}
+
+ Vec_IntFree( vVars2Q );
+ return dd;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Creates quantifiable variables for both types of traversal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4SweepPrintSuppProfile( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups, int fVerbose )
+{
+ Aig_Obj_t * pObj;
+ int i, * pSupp;
+ int nSuppAll = 0, nSuppPi = 0, nSuppPo = 0, nSuppLi = 0, nSuppLo = 0, nSuppAnd = 0;
+
+ pSupp = ABC_CALLOC( int, Cudd_ReadSize(dd) );
+ Extra_VectorSupportArray( dd, (DdNode **)Vec_PtrArray(vGroups), Vec_PtrSize(vGroups), pSupp );
+
+ Aig_ManForEachObj( pAig, pObj, i )
+ {
+ if ( Llb_ObjBddVar(vOrder, pObj) < 0 )
+ continue;
+ // remove variables that do not participate
+ if ( pSupp[Llb_ObjBddVar(vOrder, pObj)] == 0 )
+ {
+ if ( Aig_ObjIsNode(pObj) )
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), -1 );
+ continue;
+ }
+ nSuppAll++;
+ if ( Saig_ObjIsPi(pAig, pObj) )
+ nSuppPi++;
+ else if ( Saig_ObjIsLo(pAig, pObj) )
+ nSuppLo++;
+ else if ( Saig_ObjIsPo(pAig, pObj) )
+ nSuppPo++;
+ else if ( Saig_ObjIsLi(pAig, pObj) )
+ nSuppLi++;
+ else
+ nSuppAnd++;
+ }
+ ABC_FREE( pSupp );
+
+ if ( fVerbose )
+ {
+ printf( "Groups =%3d ", Vec_PtrSize(vGroups) );
+ printf( "Variables: all =%4d ", nSuppAll );
+ printf( "pi =%4d ", nSuppPi );
+ printf( "po =%4d ", nSuppPo );
+ printf( "lo =%4d ", nSuppLo );
+ printf( "li =%4d ", nSuppLi );
+ printf( "and =%4d", nSuppAnd );
+ printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs BDD sweep on the netlist.]
+
+ Description [Returns BDD manager, ordering, clusters, and bad states
+ inside dd->bFunc.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb4_Nonlin4Sweep( Aig_Man_t * pAig, int nSweepMax, int nClusterMax, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int fVerbose )
+{
+ DdManager * ddBad, * ddWork;
+ Vec_Ptr_t * vGroups;
+ Vec_Int_t * vOrder;
+ int Counter, nCutPoints;
+
+ // get the original ordering
+ Aig_ManCleanMarkA( pAig );
+ vOrder = Llb_Nonlin4SweepOrder( pAig, &Counter, 1 );
+ assert( Counter == Aig_ManNodeNum(pAig) );
+ // mark the nodes
+ nCutPoints = Llb4_Nonlin4SweepCutpoints( pAig, vOrder, nSweepMax, fVerbose );
+ Vec_IntFree( vOrder );
+ // get better ordering
+ vOrder = Llb_Nonlin4SweepOrder( pAig, &Counter, 0 );
+ assert( Counter == nCutPoints );
+ Aig_ManCleanMarkA( pAig );
+ // compute the BAD states
+ ddBad = Llb4_Nonlin4SweepBadStates( pAig, vOrder, nCutPoints + Aig_ManCiNum(pAig) + Aig_ManCoNum(pAig) );
+ // compute the clusters
+ ddWork = Llb4_Nonlin4SweepGroups( pAig, vOrder, nCutPoints + Aig_ManCiNum(pAig) + Aig_ManCoNum(pAig), &vGroups, nClusterMax, fVerbose );
+ // transfer the result from the Bad manager
+//printf( "Bad before = %d.\n", Cudd_DagSize(ddBad->bFunc) );
+ ddWork->bFunc = Cudd_bddTransfer( ddBad, ddWork, ddBad->bFunc ); Cudd_Ref( ddWork->bFunc );
+ Cudd_RecursiveDeref( ddBad, ddBad->bFunc ); ddBad->bFunc = NULL;
+ Extra_StopManager( ddBad );
+ // update ordering to exclude quantified variables
+//printf( "Bad after = %d.\n", Cudd_DagSize(ddWork->bFunc) );
+
+ Llb_Nonlin4SweepPrintSuppProfile( ddWork, pAig, vOrder, vGroups, fVerbose );
+
+ // return the result
+ *pdd = ddWork;
+ *pvOrder = vOrder;
+ *pvGroups = vGroups;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs BDD sweep on the netlist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb4_Nonlin4SweepExperiment( Aig_Man_t * pAig )
+{
+ DdManager * dd;
+ Vec_Int_t * vOrder;
+ Vec_Ptr_t * vGroups;
+ Llb4_Nonlin4Sweep( pAig, 100, 500, &dd, &vOrder, &vGroups, 1 );
+
+ Llb_Nonlin4SweepDeref( dd, vGroups );
+
+ Cudd_RecursiveDeref( dd, dd->bFunc );
+ Extra_StopManager( dd );
+ Vec_IntFree( vOrder );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/bdd/llb/llbInt.h b/src/bdd/llb/llbInt.h
new file mode 100644
index 00000000..238da04e
--- /dev/null
+++ b/src/bdd/llb/llbInt.h
@@ -0,0 +1,212 @@
+/**CFile****************************************************************
+
+ FileName [llbInt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD-based reachability.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 8, 2010.]
+
+ Revision [$Id: llbInt.h,v 1.00 2010/05/08 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__llb__llbInt_h
+#define ABC__aig__llb__llbInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "aig/aig/aig.h"
+#include "aig/saig/saig.h"
+#include "proof/ssw/ssw.h"
+#include "llb.h"
+
+#include "bdd/extrab/extraBdd.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Llb_Man_t_ Llb_Man_t;
+typedef struct Llb_Mtr_t_ Llb_Mtr_t;
+typedef struct Llb_Grp_t_ Llb_Grp_t;
+
+struct Llb_Man_t_
+{
+ Gia_ParLlb_t * pPars; // parameters
+ Aig_Man_t * pAigGlo; // initial AIG manager (owned by the caller)
+ Aig_Man_t * pAig; // derived AIG manager (created in this package)
+ DdManager * dd; // BDD manager
+ DdManager * ddG; // BDD manager
+ DdManager * ddR; // BDD manager
+ Vec_Int_t * vObj2Var; // mapping AIG ObjId into BDD var index
+ Vec_Int_t * vVar2Obj; // mapping BDD var index into AIG ObjId
+ Vec_Ptr_t * vGroups; // group Id into group pointer
+ Llb_Mtr_t * pMatrix; // dependency matrix
+ // image computation
+ Vec_Ptr_t * vRings; // onion rings
+ Vec_Int_t * vVarBegs; // the first group where the var appears
+ Vec_Int_t * vVarEnds; // the last group where the var appears
+ // variable mapping
+ Vec_Int_t * vNs2Glo; // next state variables into global variables
+ Vec_Int_t * vCs2Glo; // next state variables into global variables
+ Vec_Int_t * vGlo2Cs; // global variables into current state variables
+ Vec_Int_t * vGlo2Ns; // global variables into current state variables
+ // flow computation
+// Vec_Int_t * vMem;
+// Vec_Ptr_t * vTops;
+// Vec_Ptr_t * vBots;
+// Vec_Ptr_t * vCuts;
+};
+
+struct Llb_Mtr_t_
+{
+ int nPis; // number of primary inputs
+ int nFfs; // number of flip-flops
+ int nRows; // number of rows
+ int nCols; // number of columns
+ int * pColSums; // sum of values in a column
+ Llb_Grp_t ** pColGrps; // group structure for each col
+ int * pRowSums; // sum of values in a row
+ char ** pMatrix; // dependency matrix
+ Llb_Man_t * pMan; // manager
+ // partial product
+ char * pProdVars; // variables in the partial product
+ int * pProdNums; // var counts in the remaining partitions
+};
+
+struct Llb_Grp_t_
+{
+ int Id; // group ID
+ Vec_Ptr_t * vIns; // input AIG objs
+ Vec_Ptr_t * vOuts; // output AIG objs
+ Vec_Ptr_t * vNodes; // internal AIG objs
+ Llb_Man_t * pMan; // manager
+ Llb_Grp_t * pPrev; // previous group
+ Llb_Grp_t * pNext; // next group
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int Llb_ObjBddVar( Vec_Int_t * vOrder, Aig_Obj_t * pObj ) { return Vec_IntEntry(vOrder, Aig_ObjId(pObj)); }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== llbConstr.c ======================================================*/
+extern Vec_Int_t * Llb_ManDeriveConstraints( Aig_Man_t * p );
+extern void Llb_ManPrintEntries( Aig_Man_t * p, Vec_Int_t * vCands );
+/*=== llbCore.c ======================================================*/
+extern int Llb_ManModelCheckAig( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars, Vec_Int_t * vHints, DdManager ** pddGlo );
+/*=== llbCluster.c ======================================================*/
+extern void Llb_ManCluster( Llb_Mtr_t * p );
+/*=== llbDump.c ======================================================*/
+extern void Llb_ManDumpReached( DdManager * ddG, DdNode * bReached, char * pModel, char * pFileName );
+/*=== llbFlow.c ======================================================*/
+extern Vec_Ptr_t * Llb_ManFlow( Aig_Man_t * p, Vec_Ptr_t * vSources, int * pnFlow );
+/*=== llbHint.c ======================================================*/
+extern int Llb_ManReachabilityWithHints( Llb_Man_t * p );
+extern int Llb_ManModelCheckAigWithHints( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars );
+/*=== llbMan.c =======================================================*/
+extern void Llb_ManPrepareVarMap( Llb_Man_t * p );
+extern Llb_Man_t * Llb_ManStart( Aig_Man_t * pAigGlo, Aig_Man_t * pAig, Gia_ParLlb_t * pPars );
+extern void Llb_ManStop( Llb_Man_t * p );
+/*=== llbMatrix.c ====================================================*/
+extern void Llb_MtrVerifyMatrix( Llb_Mtr_t * p );
+extern Llb_Mtr_t * Llb_MtrCreate( Llb_Man_t * p );
+extern void Llb_MtrFree( Llb_Mtr_t * p );
+extern void Llb_MtrPrint( Llb_Mtr_t * p, int fOrder );
+extern void Llb_MtrPrintMatrixStats( Llb_Mtr_t * p );
+/*=== llbPart.c ======================================================*/
+extern Llb_Grp_t * Llb_ManGroupAlloc( Llb_Man_t * pMan );
+extern void Llb_ManGroupStop( Llb_Grp_t * p );
+extern void Llb_ManPrepareGroups( Llb_Man_t * pMan );
+extern Llb_Grp_t * Llb_ManGroupsCombine( Llb_Grp_t * p1, Llb_Grp_t * p2 );
+extern Llb_Grp_t * Llb_ManGroupCreateFromCuts( Llb_Man_t * pMan, Vec_Int_t * vCut1, Vec_Int_t * vCut2 );
+extern void Llb_ManPrepareVarLimits( Llb_Man_t * p );
+/*=== llbPivot.c =====================================================*/
+extern int Llb_ManTracePaths( Aig_Man_t * p, Aig_Obj_t * pPivot );
+extern Vec_Int_t * Llb_ManMarkPivotNodes( Aig_Man_t * p, int fUseInternal );
+/*=== llbReach.c =====================================================*/
+extern int Llb_ManReachability( Llb_Man_t * p, Vec_Int_t * vHints, DdManager ** pddGlo );
+/*=== llbSched.c =====================================================*/
+extern void Llb_MtrSchedule( Llb_Mtr_t * p );
+
+/*=== llb2Bad.c ======================================================*/
+extern DdNode * Llb_BddComputeBad( Aig_Man_t * pInit, DdManager * dd, abctime TimeOut );
+extern DdNode * Llb_BddQuantifyPis( Aig_Man_t * pInit, DdManager * dd, DdNode * bFunc );
+/*=== llb2Core.c ======================================================*/
+extern DdNode * Llb_CoreComputeCube( DdManager * dd, Vec_Int_t * vVars, int fUseVarIndex, char * pValues );
+extern int Llb_CoreExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, abctime TimeTarget );
+/*=== llb2Driver.c ======================================================*/
+extern Vec_Int_t * Llb_DriverCountRefs( Aig_Man_t * p );
+extern Vec_Int_t * Llb_DriverCollectNs( Aig_Man_t * pAig, Vec_Int_t * vDriRefs );
+extern Vec_Int_t * Llb_DriverCollectCs( Aig_Man_t * pAig );
+extern DdNode * Llb_DriverPhaseCube( Aig_Man_t * pAig, Vec_Int_t * vDriRefs, DdManager * dd );
+extern DdManager * Llb_DriverLastPartition( Aig_Man_t * p, Vec_Int_t * vVarsNs, abctime TimeTarget );
+/*=== llb2Image.c ======================================================*/
+extern Vec_Ptr_t * Llb_ImgSupports( Aig_Man_t * p, Vec_Ptr_t * vDdMans, Vec_Int_t * vStart, Vec_Int_t * vStop, int fAddPis, int fVerbose );
+extern void Llb_ImgSchedule( Vec_Ptr_t * vSupps, Vec_Ptr_t ** pvQuant0, Vec_Ptr_t ** pvQuant1, int fVerbose );
+extern DdManager * Llb_ImgPartition( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, abctime TimeTarget );
+extern void Llb_ImgQuantifyFirst( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, Vec_Ptr_t * vQuant0, int fVerbose );
+extern void Llb_ImgQuantifyReset( Vec_Ptr_t * vDdMans );
+extern DdNode * Llb_ImgComputeImage( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, DdManager * dd, DdNode * bInit,
+ Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1, Vec_Int_t * vDriRefs,
+ abctime TimeTarget, int fBackward, int fReorder, int fVerbose );
+
+extern DdManager * Llb_NonlinImageStart( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, int * pOrder, int fFirst, abctime TimeTarget );
+extern DdNode * Llb_NonlinImageCompute( DdNode * bCurrent, int fReorder, int fDrop, int fVerbose, int * pOrder );
+extern void Llb_NonlinImageQuit();
+
+/*=== llb3Image.c =======================================================*/
+extern DdNode * Llb_NonlinImage( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q,
+ DdManager * dd, DdNode * bCurrent, int fReorder, int fVerbose, int * pOrder );
+/*=== llb3Nonlin.c ======================================================*/
+extern DdNode * Llb_NonlinComputeInitState( Aig_Man_t * pAig, DdManager * dd );
+
+
+/*=== llb4Cex.c =======================================================*/
+extern Abc_Cex_t * Llb4_Nonlin4TransformCex( Aig_Man_t * pAig, Vec_Ptr_t * vStates, int iCexPo, int fVerbose );
+/*=== llb4Cluster.c =======================================================*/
+//extern void Llb_Nonlin4Cluster( Aig_Man_t * pAig, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int nBddMax, int fVerbose );
+/*=== llb4Image.c =======================================================*/
+extern DdNode * Llb_Nonlin4Image( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q );
+extern Vec_Ptr_t * Llb_Nonlin4Group( DdManager * dd, Vec_Ptr_t * vParts, Vec_Int_t * vVars2Q, int nSizeMax );
+/*=== llb4Map.c =========================================================*/
+//extern Vec_Int_t * Llb_AigMap( Aig_Man_t * pAig, int nLutSize, int nLutMin );
+/*=== llb4Nonlin.c ======================================================*/
+//extern int Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars );
+/*=== llb4Sweep.c ======================================================*/
+extern void Llb4_Nonlin4Sweep( Aig_Man_t * pAig, int nSweepMax, int nClusterMax, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int fVerbose );
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/bdd/llb/module.make b/src/bdd/llb/module.make
new file mode 100644
index 00000000..6d253d50
--- /dev/null
+++ b/src/bdd/llb/module.make
@@ -0,0 +1,22 @@
+SRC += src/bdd/llb/llb1Cluster.c \
+ src/bdd/llb/llb1Constr.c \
+ src/bdd/llb/llb1Core.c \
+ src/bdd/llb/llb1Group.c \
+ src/bdd/llb/llb1Hint.c \
+ src/bdd/llb/llb1Man.c \
+ src/bdd/llb/llb1Matrix.c \
+ src/bdd/llb/llb1Pivot.c \
+ src/bdd/llb/llb1Reach.c \
+ src/bdd/llb/llb1Sched.c \
+ src/bdd/llb/llb2Bad.c \
+ src/bdd/llb/llb2Core.c \
+ src/bdd/llb/llb2Driver.c \
+ src/bdd/llb/llb2Dump.c \
+ src/bdd/llb/llb2Flow.c \
+ src/bdd/llb/llb2Image.c \
+ src/bdd/llb/llb3Image.c \
+ src/bdd/llb/llb3Nonlin.c \
+ src/bdd/llb/llb4Cex.c \
+ src/bdd/llb/llb4Image.c \
+ src/bdd/llb/llb4Nonlin.c \
+ src/bdd/llb/llb4Sweep.c