summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBaruch Sterin <baruchs@gmail.com>2011-02-01 16:19:38 -0800
committerBaruch Sterin <baruchs@gmail.com>2011-02-01 16:19:38 -0800
commit35e05b7e5a422c3c075711eba3b4329c35ac426f (patch)
tree0594feba48403b8291f25d6bbf0df6610981fc62 /src
parent3a41da37a28535aed93abc3b91130539624fb3ca (diff)
parentd4291dab37a647ac3d8d0f4e91e571bbb4e3553b (diff)
downloadabc-35e05b7e5a422c3c075711eba3b4329c35ac426f.tar.gz
abc-35e05b7e5a422c3c075711eba3b4329c35ac426f.tar.bz2
abc-35e05b7e5a422c3c075711eba3b4329c35ac426f.zip
merge pyabc changes into mainline
Diffstat (limited to 'src')
-rw-r--r--src/aig/aig/aig.h2
-rw-r--r--src/aig/aig/aigDfs.c64
-rw-r--r--src/aig/aig/aigDoms.c959
-rw-r--r--src/aig/aig/aigDup.c27
-rw-r--r--src/aig/bbr/bbrReach.c9
-rw-r--r--src/aig/live/liveness_old.c1756
-rw-r--r--src/aig/llb/llb.h4
-rw-r--r--src/aig/llb/llb1Cluster.c (renamed from src/aig/llb/llbCluster.c)4
-rw-r--r--src/aig/llb/llb1Constr.c (renamed from src/aig/llb/llbConstr.c)4
-rw-r--r--src/aig/llb/llb1Core.c (renamed from src/aig/llb/llbCore.c)12
-rw-r--r--src/aig/llb/llb1Group.c (renamed from src/aig/llb/llbPart.c)4
-rw-r--r--src/aig/llb/llb1Hint.c (renamed from src/aig/llb/llbHint.c)8
-rw-r--r--src/aig/llb/llb1Man.c (renamed from src/aig/llb/llbMan.c)8
-rw-r--r--src/aig/llb/llb1Matrix.c (renamed from src/aig/llb/llbMatrix.c)4
-rw-r--r--src/aig/llb/llb1Pivot.c (renamed from src/aig/llb/llbPivot.c)4
-rw-r--r--src/aig/llb/llb1Reach.c (renamed from src/aig/llb/llbReach.c)61
-rw-r--r--src/aig/llb/llb1Sched.c (renamed from src/aig/llb/llbSched.c)6
-rw-r--r--src/aig/llb/llb2Bad.c126
-rw-r--r--src/aig/llb/llb2Core.c638
-rw-r--r--src/aig/llb/llb2Driver.c208
-rw-r--r--src/aig/llb/llb2Dump.c104
-rw-r--r--src/aig/llb/llb2Flow.c1374
-rw-r--r--src/aig/llb/llb2Image.c440
-rw-r--r--src/aig/llb/llb3Image.c905
-rw-r--r--src/aig/llb/llb3Nonlin.c711
-rw-r--r--src/aig/llb/llb3Nonlin_multi.c1490
-rw-r--r--src/aig/llb/llbCex.c56
-rw-r--r--src/aig/llb/llbFlow.c639
-rw-r--r--src/aig/llb/llbInt.h34
-rw-r--r--src/aig/llb/module.make30
-rw-r--r--src/aig/nwk/nwkAig.c4
-rw-r--r--src/aig/saig/saigAbs.c26
-rw-r--r--src/aig/saig/saigPhase.c61
-rw-r--r--src/aig/saig/saigTempor.c61
-rw-r--r--src/base/abci/abc.c317
-rw-r--r--src/base/abci/abcDar.c21
-rw-r--r--src/bdd/cudd/cudd.h1
-rw-r--r--src/bdd/cudd/cuddAndAbs.c40
-rw-r--r--src/bdd/cudd/cuddInit.c3
-rw-r--r--src/bdd/cudd/cuddInt.h3
-rw-r--r--src/misc/extra/extra.h2
-rw-r--r--src/misc/extra/extraBddMisc.c141
-rw-r--r--src/misc/hash/hashFlt.h5
-rw-r--r--src/misc/hash/hashPtr.h12
44 files changed, 7815 insertions, 2573 deletions
diff --git a/src/aig/aig/aig.h b/src/aig/aig/aig.h
index 1f138771..ddedb4e2 100644
--- a/src/aig/aig/aig.h
+++ b/src/aig/aig/aig.h
@@ -470,6 +470,7 @@ extern void Aig_ManCutStop( Aig_ManCut_t * p );
/*=== aigDfs.c ==========================================================*/
extern int Aig_ManVerifyTopoOrder( Aig_Man_t * p );
extern Vec_Ptr_t * Aig_ManDfs( Aig_Man_t * p, int fNodesOnly );
+extern Vec_Ptr_t * Aig_ManDfsAll( Aig_Man_t * p );
extern Vec_Ptr_t * Aig_ManDfsPreorder( Aig_Man_t * p, int fNodesOnly );
extern Vec_Vec_t * Aig_ManLevelize( Aig_Man_t * p );
extern Vec_Ptr_t * Aig_ManDfsNodes( Aig_Man_t * p, Aig_Obj_t ** ppNodes, int nNodes );
@@ -501,6 +502,7 @@ extern Vec_Ptr_t * Aig_ManOrderPios( Aig_Man_t * p, Aig_Man_t * pOrder );
extern Aig_Man_t * Aig_ManDupDfsGuided( Aig_Man_t * p, Vec_Ptr_t * vPios );
extern Aig_Man_t * Aig_ManDupLevelized( Aig_Man_t * p );
extern Aig_Man_t * Aig_ManDupWithoutPos( Aig_Man_t * p );
+extern Aig_Man_t * Aig_ManDupFlopsOnly( Aig_Man_t * p );
extern Aig_Man_t * Aig_ManDupRepres( Aig_Man_t * p );
extern Aig_Man_t * Aig_ManDupRepresDfs( Aig_Man_t * p );
extern Aig_Man_t * Aig_ManCreateMiter( Aig_Man_t * p1, Aig_Man_t * p2, int fImpl );
diff --git a/src/aig/aig/aigDfs.c b/src/aig/aig/aigDfs.c
index 6b30611a..5a11c9a5 100644
--- a/src/aig/aig/aigDfs.c
+++ b/src/aig/aig/aigDfs.c
@@ -178,6 +178,70 @@ Vec_Ptr_t * Aig_ManDfs( Aig_Man_t * p, int fNodesOnly )
SeeAlso []
***********************************************************************/
+void Aig_ManDfsAll_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ return;
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ if ( Aig_ObjIsPi(pObj) )
+ {
+ Vec_PtrPush( vNodes, pObj );
+ return;
+ }
+ if ( Aig_ObjIsPo(pObj) )
+ {
+ Aig_ManDfsAll_rec( p, Aig_ObjFanin0(pObj), vNodes );
+ Vec_PtrPush( vNodes, pObj );
+ return;
+ }
+ assert( Aig_ObjIsNode(pObj) );
+ Aig_ManDfsAll_rec( p, Aig_ObjFanin0(pObj), vNodes );
+ Aig_ManDfsAll_rec( p, Aig_ObjFanin1(pObj), vNodes );
+ Vec_PtrPush( vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects objects of the AIG in the DFS order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ManDfsAll( Aig_Man_t * p )
+{
+ Vec_Ptr_t * vNodes;
+ Aig_Obj_t * pObj;
+ int i;
+ Aig_ManIncrementTravId( p );
+ vNodes = Vec_PtrAlloc( Aig_ManObjNumMax(p) );
+ // add constant
+ Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) );
+ Vec_PtrPush( vNodes, Aig_ManConst1(p) );
+ // collect nodes reachable in the DFS order
+ Aig_ManForEachPo( p, pObj, i )
+ Aig_ManDfsAll_rec( p, pObj, vNodes );
+ Aig_ManForEachPi( p, pObj, i )
+ if ( !Aig_ObjIsTravIdCurrent(p, pObj) )
+ Vec_PtrPush( vNodes, pObj );
+ assert( Vec_PtrSize(vNodes) == Aig_ManObjNum(p) );
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects internal nodes in the DFS order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
void Aig_ManDfsPreorder_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
{
if ( pObj == NULL )
diff --git a/src/aig/aig/aigDoms.c b/src/aig/aig/aigDoms.c
new file mode 100644
index 00000000..c12c0caa
--- /dev/null
+++ b/src/aig/aig/aigDoms.c
@@ -0,0 +1,959 @@
+/**CFile****************************************************************
+
+ FileName [aigDoms.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [AIG package.]
+
+ Synopsis [Computing multi-output dominators.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: aigDoms.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+#include "saig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Aig_Sto_t_ Aig_Sto_t;
+typedef struct Aig_Dom_t_ Aig_Dom_t;
+
+struct Aig_Dom_t_
+{
+ int uSign; // signature
+ int nNodes; // the number of nodes
+ int pNodes[0]; // the nodes
+};
+
+struct Aig_Sto_t_
+{
+ int Limit;
+ Aig_Man_t * pAig; // user's AIG
+ Aig_MmFixed_t * pMem; // memory manager for dominators
+ Vec_Ptr_t * vDoms; // dominators
+ Vec_Int_t * vFans; // temporary fanouts
+ int nDomNodes; // nodes with dominators
+ int nDomsTotal; // total dominators
+ int nDomsFilter1; // filtered dominators
+ int nDomsFilter2; // filtered dominators
+};
+
+#define Aig_DomForEachNode( pAig, pDom, pNode, i ) \
+ for ( i = 0; (i < pDom->nNodes) && ((pNode) = Aig_ManObj(pAig, (pDom)->pNodes[i])); i++ )
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Creates dominator manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Sto_t * Aig_ManDomStart( Aig_Man_t * pAig, int Limit )
+{
+ Aig_Sto_t * pSto;
+ assert( Aig_ManRegNum(pAig) > 0 );
+ pSto = ABC_CALLOC( Aig_Sto_t, 1 );
+ pSto->pAig = pAig;
+ pSto->Limit = Limit;
+ pSto->pMem = Aig_MmFixedStart( sizeof(Aig_Dom_t) + sizeof(int) * Limit, 10000 );
+ pSto->vDoms = Vec_PtrStart( Aig_ManObjNumMax(pAig) );
+ pSto->vFans = Vec_IntAlloc( 100 );
+ return pSto;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds trivial dominator.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_ObjAddTriv( Aig_Sto_t * pSto, int Id, Vec_Ptr_t * vDoms )
+{
+ Aig_Dom_t * pDom;
+ pDom = (Aig_Dom_t *)Aig_MmFixedEntryFetch( pSto->pMem );
+ pDom->uSign = (1 << (Id % 63));
+ pDom->nNodes = 1;
+ pDom->pNodes[0] = Id;
+ Vec_PtrPushFirst( vDoms, pDom );
+ assert( Vec_PtrEntry( pSto->vDoms, Id ) == NULL );
+ Vec_PtrWriteEntry( pSto->vDoms, Id, vDoms );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates vector of doms.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ObjDomVecDup( Aig_Sto_t * pSto, Vec_Ptr_t * vDoms, int fSkip1 )
+{
+ Vec_Ptr_t * vDoms2;
+ Aig_Dom_t * pDom, * pDom2;
+ int i;
+ vDoms2 = Vec_PtrAlloc( 0 );
+ Vec_PtrForEachEntryStart( Aig_Dom_t *, vDoms, pDom, i, fSkip1 )
+ {
+ pDom2 = (Aig_Dom_t *)Aig_MmFixedEntryFetch( pSto->pMem );
+ memcpy( pDom2, pDom, sizeof(Aig_Dom_t) + sizeof(int) * pSto->Limit );
+ Vec_PtrPush( vDoms2, pDom2 );
+ }
+ return vDoms2;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recycles vector of doms.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_ObjDomVecRecycle( Aig_Sto_t * pSto, Vec_Ptr_t * vDoms )
+{
+ Aig_Dom_t * pDom;
+ int i;
+ Vec_PtrForEachEntry( Aig_Dom_t *, vDoms, pDom, i )
+ Aig_MmFixedEntryRecycle( pSto->pMem, (char *)pDom );
+ Vec_PtrFree( vDoms );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates the vector of doms.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_ObjDomPrint( Aig_Sto_t * pSto, Aig_Dom_t * pDom, int Num )
+{
+ int k;
+ printf( "%4d : {", Num );
+ for ( k = 0; k < pDom->nNodes; k++ )
+ printf( " %4d", pDom->pNodes[k] );
+ for ( ; k < pSto->Limit; k++ )
+ printf( " " );
+ printf( " }\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates the vector of doms.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_ObjDomVecPrint( Aig_Sto_t * pSto, Vec_Ptr_t * vDoms )
+{
+ Aig_Dom_t * pDom;
+ int i;
+ Vec_PtrForEachEntry( Aig_Dom_t *, vDoms, pDom, i )
+ Aig_ObjDomPrint( pSto, pDom, i );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes multi-node dominators.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_ManDomPrint( Aig_Sto_t * pSto )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Saig_ManForEachLo( pSto->pAig, pObj, i )
+ {
+ printf( "*** LO %4d %4d :\n", i, pObj->Id );
+ Aig_ObjDomVecPrint( pSto, (Vec_Ptr_t *)Vec_PtrEntry(pSto->vDoms, pObj->Id) );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Divides the circuit into well-balanced parts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_ManDomStop( Aig_Sto_t * pSto )
+{
+ Vec_Ptr_t * vDoms;
+ int i;
+ Vec_PtrForEachEntry( Vec_Ptr_t *, pSto->vDoms, vDoms, i )
+ if ( vDoms )
+ Aig_ObjDomVecRecycle( pSto, vDoms );
+ Vec_PtrFree( pSto->vDoms );
+ Vec_IntFree( pSto->vFans );
+ Aig_MmFixedStop( pSto->pMem, 0 );
+ ABC_FREE( pSto );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Checks correctness of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Aig_ObjDomCheck( Aig_Dom_t * pDom )
+{
+ int i;
+ for ( i = 1; i < pDom->nNodes; i++ )
+ {
+ if ( pDom->pNodes[i-1] >= pDom->pNodes[i] )
+ {
+ Abc_Print( -1, "Aig_ObjDomCheck(): Cut has wrong ordering of inputs.\n" );
+ return 0;
+ }
+ assert( pDom->pNodes[i-1] < pDom->pNodes[i] );
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if pDom is contained in pCut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Aig_ObjDomCheckDominance( Aig_Dom_t * pDom, Aig_Dom_t * pCut )
+{
+ int i, k;
+ for ( i = 0; i < pDom->nNodes; i++ )
+ {
+ for ( k = 0; k < (int)pCut->nNodes; k++ )
+ if ( pDom->pNodes[i] == pCut->pNodes[k] )
+ break;
+ if ( k == (int)pCut->nNodes ) // node i in pDom is not contained in pCut
+ return 0;
+ }
+ // every node in pDom is contained in pCut
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the cut is contained.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Aig_ObjDomFilter( Aig_Sto_t * pSto, Vec_Ptr_t * vDoms, Aig_Dom_t * pDom )
+{
+ Aig_Dom_t * pTemp;
+ int i;
+ Vec_PtrForEachEntry( Aig_Dom_t *, vDoms, pTemp, i )
+ {
+ if ( pTemp->nNodes > pDom->nNodes )
+ {
+ // do not fiter the first cut
+ if ( i == 0 )
+ continue;
+ // skip the non-contained cuts
+ if ( (pTemp->uSign & pDom->uSign) != pDom->uSign )
+ continue;
+ // check containment seriously
+ if ( Aig_ObjDomCheckDominance( pDom, pTemp ) )
+ {
+ Vec_PtrRemove( vDoms, pTemp );
+ Aig_MmFixedEntryRecycle( pSto->pMem, (char *)pTemp );
+ i--;
+ pSto->nDomsFilter1++;
+ }
+ }
+ else
+ {
+ // skip the non-contained cuts
+ if ( (pTemp->uSign & pDom->uSign) != pTemp->uSign )
+ continue;
+ // check containment seriously
+ if ( Aig_ObjDomCheckDominance( pTemp, pDom ) )
+ {
+ pSto->nDomsFilter2++;
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Merges two cuts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Aig_ObjDomMergeOrdered( Aig_Dom_t * pD0, Aig_Dom_t * pD1, Aig_Dom_t * pD, int Limit )
+{
+ int i, k, c;
+ assert( pD0->nNodes >= pD1->nNodes );
+ // the case of the largest cut sizes
+ if ( pD0->nNodes == Limit && pD1->nNodes == Limit )
+ {
+ for ( i = 0; i < pD0->nNodes; i++ )
+ if ( pD0->pNodes[i] != pD1->pNodes[i] )
+ return 0;
+ for ( i = 0; i < pD0->nNodes; i++ )
+ pD->pNodes[i] = pD0->pNodes[i];
+ pD->nNodes = pD0->nNodes;
+ return 1;
+ }
+ // the case when one of the cuts is the largest
+ if ( pD0->nNodes == Limit )
+ {
+ for ( i = 0; i < pD1->nNodes; i++ )
+ {
+ for ( k = pD0->nNodes - 1; k >= 0; k-- )
+ if ( pD0->pNodes[k] == pD1->pNodes[i] )
+ break;
+ if ( k == -1 ) // did not find
+ return 0;
+ }
+ for ( i = 0; i < pD0->nNodes; i++ )
+ pD->pNodes[i] = pD0->pNodes[i];
+ pD->nNodes = pD0->nNodes;
+ return 1;
+ }
+
+ // compare two cuts with different numbers
+ i = k = 0;
+ for ( c = 0; c < (int)Limit; c++ )
+ {
+ if ( k == pD1->nNodes )
+ {
+ if ( i == pD0->nNodes )
+ {
+ pD->nNodes = c;
+ return 1;
+ }
+ pD->pNodes[c] = pD0->pNodes[i++];
+ continue;
+ }
+ if ( i == pD0->nNodes )
+ {
+ if ( k == pD1->nNodes )
+ {
+ pD->nNodes = c;
+ return 1;
+ }
+ pD->pNodes[c] = pD1->pNodes[k++];
+ continue;
+ }
+ if ( pD0->pNodes[i] < pD1->pNodes[k] )
+ {
+ pD->pNodes[c] = pD0->pNodes[i++];
+ continue;
+ }
+ if ( pD0->pNodes[i] > pD1->pNodes[k] )
+ {
+ pD->pNodes[c] = pD1->pNodes[k++];
+ continue;
+ }
+ pD->pNodes[c] = pD0->pNodes[i++];
+ k++;
+ }
+ if ( i < pD0->nNodes || k < pD1->nNodes )
+ return 0;
+ pD->nNodes = c;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the object for FPGA mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Aig_ObjDomMergeTwo( Aig_Dom_t * pDom0, Aig_Dom_t * pDom1, Aig_Dom_t * pDom, int Limit )
+{
+ assert( Limit > 0 );
+ if ( pDom0->nNodes < pDom1->nNodes )
+ {
+ if ( !Aig_ObjDomMergeOrdered( pDom1, pDom0, pDom, Limit ) )
+ return 0;
+ }
+ else
+ {
+ if ( !Aig_ObjDomMergeOrdered( pDom0, pDom1, pDom, Limit ) )
+ return 0;
+ }
+ pDom->uSign = pDom0->uSign | pDom1->uSign;
+ assert( pDom->nNodes <= Limit );
+ assert( Aig_ObjDomCheck( pDom ) );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Merge two arrays of dominators.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ObjDomMerge( Aig_Sto_t * pSto, Vec_Ptr_t * vDoms0, Vec_Ptr_t * vDoms1 )
+{
+ Vec_Ptr_t * vDoms;
+ Aig_Dom_t * pDom0, * pDom1, * pDom;
+ int i, k;
+ vDoms = Vec_PtrAlloc( 16 );
+ Vec_PtrForEachEntry( Aig_Dom_t *, vDoms0, pDom0, i )
+ Vec_PtrForEachEntry( Aig_Dom_t *, vDoms1, pDom1, k )
+ {
+ if ( Aig_WordCountOnes( pDom0->uSign | pDom1->uSign ) > pSto->Limit )
+ continue;
+ // check if the cut exists
+ pDom = (Aig_Dom_t *)Aig_MmFixedEntryFetch( pSto->pMem );
+ if ( !Aig_ObjDomMergeTwo( pDom0, pDom1, pDom, pSto->Limit ) )
+ {
+ Aig_MmFixedEntryRecycle( pSto->pMem, (char *)pDom );
+ continue;
+ }
+ // check if this cut is contained in any of the available cuts
+ if ( Aig_ObjDomFilter( pSto, vDoms, pDom ) )
+ {
+ Aig_MmFixedEntryRecycle( pSto->pMem, (char *)pDom );
+ continue;
+ }
+ Vec_PtrPush( vDoms, pDom );
+ }
+ return vDoms;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Union two arrays of dominators.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_ObjDomUnion( Aig_Sto_t * pSto, Vec_Ptr_t * vDoms2, Vec_Ptr_t * vDoms1 )
+{
+ Aig_Dom_t * pDom1, * pDom2;
+ int i;
+ Vec_PtrForEachEntry( Aig_Dom_t *, vDoms1, pDom1, i )
+ {
+ if ( i == 0 )
+ continue;
+ if ( Aig_ObjDomFilter( pSto, vDoms2, pDom1 ) )
+ continue;
+ pDom2 = (Aig_Dom_t *)Aig_MmFixedEntryFetch( pSto->pMem );
+ memcpy( pDom2, pDom1, sizeof(Aig_Dom_t) + sizeof(int) * pSto->Limit );
+ Vec_PtrPush( vDoms2, pDom2 );
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes multi-node dominators.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_ObjDomCompute( Aig_Sto_t * pSto, Aig_Obj_t * pObj )
+{
+ Vec_Ptr_t * vDoms0, * vDoms1, * vDoms2, * vDomsT;
+ Aig_Obj_t * pFanout;
+ int i, iFanout;
+ pSto->nDomNodes += Aig_ObjIsNode(pObj);
+ Vec_IntClear( pSto->vFans );
+ Aig_ObjForEachFanout( pSto->pAig, pObj, pFanout, iFanout, i )
+ if ( Aig_ObjIsTravIdCurrent(pSto->pAig, pFanout) )
+ Vec_IntPush( pSto->vFans, iFanout>>1 );
+ if ( Vec_IntSize(pSto->vFans) == 0 )
+ return;
+ vDoms0 = Vec_PtrEntry( pSto->vDoms, Vec_IntEntry(pSto->vFans, 0) );
+ vDoms2 = Aig_ObjDomVecDup( pSto, vDoms0, 0 );
+ Vec_IntForEachEntryStart( pSto->vFans, iFanout, i, 1 )
+ {
+ vDoms1 = Vec_PtrEntry( pSto->vDoms, iFanout );
+ vDoms2 = Aig_ObjDomMerge( pSto, vDomsT = vDoms2, vDoms1 );
+ Aig_ObjDomVecRecycle( pSto, vDomsT );
+ }
+ Aig_ObjAddTriv( pSto, pObj->Id, vDoms2 );
+ pSto->nDomsTotal += Vec_PtrSize(vDoms2);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks the flop TFI with the current traversal ID.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Aig_ManMarkFlopTfi_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+ int Count;
+ assert( !Aig_IsComplement(pObj) );
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ return 0;
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ if ( Aig_ObjIsPi(pObj) || Aig_ObjIsConst1(pObj) )
+ return 1;
+ Count = Aig_ManMarkFlopTfi_rec( p, Aig_ObjFanin0(pObj) );
+ if ( Aig_ObjIsNode(pObj) )
+ Count += Aig_ManMarkFlopTfi_rec( p, Aig_ObjFanin1(pObj) );
+ return Count;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks the flop TFI with the current traversal ID.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_ManMarkFlopTfi( Aig_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Aig_ManIncrementTravId( p );
+ Saig_ManForEachLi( p, pObj, i )
+ Aig_ManMarkFlopTfi_rec( p, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes multi-node dominators.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Sto_t * Aig_ManComputeDoms( Aig_Man_t * pAig, int Limit )
+{
+ Aig_Sto_t * pSto;
+ Vec_Ptr_t * vNodes;
+ Aig_Obj_t * pObj;
+ int i, clk = clock();
+ pSto = Aig_ManDomStart( pAig, Limit );
+ // initialize flop inputs
+ Saig_ManForEachLi( pAig, pObj, i )
+ Aig_ObjAddTriv( pSto, pObj->Id, Vec_PtrAlloc(1) );
+ // compute internal nodes
+ vNodes = Aig_ManDfsReverse( pAig );
+ Aig_ManMarkFlopTfi( pAig );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+ if ( Aig_ObjIsTravIdCurrent(pSto->pAig, pObj) )
+ Aig_ObjDomCompute( pSto, pObj );
+ Vec_PtrFree( vNodes );
+ // compute combinational inputs
+ Aig_ManForEachPi( pAig, pObj, i )
+ Aig_ObjDomCompute( pSto, pObj );
+
+ // print statistics
+ printf( "Nodes =%4d. Flops =%4d. Doms =%9d. Ave =%8.2f. ",
+ pSto->nDomNodes, Aig_ManRegNum(pSto->pAig), pSto->nDomsTotal,
+// pSto->nDomsFilter1, pSto->nDomsFilter2,
+ 1.0 * pSto->nDomsTotal / (pSto->nDomNodes + Aig_ManRegNum(pSto->pAig)) );
+ Abc_PrintTime( 1, "Time", clock() - clk );
+ return pSto;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Collects dominators from the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Aig_ObjDomCollect( Aig_Sto_t * pSto, Vec_Int_t * vCut )
+{
+ Vec_Ptr_t * vDoms0, * vDoms1, * vDoms2;
+ int i, ObjId;
+ vDoms0 = Vec_PtrEntry( pSto->vDoms, Vec_IntEntry(vCut, 0) );
+ vDoms2 = Aig_ObjDomVecDup( pSto, vDoms0, 1 );
+ Vec_IntForEachEntryStart( vCut, ObjId, i, 1 )
+ {
+ vDoms1 = Vec_PtrEntry( pSto->vDoms, ObjId );
+ if ( vDoms1 == NULL )
+ continue;
+ Aig_ObjDomUnion( pSto, vDoms2, vDoms1 );
+ }
+ return vDoms2;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Marks the flop TFI with the current traversal ID.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Aig_ObjDomVolume_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+ int Count;
+ assert( !Aig_IsComplement(pObj) );
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ return 0;
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ if ( pObj->fMarkA )
+ return 1;
+// assert( !Aig_ObjIsPi(pObj) && !Aig_ObjIsConst1(pObj) );
+ if ( Aig_ObjIsPi(pObj) || Aig_ObjIsConst1(pObj) )
+ return 1;
+ Count = Aig_ObjDomVolume_rec( p, Aig_ObjFanin0(pObj) );
+ if ( Aig_ObjIsNode(pObj) )
+ Count += Aig_ObjDomVolume_rec( p, Aig_ObjFanin1(pObj) );
+ return Count;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Count the number of nodes in the dominator.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Aig_ObjDomVolume( Aig_Sto_t * pSto, Aig_Dom_t * pDom )
+{
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ Aig_ManIncrementTravId( pSto->pAig );
+ Aig_DomForEachNode( pSto->pAig, pDom, pObj, i )
+ Counter += Aig_ObjDomVolume_rec( pSto->pAig, pObj );
+ return Counter;
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Dereferences the node's MFFC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Aig_ObjDomDeref_rec( Aig_Obj_t * pNode )
+{
+ int Counter = 0;
+ assert( pNode->nRefs > 0 );
+ if ( --pNode->nRefs > 0 )
+ return 0;
+ assert( pNode->nRefs == 0 );
+ if ( pNode->fMarkA )
+ return 1;
+ if ( Aig_ObjIsPi(pNode) )
+ return 0;
+ Counter += Aig_ObjDomDeref_rec( Aig_ObjFanin0(pNode) );
+ if ( Aig_ObjIsNode(pNode) )
+ Counter += Aig_ObjDomDeref_rec( Aig_ObjFanin1(pNode) );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [References the node's MFFC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Aig_ObjDomRef_rec( Aig_Obj_t * pNode )
+{
+ int Counter = 0;
+ assert( pNode->nRefs >= 0 );
+ if ( pNode->nRefs++ > 0 )
+ return 0;
+ assert( pNode->nRefs == 1 );
+ if ( pNode->fMarkA )
+ return 1;
+ if ( Aig_ObjIsPi(pNode) )
+ return 0;
+ Counter += Aig_ObjDomRef_rec( Aig_ObjFanin0(pNode) );
+ if ( Aig_ObjIsNode(pNode) )
+ Counter += Aig_ObjDomRef_rec( Aig_ObjFanin1(pNode) );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Count the number of nodes in the dominator.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Aig_ObjDomDomed( Aig_Sto_t * pSto, Aig_Dom_t * pDom )
+{
+ Aig_Obj_t * pObj;
+ int i, Counter0, Counter1;
+ Counter0 = 0;
+ Aig_DomForEachNode( pSto->pAig, pDom, pObj, i )
+ {
+ assert( !Aig_ObjIsPi(pObj) );
+ Counter0 += Aig_ObjDomDeref_rec( Aig_ObjFanin0(pObj) );
+ if ( Aig_ObjIsNode(pObj) )
+ Counter0 += Aig_ObjDomDeref_rec( Aig_ObjFanin1(pObj) );
+ }
+ Counter1 = 0;
+ Aig_DomForEachNode( pSto->pAig, pDom, pObj, i )
+ {
+ assert( !Aig_ObjIsPi(pObj) );
+ Counter1 += Aig_ObjDomRef_rec( Aig_ObjFanin0(pObj) );
+ if ( Aig_ObjIsNode(pObj) )
+ Counter1 += Aig_ObjDomRef_rec( Aig_ObjFanin1(pObj) );
+ }
+ assert( Counter0 == Counter1 );
+ return Counter0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Collects dominators from the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Aig_ObjDomCollectLos( Aig_Sto_t * pSto )
+{
+ Vec_Int_t * vCut;
+ Aig_Obj_t * pObj;
+ int i;
+ vCut = Vec_IntAlloc( Aig_ManRegNum(pSto->pAig) );
+ Saig_ManForEachLo( pSto->pAig, pObj, i )
+ {
+ Vec_IntPush( vCut, pObj->Id );
+ pObj->fMarkA = 1;
+ }
+ return vCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_ObjPoLogicDeref( Aig_Sto_t * pSto )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Saig_ManForEachPo( pSto->pAig, pObj, i )
+ Aig_ObjDomDeref_rec( Aig_ObjFanin0(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_ObjPoLogicRef( Aig_Sto_t * pSto )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Saig_ManForEachPo( pSto->pAig, pObj, i )
+ Aig_ObjDomRef_rec( Aig_ObjFanin0(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects dominators from the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_ObjDomFindGood( Aig_Sto_t * pSto )
+{
+ Aig_Dom_t * pDom;
+ Vec_Int_t * vCut;
+ Vec_Ptr_t * vDoms;
+ int i;
+ vCut = Aig_ObjDomCollectLos( pSto );
+ vDoms = Aig_ObjDomCollect( pSto, vCut );
+ Vec_IntFree( vCut );
+ printf( "The cut has %d non-trivial %d-dominators.\n", Vec_PtrSize(vDoms), pSto->Limit );
+
+ Aig_ObjPoLogicDeref( pSto );
+ Vec_PtrForEachEntry( Aig_Dom_t *, vDoms, pDom, i )
+ {
+// if ( Aig_ObjDomDomed(pSto, pDom) <= 1 )
+// continue;
+ printf( "Vol =%3d. ", Aig_ObjDomVolume(pSto, pDom) );
+ printf( "Dom =%3d. ", Aig_ObjDomDomed(pSto, pDom) );
+ Aig_ObjDomPrint( pSto, pDom, i );
+ }
+ Aig_ObjPoLogicRef( pSto );
+
+ Aig_ObjDomVecRecycle( pSto, vDoms );
+ Aig_ManCleanMarkA( pSto->pAig );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes multi-node dominators.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_ManComputeDomsTest( Aig_Man_t * pAig, int Num )
+{
+ Aig_Sto_t * pSto;
+// int i;
+//Aig_ManShow( pAig, 0, NULL );
+ Aig_ManFanoutStart( pAig );
+// for ( i = 1; i < 9; i++ )
+ {
+ printf( "ITERATION %d:\n", Num );
+ pSto = Aig_ManComputeDoms( pAig, Num );
+ Aig_ObjDomFindGood( pSto );
+// Aig_ManDomPrint( pSto );
+ Aig_ManDomStop( pSto );
+ }
+ Aig_ManFanoutStop( pAig );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/aig/aig/aigDup.c b/src/aig/aig/aigDup.c
index 91531093..dcd2e477 100644
--- a/src/aig/aig/aigDup.c
+++ b/src/aig/aig/aigDup.c
@@ -913,6 +913,33 @@ Aig_Man_t * Aig_ManDupWithoutPos( Aig_Man_t * p )
return pNew;
}
+/**Function*************************************************************
+
+ Synopsis [Duplicates the AIG manager.]
+
+ Description [Assumes topological ordering of nodes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Aig_ManDupFlopsOnly( Aig_Man_t * p )
+{
+ Aig_Man_t * pNew;
+ Aig_Obj_t * pObj;
+ int i;
+ pNew = Aig_ManDupWithoutPos( p );
+ Saig_ManForEachLi( p, pObj, i )
+ pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) );
+ Aig_ManCleanup( pNew );
+ Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) );
+ if ( !Aig_ManCheck(pNew) )
+ printf( "Aig_ManDupFlopsOnly(): The check has failed.\n" );
+ return pNew;
+
+}
+
/**Function*************************************************************
diff --git a/src/aig/bbr/bbrReach.c b/src/aig/bbr/bbrReach.c
index f76c9671..c2433d45 100644
--- a/src/aig/bbr/bbrReach.c
+++ b/src/aig/bbr/bbrReach.c
@@ -370,6 +370,15 @@ int Aig_ManComputeReachable( DdManager * dd, Aig_Man_t * p, DdNode ** pbParts, D
if ( pPars->fVerbose )
// fprintf( stdout, "\r" );
fprintf( stdout, "\n" );
+
+ if ( pPars->fVerbose )
+ {
+ double nMints = Cudd_CountMinterm(dd, bReached, Saig_ManRegNum(p) );
+// Extra_bddPrint( dd, bReached );printf( "\n" );
+ fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p)) );
+ fflush( stdout );
+ }
+
}
Cudd_RecursiveDeref( dd, bNext );
// free the onion rings
diff --git a/src/aig/live/liveness_old.c b/src/aig/live/liveness_old.c
deleted file mode 100644
index b3ddb1fc..00000000
--- a/src/aig/live/liveness_old.c
+++ /dev/null
@@ -1,1756 +0,0 @@
-#include <stdio.h>
-#include "main.h"
-#include "aig.h"
-#include "saig.h"
-#include <string.h>
-
-ABC_NAMESPACE_IMPL_START
-
-
-#define PROPAGATE_NAMES
-
-#define FULL_BIERE_MODE 0
-#define IGNORE_LIVENESS_KEEP_SAFETY_MODE 1
-#define IGNORE_SAFETY_KEEP_LIVENESS_MODE 2
-#define IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE 3
-#define FULL_BIERE_ONE_LOOP_MODE 4
-//#define DUPLICATE_CKT_DEBUG
-
-extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
-extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan );
-//char *strdup(const char *string);
-
-
-/*******************************************************************
-LAYOUT OF PI VECTOR:
-
-+------------------------------------------------------------------------------------------------------------------------------------+
-| TRUE ORIGINAL PI (n) | SAVE(PI) (1) | ORIGINAL LO (k) | SAVED(LO) (1) | SHADOW_ORIGINAL LO (k) | LIVENESS LO (l) | FAIRNESS LO (f) |
-+------------------------------------------------------------------------------------------------------------------------------------+
-<------------True PI----------------->|<----------------------------LO--------------------------------------------------------------->
-
-LAYOUT OF PO VECTOR:
-
-+-----------------------------------------------------------------------------------------------------------+
-| SOLE PO (1) | ORIGINAL LI (k) | SAVED LI (1) | SHADOW_ORIGINAL LI (k) | LIVENESS LI (l) | FAIRNESS LI (f) |
-+-----------------------------------------------------------------------------------------------------------+
-<--True PO--->|<--------------------------------------LI---------------------------------------------------->
-
-********************************************************************/
-
-
-static int nodeName_starts_with( Abc_Obj_t *pNode, const char *prefix )
-{
- if( strstr( Abc_ObjName( pNode ), prefix ) == Abc_ObjName( pNode ) )
- return 1;
- else
- return 0;
-}
-
-void printVecPtrOfString( Vec_Ptr_t *vec )
-{
- int i;
-
- for( i=0; i< Vec_PtrSize( vec ); i++ )
- {
- printf("vec[%d] = %s\n", i, (char *)Vec_PtrEntry(vec, i) );
- }
-}
-
-int getPoIndex( Aig_Man_t *pAig, Aig_Obj_t *pPivot )
-{
- int i;
- Aig_Obj_t *pObj;
-
- Saig_ManForEachPo( pAig, pObj, i )
- {
- if( pObj == pPivot )
- return i;
- }
- return -1;
-}
-
-char * retrieveTruePiName( Abc_Ntk_t *pNtkOld, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, Aig_Obj_t *pObjPivot )
-{
- Aig_Obj_t *pObjOld, *pObj;
- Abc_Obj_t *pNode;
- int index;
-
- assert( Saig_ObjIsPi( pAigNew, pObjPivot ) );
- Aig_ManForEachPi( pAigNew, pObj, index )
- if( pObj == pObjPivot )
- break;
- assert( index < Aig_ManPiNum( pAigNew ) - Aig_ManRegNum( pAigNew ) );
- if( index == Saig_ManPiNum( pAigNew ) - 1 )
- return "SAVE_BIERE";
- else
- {
- pObjOld = Aig_ManPi( pAigOld, index );
- pNode = Abc_NtkPi( pNtkOld, index );
- assert( pObjOld->pData == pObjPivot );
- return Abc_ObjName( pNode );
- }
-}
-
-char * retrieveLOName( Abc_Ntk_t *pNtkOld, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, Aig_Obj_t *pObjPivot, Vec_Ptr_t *vLive, Vec_Ptr_t * vFair )
-{
- Aig_Obj_t *pObjOld, *pObj;
- Abc_Obj_t *pNode;
- int index, oldIndex, originalLatchNum = Saig_ManRegNum(pAigOld), strMatch, i;
- char *dummyStr = (char *)malloc( sizeof(char) * 50 );
-
- assert( Saig_ObjIsLo( pAigNew, pObjPivot ) );
- Saig_ManForEachLo( pAigNew, pObj, index )
- if( pObj == pObjPivot )
- break;
- if( index < originalLatchNum )
- {
- oldIndex = Saig_ManPiNum( pAigOld ) + index;
- pObjOld = Aig_ManPi( pAigOld, oldIndex );
- pNode = Abc_NtkCi( pNtkOld, oldIndex );
- assert( pObjOld->pData == pObjPivot );
- return Abc_ObjName( pNode );
- }
- else if( index == originalLatchNum )
- return "SAVED_LO";
- else if( index > originalLatchNum && index < 2 * originalLatchNum + 1 )
- {
- oldIndex = Saig_ManPiNum( pAigOld ) + index - originalLatchNum - 1;
- pObjOld = Aig_ManPi( pAigOld, oldIndex );
- pNode = Abc_NtkCi( pNtkOld, oldIndex );
- sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "SHADOW");
- return dummyStr;
- }
- else if( index >= 2 * originalLatchNum + 1 && index < 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) )
- {
- oldIndex = index - 2 * originalLatchNum - 1;
- strMatch = 0;
- dummyStr[0] = '\0';
- Saig_ManForEachPo( pAigOld, pObj, i )
- {
- pNode = Abc_NtkPo( pNtkOld, i );
- //if( strstr( Abc_ObjName( pNode ), "assert_fair" ) != NULL )
- if( nodeName_starts_with( pNode, "assert_fair" ) )
- {
- if( strMatch == oldIndex )
- {
- sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "LIVENESS");
- //return dummyStr;
- break;
- }
- else
- strMatch++;
- }
- }
- assert( dummyStr[0] != '\0' );
- return dummyStr;
- }
- else if( index >= 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) && index < 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) )
- {
- oldIndex = index - 2 * originalLatchNum - 1 - Vec_PtrSize( vLive );
- strMatch = 0;
- dummyStr[0] = '\0';
- Saig_ManForEachPo( pAigOld, pObj, i )
- {
- pNode = Abc_NtkPo( pNtkOld, i );
- //if( strstr( Abc_ObjName( pNode ), "assume_fair" ) != NULL )
- if( nodeName_starts_with( pNode, "assume_fair" ) )
- {
- if( strMatch == oldIndex )
- {
- sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "FAIRNESS");
- //return dummyStr;
- break;
- }
- else
- strMatch++;
- }
- }
- assert( dummyStr[0] != '\0' );
- return dummyStr;
- }
- else
- return "UNKNOWN";
-}
-
-Vec_Ptr_t *vecPis, *vecPiNames;
-Vec_Ptr_t *vecLos, *vecLoNames;
-
-
-int Aig_ManPiCleanupBiere( Aig_Man_t * p )
-{
- int k = 0, nPisOld = Aig_ManPiNum(p);
-
- p->nObjs[AIG_OBJ_PI] = Vec_PtrSize( p->vPis );
- if ( Aig_ManRegNum(p) )
- p->nTruePis = Aig_ManPiNum(p) - Aig_ManRegNum(p);
-
- return nPisOld - Aig_ManPiNum(p);
-}
-
-
-int Aig_ManPoCleanupBiere( Aig_Man_t * p )
-{
- int k = 0, nPosOld = Aig_ManPoNum(p);
-
- p->nObjs[AIG_OBJ_PO] = Vec_PtrSize( p->vPos );
- if ( Aig_ManRegNum(p) )
- p->nTruePos = Aig_ManPoNum(p) - Aig_ManRegNum(p);
- return nPosOld - Aig_ManPoNum(p);
-}
-
-Aig_Man_t * LivenessToSafetyTransformation( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p,
- Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety )
-{
- Aig_Man_t * pNew;
- int i, nRegCount;
- Aig_Obj_t * pObjSavePi;
- Aig_Obj_t *pObjSavedLo, *pObjSavedLi;
- Aig_Obj_t *pObj, *pMatch;
- Aig_Obj_t *pObjSaveOrSaved, *pObjSaveAndNotSaved, *pObjSavedLoAndEquality;
- Aig_Obj_t *pObjShadowLo, *pObjShadowLi, *pObjShadowLiDriver;
- Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc;
- Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate;
- Aig_Obj_t *pObjSafetyPropertyOutput;
- Aig_Obj_t *pObjOriginalSafetyPropertyOutput;
- Aig_Obj_t *pDriverImage, *pArgument, *collectiveAssertSafety, *collectiveAssumeSafety;
- char *nodeName;
- int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, piVecIndex = 0, liveLatch = 0, fairLatch = 0;
-
- vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1);
- vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1);
-
- vecLos = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) );
- vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) );
-
- //****************************************************************
- // Step1: create the new manager
- // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)"
- // nodes, but this selection is arbitrary - need to be justified
- //****************************************************************
- pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) );
- pNew->pName = (char *)malloc( strlen( pNtk->pName ) + strlen("_l2s") + 1 );
- sprintf(pNew->pName, "%s_%s", pNtk->pName, "l2s");
- pNew->pSpec = NULL;
-
- //****************************************************************
- // Step 2: map constant nodes
- //****************************************************************
- pObj = Aig_ManConst1( p );
- pObj->pData = Aig_ManConst1( pNew );
-
- //****************************************************************
- // Step 3: create true PIs
- //****************************************************************
- Saig_ManForEachPi( p, pObj, i )
- {
- piCopied++;
- pObj->pData = Aig_ObjCreatePi(pNew);
- Vec_PtrPush( vecPis, pObj->pData );
- nodeName = Aig_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) ));
- Vec_PtrPush( vecPiNames, nodeName );
- }
-
- //****************************************************************
- // Step 4: create the special Pi corresponding to SAVE
- //****************************************************************
- if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
- {
- pObjSavePi = Aig_ObjCreatePi( pNew );
- nodeName = "SAVE_BIERE",
- Vec_PtrPush( vecPiNames, nodeName );
- }
-
- //****************************************************************
- // Step 5: create register outputs
- //****************************************************************
- Saig_ManForEachLo( p, pObj, i )
- {
- loCopied++;
- pObj->pData = Aig_ObjCreatePi(pNew);
- Vec_PtrPush( vecLos, pObj->pData );
- nodeName = Aig_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ));
- Vec_PtrPush( vecLoNames, nodeName );
- }
-
- //****************************************************************
- // Step 6: create "saved" register output
- //****************************************************************
- if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
- {
- loCreated++;
- pObjSavedLo = Aig_ObjCreatePi( pNew );
- Vec_PtrPush( vecLos, pObjSavedLo );
- nodeName = "SAVED_LO";
- Vec_PtrPush( vecLoNames, nodeName );
- }
-
- //****************************************************************
- // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi
- //****************************************************************
- if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
- {
- pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo );
- pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) );
- }
-
- //********************************************************************
- // Step 8: create internal nodes
- //********************************************************************
- Aig_ManForEachNode( p, pObj, i )
- {
- pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
- }
-
-
- //********************************************************************
- // Step 8.x : create PO for each safety assertions
- // NOTE : Here the output is purposely inverted as it will be thrown to
- // dprove
- //********************************************************************
- if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE )
- {
- if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 )
- {
- pObjAndAcc = Aig_ManConst1( pNew );
- Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i )
- {
- pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
- pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc );
- }
- pObjOriginalSafetyPropertyOutput = Aig_ObjCreatePo( pNew, Aig_Not(pObjAndAcc) );
- }
- else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 )
- {
- pObjAndAcc = Aig_ManConst1( pNew );
- Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i )
- {
- pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
- pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc );
- }
- collectiveAssertSafety = pObjAndAcc;
-
- pObjAndAcc = Aig_ManConst1( pNew );
- Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i )
- {
- pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
- pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc );
- }
- collectiveAssumeSafety = pObjAndAcc;
- pObjOriginalSafetyPropertyOutput = Aig_ObjCreatePo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) );
- }
- else
- {
- printf("WARNING!! No safety property is found, a new (negated) constant 1 output is created\n");
- pObjOriginalSafetyPropertyOutput = Aig_ObjCreatePo( pNew, Aig_Not( Aig_ManConst1(pNew) ) );
- }
- }
-
- //********************************************************************
- // Step 9: create the safety property output gate for the liveness properties
- // discuss with Sat/Alan for an alternative implementation
- //********************************************************************
- if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
- {
- pObjSafetyPropertyOutput = Aig_ObjCreatePo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData );
- }
-
- // create register inputs for the original registers
- nRegCount = 0;
-
- Saig_ManForEachLo( p, pObj, i )
- {
- pMatch = Saig_ObjLoToLi( p, pObj );
- Aig_ObjCreatePo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) );
- nRegCount++;
- liCopied++;
- }
-
- // create register input corresponding to the register "saved"
- if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
- {
- #ifndef DUPLICATE_CKT_DEBUG
- pObjSavedLi = Aig_ObjCreatePo( pNew, pObjSaveOrSaved );
- nRegCount++;
- liCreated++;
-
- //Changed on October 13, 2009
- //pObjAndAcc = NULL;
- pObjAndAcc = Aig_ManConst1( pNew );
-
- // create the family of shadow registers, then create the cascade of Xnor and And gates for the comparator
- Saig_ManForEachLo( p, pObj, i )
- {
- pObjShadowLo = Aig_ObjCreatePi( pNew );
-
- #ifdef PROPAGATE_NAMES
- Vec_PtrPush( vecLos, pObjShadowLo );
- nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ) ) + 10 );
- sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "SHADOW" );
-
- Vec_PtrPush( vecLoNames, nodeName );
- #endif
-
- pObjShadowLiDriver = Aig_Mux( pNew, pObjSaveAndNotSaved, (Aig_Obj_t *)pObj->pData, pObjShadowLo );
- pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver );
- nRegCount++;
- loCreated++; liCreated++;
-
- pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, pObjShadowLo );
- pObjXnor = Aig_Not( pObjXor );
-
- pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAcc );
- }
-
- // create the AND gate whose output will be the signal "looped"
- pObjSavedLoAndEquality = Aig_And( pNew, pObjSavedLo, pObjAndAcc );
-
- // create the master AND gate and corresponding AND and OR logic for the liveness properties
- pObjAndAcc = Aig_ManConst1( pNew );
- if( vLive == NULL || Vec_PtrSize( vLive ) == 0 )
- {
- printf("Circuit without any liveness property\n");
- }
- else
- {
- Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i )
- {
- liveLatch++;
- pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj));
- pObjShadowLo = Aig_ObjCreatePi( pNew );
-
- #ifdef PROPAGATE_NAMES
- Vec_PtrPush( vecLos, pObjShadowLo );
- nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 );
- sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "LIVENESS" );
- Vec_PtrPush( vecLoNames, nodeName );
- #endif
-
- pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) );
- pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver );
- nRegCount++;
- loCreated++; liCreated++;
-
- pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc );
- }
- }
-
- pObjLive = pObjAndAcc;
-
- pObjAndAcc = Aig_ManConst1( pNew );
- if( vFair == NULL || Vec_PtrSize( vFair ) == 0 )
- printf("Circuit without any fairness property\n");
- else
- {
- Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i )
- {
- fairLatch++;
- pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj));
- pObjShadowLo = Aig_ObjCreatePi( pNew );
-
- #ifdef PROPAGATE_NAMES
- Vec_PtrPush( vecLos, pObjShadowLo );
- nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 );
- sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "FAIRNESS" );
- Vec_PtrPush( vecLoNames, nodeName );
- #endif
-
- pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) );
- pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver );
- nRegCount++;
- loCreated++; liCreated++;
-
- pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc );
- }
- }
-
- pObjFair = pObjAndAcc;
-
- //pObjSafetyGate = Aig_Exor( pNew, Aig_Not(Aig_ManConst1( pNew )), Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ) );
- //Following is the actual Biere translation
- pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) );
-
- Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate );
- #endif
- }
-
- Aig_ManSetRegNum( pNew, nRegCount );
-
- Aig_ManPiCleanupBiere( pNew );
- Aig_ManPoCleanupBiere( pNew );
-
- Aig_ManCleanup( pNew );
-
- assert( Aig_ManCheck( pNew ) );
-
- if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
- {
- assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vPos, Saig_ManPoNum(pNew)+Aig_ObjPioNum(pObjSavedLo)-Saig_ManPiNum(p)-1) == pObjSavedLi);
- assert( Saig_ManPiNum( p ) + 1 == Saig_ManPiNum( pNew ) );
- assert( Saig_ManRegNum( pNew ) == Saig_ManRegNum( p ) * 2 + 1 + liveLatch + fairLatch );
- }
-
- return pNew;
-}
-
-
-
-
-
-Aig_Man_t * LivenessToSafetyTransformationAbs( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p, Vec_Int_t *vFlops,
- Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety )
-{
- Aig_Man_t * pNew;
- int i, nRegCount, iEntry;
- Aig_Obj_t * pObjSavePi;
- Aig_Obj_t *pObjSavedLo, *pObjSavedLi;
- Aig_Obj_t *pObj, *pMatch;
- Aig_Obj_t *pObjSaveOrSaved, *pObjSaveAndNotSaved, *pObjSavedLoAndEquality;
- Aig_Obj_t *pObjShadowLo, *pObjShadowLi, *pObjShadowLiDriver;
- Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc;
- Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate;
- Aig_Obj_t *pObjSafetyPropertyOutput;
- Aig_Obj_t *pDriverImage, *pArgument, *collectiveAssertSafety, *collectiveAssumeSafety;
- char *nodeName;
- int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, piVecIndex = 0, liveLatch = 0, fairLatch = 0;
-
- vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1);
- vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1);
-
- vecLos = Vec_PtrAlloc( Saig_ManRegNum( p ) + Vec_IntSize( vFlops ) + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) );
- vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p ) + Vec_IntSize( vFlops ) + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) );
-
- //****************************************************************
- // Step1: create the new manager
- // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)"
- // nodes, but this selection is arbitrary - need to be justified
- //****************************************************************
- pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) );
- pNew->pName = (char *)malloc( strlen( pNtk->pName ) + strlen("_l2s") + 1 );
- sprintf(pNew->pName, "%s_%s", pNtk->pName, "l2s");
- pNew->pSpec = NULL;
-
- //****************************************************************
- // Step 2: map constant nodes
- //****************************************************************
- pObj = Aig_ManConst1( p );
- pObj->pData = Aig_ManConst1( pNew );
-
- //****************************************************************
- // Step 3: create true PIs
- //****************************************************************
- Saig_ManForEachPi( p, pObj, i )
- {
- piCopied++;
- pObj->pData = Aig_ObjCreatePi(pNew);
- Vec_PtrPush( vecPis, pObj->pData );
- nodeName = Aig_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) ));
- Vec_PtrPush( vecPiNames, nodeName );
- }
-
- //****************************************************************
- // Step 4: create the special Pi corresponding to SAVE
- //****************************************************************
- if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
- {
- pObjSavePi = Aig_ObjCreatePi( pNew );
- nodeName = "SAVE_BIERE",
- Vec_PtrPush( vecPiNames, nodeName );
- }
-
- //****************************************************************
- // Step 5: create register outputs
- //****************************************************************
- Saig_ManForEachLo( p, pObj, i )
- {
- loCopied++;
- pObj->pData = Aig_ObjCreatePi(pNew);
- Vec_PtrPush( vecLos, pObj->pData );
- nodeName = Aig_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ));
- Vec_PtrPush( vecLoNames, nodeName );
- }
-
- //****************************************************************
- // Step 6: create "saved" register output
- //****************************************************************
- if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
- {
- loCreated++;
- pObjSavedLo = Aig_ObjCreatePi( pNew );
- Vec_PtrPush( vecLos, pObjSavedLo );
- nodeName = "SAVED_LO";
- Vec_PtrPush( vecLoNames, nodeName );
- }
-
- //****************************************************************
- // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi
- //****************************************************************
- if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
- {
- pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo );
- pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) );
- }
-
- //********************************************************************
- // Step 8: create internal nodes
- //********************************************************************
- Aig_ManForEachNode( p, pObj, i )
- {
- pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
- }
-
-
- //********************************************************************
- // Step 8.x : create PO for each safety assertions
- // NOTE : Here the output is purposely inverted as it will be thrown to
- // dprove
- //********************************************************************
- if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE )
- {
- if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 )
- {
- pObjAndAcc = Aig_ManConst1( pNew );
- Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i )
- {
- pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
- pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc );
- }
- Aig_ObjCreatePo( pNew, Aig_Not(pObjAndAcc) );
- }
- else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 )
- {
- pObjAndAcc = Aig_ManConst1( pNew );
- Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i )
- {
- pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
- pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc );
- }
- collectiveAssertSafety = pObjAndAcc;
-
- pObjAndAcc = Aig_ManConst1( pNew );
- Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i )
- {
- pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
- pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc );
- }
- collectiveAssumeSafety = pObjAndAcc;
- Aig_ObjCreatePo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) );
- }
- else
- {
- printf("WARNING!! No safety property is found, a new (negated) constant 1 output is created\n");
- Aig_ObjCreatePo( pNew, Aig_Not( Aig_ManConst1(pNew) ) );
- }
- }
-
- //********************************************************************
- // Step 9: create the safety property output gate for the liveness properties
- // discuss with Sat/Alan for an alternative implementation
- //********************************************************************
- if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
- {
- pObjSafetyPropertyOutput = Aig_ObjCreatePo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData );
- }
-
- // create register inputs for the original registers
- nRegCount = 0;
-
- Saig_ManForEachLo( p, pObj, i )
- {
- pMatch = Saig_ObjLoToLi( p, pObj );
- Aig_ObjCreatePo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) );
- nRegCount++;
- liCopied++;
- }
-
- // create register input corresponding to the register "saved"
- if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
- {
- #ifndef DUPLICATE_CKT_DEBUG
- pObjSavedLi = Aig_ObjCreatePo( pNew, pObjSaveOrSaved );
- nRegCount++;
- liCreated++;
-
- //Changed on October 13, 2009
- //pObjAndAcc = NULL;
- pObjAndAcc = Aig_ManConst1( pNew );
-
- // create the family of shadow registers, then create the cascade of Xnor and And gates for the comparator
- //Saig_ManForEachLo( p, pObj, i )
- Saig_ManForEachLo( p, pObj, i )
- {
- printf("Flop[%d] = %s\n", i, Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ) );
- }
- Vec_IntForEachEntry( vFlops, iEntry, i )
- {
- pObjShadowLo = Aig_ObjCreatePi( pNew );
- pObj = Aig_ManLo( p, iEntry );
-
- #ifdef PROPAGATE_NAMES
- Vec_PtrPush( vecLos, pObjShadowLo );
- nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + iEntry ) ) ) + 10 );
- sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + iEntry ) ), "SHADOW" );
- printf("Flop copied [%d] = %s\n", iEntry, nodeName );
- Vec_PtrPush( vecLoNames, nodeName );
- #endif
-
- pObjShadowLiDriver = Aig_Mux( pNew, pObjSaveAndNotSaved, (Aig_Obj_t *)pObj->pData, pObjShadowLo );
- pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver );
- nRegCount++;
- loCreated++; liCreated++;
-
- pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, pObjShadowLo );
- pObjXnor = Aig_Not( pObjXor );
-
- pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAcc );
- }
-
- // create the AND gate whose output will be the signal "looped"
- pObjSavedLoAndEquality = Aig_And( pNew, pObjSavedLo, pObjAndAcc );
-
- // create the master AND gate and corresponding AND and OR logic for the liveness properties
- pObjAndAcc = Aig_ManConst1( pNew );
- if( vLive == NULL || Vec_PtrSize( vLive ) == 0 )
- {
- printf("Circuit without any liveness property\n");
- }
- else
- {
- Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i )
- {
- liveLatch++;
- pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj));
- pObjShadowLo = Aig_ObjCreatePi( pNew );
-
- #ifdef PROPAGATE_NAMES
- Vec_PtrPush( vecLos, pObjShadowLo );
- nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 );
- sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "LIVENESS" );
- Vec_PtrPush( vecLoNames, nodeName );
- #endif
-
- pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) );
- pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver );
- nRegCount++;
- loCreated++; liCreated++;
-
- pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc );
- }
- }
-
- pObjLive = pObjAndAcc;
-
- pObjAndAcc = Aig_ManConst1( pNew );
- if( vFair == NULL || Vec_PtrSize( vFair ) == 0 )
- printf("Circuit without any fairness property\n");
- else
- {
- Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i )
- {
- fairLatch++;
- pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj));
- pObjShadowLo = Aig_ObjCreatePi( pNew );
-
- #ifdef PROPAGATE_NAMES
- Vec_PtrPush( vecLos, pObjShadowLo );
- nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 );
- sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "FAIRNESS" );
- Vec_PtrPush( vecLoNames, nodeName );
- #endif
-
- pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) );
- pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver );
- nRegCount++;
- loCreated++; liCreated++;
-
- pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc );
- }
- }
-
- pObjFair = pObjAndAcc;
-
- //pObjSafetyGate = Aig_Exor( pNew, Aig_Not(Aig_ManConst1( pNew )), Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ) );
- //Following is the actual Biere translation
- pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) );
-
- Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate );
- #endif
- }
-
- Aig_ManSetRegNum( pNew, nRegCount );
-
- Aig_ManPiCleanupBiere( pNew );
- Aig_ManPoCleanupBiere( pNew );
-
- Aig_ManCleanup( pNew );
-
- assert( Aig_ManCheck( pNew ) );
-
- if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
- {
- assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vPos, Saig_ManPoNum(pNew)+Aig_ObjPioNum(pObjSavedLo)-Saig_ManPiNum(p)-1) == pObjSavedLi);
- assert( Saig_ManPiNum( p ) + 1 == Saig_ManPiNum( pNew ) );
- assert( Saig_ManRegNum( pNew ) == Saig_ManRegNum( p ) + Vec_IntSize( vFlops ) + 1 + liveLatch + fairLatch );
- }
-
- return pNew;
-}
-
-
-
-Aig_Man_t * LivenessToSafetyTransformationOneStepLoop( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p,
- Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety )
-{
- Aig_Man_t * pNew;
- int i, nRegCount;
- Aig_Obj_t * pObjSavePi;
- Aig_Obj_t *pObj, *pMatch;
- Aig_Obj_t *pObjSavedLoAndEquality;
- Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc, *pObjAndAccDummy;
- Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate;
- Aig_Obj_t *pObjSafetyPropertyOutput;
- Aig_Obj_t *pDriverImage;
- Aig_Obj_t *pObjCorrespondingLi;
- Aig_Obj_t *pArgument;
- Aig_Obj_t *collectiveAssertSafety, *collectiveAssumeSafety;
-
- char *nodeName;
- int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, piVecIndex = 0;
-
- if( Aig_ManRegNum( p ) == 0 )
- {
- printf("The input AIG contains no register, returning the original AIG as it is\n");
- return p;
- }
-
- vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1);
- vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1);
-
- vecLos = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) );
- vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) );
-
- //****************************************************************
- // Step1: create the new manager
- // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)"
- // nodes, but this selection is arbitrary - need to be justified
- //****************************************************************
- pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) );
- pNew->pName = Aig_UtilStrsav( "live2safe" );
- pNew->pSpec = NULL;
-
- //****************************************************************
- // Step 2: map constant nodes
- //****************************************************************
- pObj = Aig_ManConst1( p );
- pObj->pData = Aig_ManConst1( pNew );
-
- //****************************************************************
- // Step 3: create true PIs
- //****************************************************************
- Saig_ManForEachPi( p, pObj, i )
- {
- piCopied++;
- pObj->pData = Aig_ObjCreatePi(pNew);
- Vec_PtrPush( vecPis, pObj->pData );
- nodeName = Aig_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) ));
- Vec_PtrPush( vecPiNames, nodeName );
- }
-
- //****************************************************************
- // Step 4: create the special Pi corresponding to SAVE
- //****************************************************************
- if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE )
- {
- pObjSavePi = Aig_ObjCreatePi( pNew );
- nodeName = "SAVE_BIERE",
- Vec_PtrPush( vecPiNames, nodeName );
- }
-
- //****************************************************************
- // Step 5: create register outputs
- //****************************************************************
- Saig_ManForEachLo( p, pObj, i )
- {
- loCopied++;
- pObj->pData = Aig_ObjCreatePi(pNew);
- Vec_PtrPush( vecLos, pObj->pData );
- nodeName = Aig_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ));
- Vec_PtrPush( vecLoNames, nodeName );
- }
-
- //****************************************************************
- // Step 6: create "saved" register output
- //****************************************************************
-
-#if 0
- loCreated++;
- pObjSavedLo = Aig_ObjCreatePi( pNew );
- Vec_PtrPush( vecLos, pObjSavedLo );
- nodeName = "SAVED_LO";
- Vec_PtrPush( vecLoNames, nodeName );
-#endif
-
- //****************************************************************
- // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi
- //****************************************************************
-#if 0
- pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo );
- pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) );
-#endif
-
- //********************************************************************
- // Step 8: create internal nodes
- //********************************************************************
- Aig_ManForEachNode( p, pObj, i )
- {
- pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
- }
-
-#if 0
- //********************************************************************
- // Step 8.x : create PO for each safety assertions
- //********************************************************************
- Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i )
- {
- pObj->pData = Aig_ObjCreatePo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) );
- }
-#endif
-
- if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE )
- {
- if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 )
- {
- pObjAndAcc = NULL;
- Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i )
- {
- //pObj->pData = Aig_ObjCreatePo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) );
- pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
- if( pObjAndAcc == NULL )
- pObjAndAcc = pArgument;
- else
- {
- pObjAndAccDummy = pObjAndAcc;
- pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAccDummy );
- }
- }
- Aig_ObjCreatePo( pNew, Aig_Not(pObjAndAcc) );
- }
- else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 )
- {
- pObjAndAcc = NULL;
- Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i )
- {
- //pObj->pData = Aig_ObjCreatePo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) );
- pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
- if( pObjAndAcc == NULL )
- pObjAndAcc = pArgument;
- else
- {
- pObjAndAccDummy = pObjAndAcc;
- pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAccDummy );
- }
- }
- collectiveAssertSafety = pObjAndAcc;
- pObjAndAcc = NULL;
- Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i )
- {
- //pObj->pData = Aig_ObjCreatePo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) );
- pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
- if( pObjAndAcc == NULL )
- pObjAndAcc = pArgument;
- else
- {
- pObjAndAccDummy = pObjAndAcc;
- pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAccDummy );
- }
- }
- collectiveAssumeSafety = pObjAndAcc;
- Aig_ObjCreatePo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) );
- }
- else
- printf("No safety property is specified, hence no safety gate is created\n");
- }
-
- //********************************************************************
- // Step 9: create the safety property output gate
- // create the safety property output gate, this will be the sole true PO
- // of the whole circuit, discuss with Sat/Alan for an alternative implementation
- //********************************************************************
-
- if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE )
- {
- pObjSafetyPropertyOutput = Aig_ObjCreatePo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData );
- }
-
- // create register inputs for the original registers
- nRegCount = 0;
-
- Saig_ManForEachLo( p, pObj, i )
- {
- pMatch = Saig_ObjLoToLi( p, pObj );
- //Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pMatch) );
- Aig_ObjCreatePo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) );
- nRegCount++;
- liCopied++;
- }
-
-#if 0
- // create register input corresponding to the register "saved"
- pObjSavedLi = Aig_ObjCreatePo( pNew, pObjSaveOrSaved );
- nRegCount++;
- liCreated++;7
-#endif
-
- pObjAndAcc = NULL;
-
- //****************************************************************************************************
- //For detection of loop of length 1 we do not need any shadow register, we only need equality detector
- //between Lo_j and Li_j and then a cascade of AND gates
- //****************************************************************************************************
-
- if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE )
- {
- Saig_ManForEachLo( p, pObj, i )
- {
- pObjCorrespondingLi = Saig_ObjLoToLi( p, pObj );
-
- pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0( pObjCorrespondingLi )->pData, Aig_ObjFaninC0( pObjCorrespondingLi ) ) );
- pObjXnor = Aig_Not( pObjXor );
-
- if( pObjAndAcc == NULL )
- pObjAndAcc = pObjXnor;
- else
- {
- pObjAndAccDummy = pObjAndAcc;
- pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAccDummy );
- }
- }
-
- // create the AND gate whose output will be the signal "looped"
- pObjSavedLoAndEquality = Aig_And( pNew, pObjSavePi, pObjAndAcc );
-
- // create the master AND gate and corresponding AND and OR logic for the liveness properties
- pObjAndAcc = NULL;
- if( vLive == NULL || Vec_PtrSize( vLive ) == 0 )
- printf("Circuit without any liveness property\n");
- else
- {
- Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i )
- {
- pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj));
- if( pObjAndAcc == NULL )
- pObjAndAcc = pDriverImage;
- else
- {
- pObjAndAccDummy = pObjAndAcc;
- pObjAndAcc = Aig_And( pNew, pDriverImage, pObjAndAccDummy );
- }
- }
- }
-
- if( pObjAndAcc != NULL )
- pObjLive = pObjAndAcc;
- else
- pObjLive = Aig_ManConst1( pNew );
-
- // create the master AND gate and corresponding AND and OR logic for the fairness properties
- pObjAndAcc = NULL;
- if( vFair == NULL || Vec_PtrSize( vFair ) == 0 )
- printf("Circuit without any fairness property\n");
- else
- {
- Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i )
- {
- pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj));
- if( pObjAndAcc == NULL )
- pObjAndAcc = pDriverImage;
- else
- {
- pObjAndAccDummy = pObjAndAcc;
- pObjAndAcc = Aig_And( pNew, pDriverImage, pObjAndAccDummy );
- }
- }
- }
-
- if( pObjAndAcc != NULL )
- pObjFair = pObjAndAcc;
- else
- pObjFair = Aig_ManConst1( pNew );
-
- pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) );
-
- Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate );
- }
-
- Aig_ManSetRegNum( pNew, nRegCount );
-
- //printf("\nSaig_ManPiNum = %d, Reg Num = %d, before everything, before Pi cleanup\n", Vec_PtrSize( pNew->vPis ), pNew->nRegs );
-
- Aig_ManPiCleanupBiere( pNew );
- Aig_ManPoCleanupBiere( pNew );
-
- Aig_ManCleanup( pNew );
-
- assert( Aig_ManCheck( pNew ) );
-
- return pNew;
-}
-
-
-
-Vec_Ptr_t * populateLivenessVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig )
-{
- Abc_Obj_t * pNode;
- int i, liveCounter = 0;
- Vec_Ptr_t * vLive;
-
- vLive = Vec_PtrAlloc( 100 );
- Abc_NtkForEachPo( pNtk, pNode, i )
- //if( strstr( Abc_ObjName( pNode ), "assert_fair") != NULL )
- if( nodeName_starts_with( pNode, "assert_fair" ) )
- {
- Vec_PtrPush( vLive, Aig_ManPo( pAig, i ) );
- liveCounter++;
- }
- printf("Number of liveness property found = %d\n", liveCounter);
- return vLive;
-}
-
-Vec_Ptr_t * populateFairnessVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig )
-{
- Abc_Obj_t * pNode;
- int i, fairCounter = 0;
- Vec_Ptr_t * vFair;
-
- vFair = Vec_PtrAlloc( 100 );
- Abc_NtkForEachPo( pNtk, pNode, i )
- //if( strstr( Abc_ObjName( pNode ), "assume_fair") != NULL )
- if( nodeName_starts_with( pNode, "assume_fair" ) )
- {
- Vec_PtrPush( vFair, Aig_ManPo( pAig, i ) );
- fairCounter++;
- }
- printf("Number of fairness property found = %d\n", fairCounter);
- return vFair;
-}
-
-Vec_Ptr_t * populateSafetyAssertionVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig )
-{
- Abc_Obj_t * pNode;
- int i, assertSafetyCounter = 0;
- Vec_Ptr_t * vAssertSafety;
-
- vAssertSafety = Vec_PtrAlloc( 100 );
- Abc_NtkForEachPo( pNtk, pNode, i )
- //if( strstr( Abc_ObjName( pNode ), "Assert") != NULL )
- if( nodeName_starts_with( pNode, "assert_safety" ) || nodeName_starts_with( pNode, "Assert" ))
- {
- Vec_PtrPush( vAssertSafety, Aig_ManPo( pAig, i ) );
- assertSafetyCounter++;
- }
- printf("Number of safety property found = %d\n", assertSafetyCounter);
- return vAssertSafety;
-}
-
-Vec_Ptr_t * populateSafetyAssumptionVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig )
-{
- Abc_Obj_t * pNode;
- int i, assumeSafetyCounter = 0;
- Vec_Ptr_t * vAssumeSafety;
-
- vAssumeSafety = Vec_PtrAlloc( 100 );
- Abc_NtkForEachPo( pNtk, pNode, i )
- //if( strstr( Abc_ObjName( pNode ), "Assert") != NULL )
- if( nodeName_starts_with( pNode, "assume_safety" ) || nodeName_starts_with( pNode, "Assume" ))
- {
- Vec_PtrPush( vAssumeSafety, Aig_ManPo( pAig, i ) );
- assumeSafetyCounter++;
- }
- printf("Number of assume_safety property found = %d\n", assumeSafetyCounter);
- return vAssumeSafety;
-}
-
-void updateNewNetworkNameManager( Abc_Ntk_t *pNtk, Aig_Man_t *pAig, Vec_Ptr_t *vPiNames, Vec_Ptr_t *vLoNames )
-{
- Aig_Obj_t *pObj;
- Abc_Obj_t *pNode;
- int i, ntkObjId;
-
- pNtk->pManName = Nm_ManCreate( Abc_NtkCiNum( pNtk ) );
-
- if( vPiNames )
- {
- Saig_ManForEachPi( pAig, pObj, i )
- {
- ntkObjId = Abc_NtkCi( pNtk, i )->Id;
- //printf("Pi %d, Saved Name = %s, id = %d\n", i, Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), Vec_PtrEntry(vPiNames, i), NULL ), ntkObjId);
- Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vPiNames, i), NULL );
- }
- }
- if( vLoNames )
- {
- Saig_ManForEachLo( pAig, pObj, i )
- {
- ntkObjId = Abc_NtkCi( pNtk, Saig_ManPiNum( pAig ) + i )->Id;
- //printf("Lo %d, Saved name = %s, id = %d\n", i, Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), Vec_PtrEntry(vLoNames, i), NULL ), ntkObjId);
- Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vLoNames, i), NULL );
- }
- }
-
- Abc_NtkForEachPo(pNtk, pNode, i)
- {
- Abc_ObjAssignName(pNode, "assert_safety_", Abc_ObjName(pNode) );
- }
-
- // assign latch input names
- Abc_NtkForEachLatch(pNtk, pNode, i)
- if ( Nm_ManFindNameById(pNtk->pManName, Abc_ObjFanin0(pNode)->Id) == NULL )
- Abc_ObjAssignName( Abc_ObjFanin0(pNode), Abc_ObjName(Abc_ObjFanin0(pNode)), NULL );
-}
-
-
-int Abc_CommandAbcLivenessToSafety( Abc_Frame_t * pAbc, int argc, char ** argv )
-{
- FILE * pOut, * pErr;
- Abc_Ntk_t * pNtk, * pNtkTemp, *pNtkNew, *pNtkOld;
- Aig_Man_t * pAig, *pAigNew;
- int c;
- Vec_Ptr_t * vLive, * vFair, *vAssertSafety, *vAssumeSafety;
- int directive = -1;
-
- pNtk = Abc_FrameReadNtk(pAbc);
- pOut = Abc_FrameReadOut(pAbc);
- pErr = Abc_FrameReadErr(pAbc);
-
- if( argc == 1 )
- {
- assert( directive == -1 );
- directive = FULL_BIERE_MODE;
- }
- else
- {
- Extra_UtilGetoptReset();
- while ( ( c = Extra_UtilGetopt( argc, argv, "1slh" ) ) != EOF )
- {
- switch( c )
- {
- case '1':
- if( directive == -1 )
- directive = FULL_BIERE_ONE_LOOP_MODE;
- else
- {
- assert( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE || directive == IGNORE_SAFETY_KEEP_LIVENESS_MODE );
- if( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE )
- directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE;
- else
- directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE;
- }
- break;
- case 's':
- if( directive == -1 )
- directive = IGNORE_SAFETY_KEEP_LIVENESS_MODE;
- else
- {
- if( directive != FULL_BIERE_ONE_LOOP_MODE )
- goto usage;
- assert(directive == FULL_BIERE_ONE_LOOP_MODE);
- directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE;
- }
- break;
- case 'l':
- if( directive == -1 )
- directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE;
- else
- {
- if( directive != FULL_BIERE_ONE_LOOP_MODE )
- goto usage;
- assert(directive == FULL_BIERE_ONE_LOOP_MODE);
- directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE;
- }
- break;
- case 'h':
- goto usage;
- default:
- goto usage;
- }
- }
- }
-
- if ( pNtk == NULL )
- {
- fprintf( pErr, "Empty network.\n" );
- return 1;
- }
- if( !Abc_NtkIsStrash( pNtk ) )
- {
- printf("The input network was not strashed, strashing....\n");
- pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
- pNtkOld = pNtkTemp;
- pAig = Abc_NtkToDar( pNtkTemp, 0, 1 );
- vLive = populateLivenessVector( pNtk, pAig );
- vFair = populateFairnessVector( pNtk, pAig );
- vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
- vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
- }
- else
- {
- pAig = Abc_NtkToDar( pNtk, 0, 1 );
- pNtkOld = pNtk;
- vLive = populateLivenessVector( pNtk, pAig );
- vFair = populateFairnessVector( pNtk, pAig );
- vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
- vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
- }
-
- switch( directive )
- {
- case FULL_BIERE_MODE:
- //if( Vec_PtrSize(vLive) == 0 && Vec_PtrSize(vAssertSafety) == 0 )
- //{
- // printf("Input circuit has NO safety and NO liveness property, original network is not disturbed\n");
- // return 1;
- //}
- //else
- //{
- pAigNew = LivenessToSafetyTransformation( FULL_BIERE_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
- if( Aig_ManRegNum(pAigNew) != 0 )
- printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n");
- break;
- //}
- case FULL_BIERE_ONE_LOOP_MODE:
- //if( Vec_PtrSize(vLive) == 0 && Vec_PtrSize(vAssertSafety) == 0 )
- //{
- // printf("Input circuit has NO safety and NO liveness property, original network is not disturbed\n");
- // return 1;
- //}
- //else
- //{
- pAigNew = LivenessToSafetyTransformationOneStepLoop( FULL_BIERE_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
- if( Aig_ManRegNum(pAigNew) != 0 )
- printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n");
- break;
- //}
- case IGNORE_LIVENESS_KEEP_SAFETY_MODE:
- //if( Vec_PtrSize(vAssertSafety) == 0 )
- //{
- // printf("Input circuit has NO safety property, original network is not disturbed\n");
- // return 1;
- //}
- //else
- //{
- pAigNew = LivenessToSafetyTransformation( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
- if( Aig_ManRegNum(pAigNew) != 0 )
- printf("A new circuit is produced with\n\t1 PO - only for safety property; liveness properties are ignored, if any.\n\tno additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n");
- break;
- //}
- case IGNORE_SAFETY_KEEP_LIVENESS_MODE:
- //if( Vec_PtrSize(vLive) == 0 )
- //{
- // printf("Input circuit has NO liveness property, original network is not disturbed\n");
- // return 1;
- //}
- //else
- //{
- pAigNew = LivenessToSafetyTransformation( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
- if( Aig_ManRegNum(pAigNew) != 0 )
- printf("A new circuit is produced with\n\t1 PO - only for liveness property; safety properties are ignored, if any.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n");
- break;
- //}
- case IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE:
- //if( Vec_PtrSize(vLive) == 0 )
- //{
- // printf("Input circuit has NO liveness property, original network is not disturbed\n");
- // return 1;
- //}
- //else
- //{
- pAigNew = LivenessToSafetyTransformationOneStepLoop( IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
- if( Aig_ManRegNum(pAigNew) != 0 )
- printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nShadow registers are not created\n");
- break;
- //}
- }
-
-#if 0
- if( argc == 1 )
- {
- pAigNew = LivenessToSafetyTransformation( FULL_BIERE_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
- if( Aig_ManRegNum(pAigNew) != 0 )
- printf("New circuit is produced considering all safety, liveness and fairness outputs.\nBiere's logic is created\n");
- }
- else
- {
- Extra_UtilGetoptReset();
- c = Extra_UtilGetopt( argc, argv, "1lsh" );
- if( c == '1' )
- {
- if ( pNtk == NULL )
- {
- fprintf( pErr, "Empty network.\n" );
- return 1;
- }
- if( !Abc_NtkIsStrash( pNtk ) )
- {
- printf("The input network was not strashed, strashing....\n");
- pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
- pNtkOld = pNtkTemp;
- pAig = Abc_NtkToDar( pNtkTemp, 0, 1 );
- vLive = populateLivenessVector( pNtk, pAig );
- vFair = populateFairnessVector( pNtk, pAig );
- vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
- vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
- }
- else
- {
- pAig = Abc_NtkToDar( pNtk, 0, 1 );
- pNtkOld = pNtk;
- vLive = populateLivenessVector( pNtk, pAig );
- vFair = populateFairnessVector( pNtk, pAig );
- vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
- vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
- }
- pAigNew = LivenessToSafetyTransformationOneStepLoop( pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
- }
- else if( c == 'l' )
- {
- if ( pNtk == NULL )
- {
- fprintf( pErr, "Empty network.\n" );
- return 1;
- }
- if( !Abc_NtkIsStrash( pNtk ) )
- {
- printf("The input network was not strashed, strashing....\n");
- pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
- pNtkOld = pNtkTemp;
- pAig = Abc_NtkToDar( pNtkTemp, 0, 1 );
- vLive = populateLivenessVector( pNtk, pAig );
- vFair = populateFairnessVector( pNtk, pAig );
- vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
- vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
- }
- else
- {
- pAig = Abc_NtkToDar( pNtk, 0, 1 );
- pNtkOld = pNtk;
- vLive = populateLivenessVector( pNtk, pAig );
- vFair = populateFairnessVector( pNtk, pAig );
- vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
- vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
- }
- pAigNew = LivenessToSafetyTransformation( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
- if( Aig_ManRegNum(pAigNew) != 0 )
- printf("New circuit is produced ignoring liveness outputs!\nOnly safety outputs are kept.\nBiere's logic is not created\n");
- }
- else if( c == 's' )
- {
- if ( pNtk == NULL )
- {
- fprintf( pErr, "Empty network.\n" );
- return 1;
- }
-
- if( !Abc_NtkIsStrash( pNtk ) )
- {
- printf("The input network was not strashed, strashing....\n");
- pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
- pNtkOld = pNtkTemp;
- pAig = Abc_NtkToDar( pNtkTemp, 0, 1 );
- vLive = populateLivenessVector( pNtk, pAig );
- vFair = populateFairnessVector( pNtk, pAig );
- vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
- vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
- }
- else
- {
- pAig = Abc_NtkToDar( pNtk, 0, 1 );
- pNtkOld = pNtk;
- vLive = populateLivenessVector( pNtk, pAig );
- vFair = populateFairnessVector( pNtk, pAig );
- vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
- vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
- }
- pAigNew = LivenessToSafetyTransformation( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
- if( Aig_ManRegNum(pAigNew) != 0 )
- printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nBiere's logic is created\n");
- }
- else if( c == 'h' )
- goto usage;
- else
- goto usage;
- }
-#endif
-
-#if 0
- Aig_ManPrintStats( pAigNew );
- printf("\nDetail statistics*************************************\n");
- printf("Number of true primary inputs = %d\n", Saig_ManPiNum( pAigNew ));
- printf("Number of true primary outputs = %d\n", Saig_ManPoNum( pAigNew ));
- printf("Number of true latch outputs = %d\n", Saig_ManCiNum( pAigNew ) - Saig_ManPiNum( pAigNew ));
- printf("Number of true latch inputs = %d\n", Saig_ManCoNum( pAigNew ) - Saig_ManPoNum( pAigNew ));
- printf("Numer of registers = %d\n", Saig_ManRegNum( pAigNew ) );
- printf("\n*******************************************************\n");
-#endif
-
- pNtkNew = Abc_NtkFromAigPhase( pAigNew );
- pNtkNew->pName = Aig_UtilStrsav( pAigNew->pName );
-
- if ( !Abc_NtkCheck( pNtkNew ) )
- fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" );
-
- updateNewNetworkNameManager( pNtkNew, pAigNew, vecPiNames, vecLoNames );
- Abc_FrameSetCurrentNetwork( pAbc, pNtkNew );
-
-#if 0
-#ifndef DUPLICATE_CKT_DEBUG
- Saig_ManForEachPi( pAigNew, pObj, i )
- assert( strcmp( (char *)Vec_PtrEntry(vecPiNames, i), retrieveTruePiName( pNtk, pAig, pAigNew, pObj ) ) == 0 );
- //printf("Name of %d-th Pi = %s, %s\n", i, retrieveTruePiName( pNtk, pAig, pAigNew, pObj ), (char *)Vec_PtrEntry(vecPiNames, i) );
-
- Saig_ManForEachLo( pAigNew, pObj, i )
- assert( strcmp( (char *)Vec_PtrEntry(vecLoNames, i), retrieveLOName( pNtk, pAig, pAigNew, pObj, vLive, vFair ) ) == 0 );
-#endif
-#endif
-
- return 0;
-
-usage:
- fprintf( stdout, "usage: l2s [-1lsh]\n" );
- fprintf( stdout, "\t performs Armin Biere's live-to-safe transformation\n" );
- fprintf( stdout, "\t-1 : no shadow logic, presume all loops are self loops\n");
- fprintf( stdout, "\t-l : ignore liveness and fairness outputs\n");
- fprintf( stdout, "\t-s : ignore safety assertions and assumptions\n");
- fprintf( stdout, "\t-h : print command usage\n");
- return 1;
-}
-
-Vec_Int_t * prepareFlopVector( Aig_Man_t * pAig, int vectorLength )
-{
- Vec_Int_t *vFlops;
- int i;
-
- vFlops = Vec_IntAlloc( vectorLength );
-
- for( i=0; i<vectorLength; i++ )
- Vec_IntPush( vFlops, i );
-
-#if 0
- Vec_IntPush( vFlops, 19 );
- Vec_IntPush( vFlops, 20 );
- Vec_IntPush( vFlops, 23 );
- Vec_IntPush( vFlops, 24 );
- //Vec_IntPush( vFlops, 2 );
- //Vec_IntPush( vFlops, 3 );
- //Vec_IntPush( vFlops, 4 );
- //Vec_IntPush( vFlops, 5 );
- //Vec_IntPush( vFlops, 8 );
- //Vec_IntPush( vFlops, 9 );
- //Vec_IntPush( vFlops, 10 );
- //Vec_IntPush( vFlops, 11 );
- //Vec_IntPush( vFlops, 0 );
- //Vec_IntPush( vFlops, 0 );
-#endif
-
- return vFlops;
-}
-
-int Abc_CommandAbcLivenessToSafetyAbstraction( Abc_Frame_t * pAbc, int argc, char ** argv )
-{
- FILE * pOut, * pErr;
- Abc_Ntk_t * pNtk, * pNtkTemp, *pNtkNew, *pNtkOld;
- Aig_Man_t * pAig, *pAigNew;
- int c;
- Vec_Ptr_t * vLive, * vFair, *vAssertSafety, *vAssumeSafety;
- int directive = -1;
- Vec_Int_t * vFlops;
-
- pNtk = Abc_FrameReadNtk(pAbc);
- pOut = Abc_FrameReadOut(pAbc);
- pErr = Abc_FrameReadErr(pAbc);
-
- if( argc == 1 )
- {
- assert( directive == -1 );
- directive = FULL_BIERE_MODE;
- }
- else
- {
- Extra_UtilGetoptReset();
- while ( ( c = Extra_UtilGetopt( argc, argv, "1slh" ) ) != EOF )
- {
- switch( c )
- {
- case '1':
- if( directive == -1 )
- directive = FULL_BIERE_ONE_LOOP_MODE;
- else
- {
- assert( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE || directive == IGNORE_SAFETY_KEEP_LIVENESS_MODE );
- if( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE )
- directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE;
- else
- directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE;
- }
- break;
- case 's':
- if( directive == -1 )
- directive = IGNORE_SAFETY_KEEP_LIVENESS_MODE;
- else
- {
- if( directive != FULL_BIERE_ONE_LOOP_MODE )
- goto usage;
- assert(directive == FULL_BIERE_ONE_LOOP_MODE);
- directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE;
- }
- break;
- case 'l':
- if( directive == -1 )
- directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE;
- else
- {
- if( directive != FULL_BIERE_ONE_LOOP_MODE )
- goto usage;
- assert(directive == FULL_BIERE_ONE_LOOP_MODE);
- directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE;
- }
- break;
- case 'h':
- goto usage;
- default:
- goto usage;
- }
- }
- }
-
- if ( pNtk == NULL )
- {
- fprintf( pErr, "Empty network.\n" );
- return 1;
- }
- if( !Abc_NtkIsStrash( pNtk ) )
- {
- printf("The input network was not strashed, strashing....\n");
- pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 );
- pNtkOld = pNtkTemp;
- pAig = Abc_NtkToDar( pNtkTemp, 0, 1 );
- vLive = populateLivenessVector( pNtk, pAig );
- vFair = populateFairnessVector( pNtk, pAig );
- vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
- vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
- }
- else
- {
- pAig = Abc_NtkToDar( pNtk, 0, 1 );
- pNtkOld = pNtk;
- vLive = populateLivenessVector( pNtk, pAig );
- vFair = populateFairnessVector( pNtk, pAig );
- vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
- vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
- }
-
- vFlops = prepareFlopVector( pAig, Aig_ManRegNum(pAig)%2 == 0? Aig_ManRegNum(pAig)/2 : (Aig_ManRegNum(pAig)-1)/2);
-
- //vFlops = prepareFlopVector( pAig, 100 );
-
- switch( directive )
- {
- case FULL_BIERE_MODE:
- //if( Vec_PtrSize(vLive) == 0 && Vec_PtrSize(vAssertSafety) == 0 )
- //{
- // printf("Input circuit has NO safety and NO liveness property, original network is not disturbed\n");
- // return 1;
- //}
- //else
- //{
- pAigNew = LivenessToSafetyTransformationAbs( FULL_BIERE_MODE, pNtk, pAig, vFlops, vLive, vFair, vAssertSafety, vAssumeSafety );
- if( Aig_ManRegNum(pAigNew) != 0 )
- printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n");
- break;
- //}
- case FULL_BIERE_ONE_LOOP_MODE:
- //if( Vec_PtrSize(vLive) == 0 && Vec_PtrSize(vAssertSafety) == 0 )
- //{
- // printf("Input circuit has NO safety and NO liveness property, original network is not disturbed\n");
- // return 1;
- //}
- //else
- //{
- pAigNew = LivenessToSafetyTransformationOneStepLoop( FULL_BIERE_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
- if( Aig_ManRegNum(pAigNew) != 0 )
- printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n");
- break;
- //}
- case IGNORE_LIVENESS_KEEP_SAFETY_MODE:
- //if( Vec_PtrSize(vAssertSafety) == 0 )
- //{
- // printf("Input circuit has NO safety property, original network is not disturbed\n");
- // return 1;
- //}
- //else
- //{
- pAigNew = LivenessToSafetyTransformationAbs( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vFlops, vLive, vFair, vAssertSafety, vAssumeSafety );
- if( Aig_ManRegNum(pAigNew) != 0 )
- printf("A new circuit is produced with\n\t1 PO - only for safety property; liveness properties are ignored, if any.\n\tno additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n");
- break;
- //}
- case IGNORE_SAFETY_KEEP_LIVENESS_MODE:
- //if( Vec_PtrSize(vLive) == 0 )
- //{
- // printf("Input circuit has NO liveness property, original network is not disturbed\n");
- // return 1;
- //}
- //else
- //{
- pAigNew = LivenessToSafetyTransformationAbs( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vFlops, vLive, vFair, vAssertSafety, vAssumeSafety );
- if( Aig_ManRegNum(pAigNew) != 0 )
- printf("A new circuit is produced with\n\t1 PO - only for liveness property; safety properties are ignored, if any.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n");
- break;
- //}
- case IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE:
- //if( Vec_PtrSize(vLive) == 0 )
- //{
- // printf("Input circuit has NO liveness property, original network is not disturbed\n");
- // return 1;
- //}
- //else
- //{
- pAigNew = LivenessToSafetyTransformationOneStepLoop( IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
- if( Aig_ManRegNum(pAigNew) != 0 )
- printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nShadow registers are not created\n");
- break;
- //}
- }
-
- pNtkNew = Abc_NtkFromAigPhase( pAigNew );
- pNtkNew->pName = Aig_UtilStrsav( pAigNew->pName );
-
- if ( !Abc_NtkCheck( pNtkNew ) )
- fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" );
-
- updateNewNetworkNameManager( pNtkNew, pAigNew, vecPiNames,vecLoNames );
- Abc_FrameSetCurrentNetwork( pAbc, pNtkNew );
-
-#if 0
-#ifndef DUPLICATE_CKT_DEBUG
- Saig_ManForEachPi( pAigNew, pObj, i )
- assert( strcmp( (char *)Vec_PtrEntry(vecPiNames, i), retrieveTruePiName( pNtk, pAig, pAigNew, pObj ) ) == 0 );
- //printf("Name of %d-th Pi = %s, %s\n", i, retrieveTruePiName( pNtk, pAig, pAigNew, pObj ), (char *)Vec_PtrEntry(vecPiNames, i) );
-
- Saig_ManForEachLo( pAigNew, pObj, i )
- assert( strcmp( (char *)Vec_PtrEntry(vecLoNames, i), retrieveLOName( pNtk, pAig, pAigNew, pObj, vLive, vFair ) ) == 0 );
-#endif
-#endif
-
- return 0;
-
-usage:
- fprintf( stdout, "usage: l2s [-1lsh]\n" );
- fprintf( stdout, "\t performs Armin Biere's live-to-safe transformation\n" );
- fprintf( stdout, "\t-1 : no shadow logic, presume all loops are self loops\n");
- fprintf( stdout, "\t-l : ignore liveness and fairness outputs\n");
- fprintf( stdout, "\t-s : ignore safety assertions and assumptions\n");
- fprintf( stdout, "\t-h : print command usage\n");
- return 1;
-}
-ABC_NAMESPACE_IMPL_END
-
diff --git a/src/aig/llb/llb.h b/src/aig/llb/llb.h
index 2c8d1c19..3cbd8136 100644
--- a/src/aig/llb/llb.h
+++ b/src/aig/llb/llb.h
@@ -31,7 +31,6 @@
////////////////////////////////////////////////////////////////////////
-
ABC_NAMESPACE_HEADER_START
@@ -50,11 +49,14 @@ struct Gia_ParLlb_t_
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
diff --git a/src/aig/llb/llbCluster.c b/src/aig/llb/llb1Cluster.c
index 1d0153ce..8a41fe58 100644
--- a/src/aig/llb/llbCluster.c
+++ b/src/aig/llb/llb1Cluster.c
@@ -1,6 +1,6 @@
/**CFile****************************************************************
- FileName [llbCluster.c]
+ FileName [llb1Cluster.c]
SystemName [ABC: Logic synthesis and verification system.]
@@ -14,7 +14,7 @@
Date [Ver. 1.0. Started - June 20, 2005.]
- Revision [$Id: llbCluster.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+ Revision [$Id: llb1Cluster.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
diff --git a/src/aig/llb/llbConstr.c b/src/aig/llb/llb1Constr.c
index eabae3bc..67fb30ba 100644
--- a/src/aig/llb/llbConstr.c
+++ b/src/aig/llb/llb1Constr.c
@@ -1,6 +1,6 @@
/**CFile****************************************************************
- FileName [llbConstr.c]
+ FileName [llb1Constr.c]
SystemName [ABC: Logic synthesis and verification system.]
@@ -14,7 +14,7 @@
Date [Ver. 1.0. Started - June 20, 2005.]
- Revision [$Id: llbConstr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+ Revision [$Id: llb1Constr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
diff --git a/src/aig/llb/llbCore.c b/src/aig/llb/llb1Core.c
index cbd527e2..ff7eadbb 100644
--- a/src/aig/llb/llbCore.c
+++ b/src/aig/llb/llb1Core.c
@@ -1,6 +1,6 @@
/**CFile****************************************************************
- FileName [llbCore.c]
+ FileName [llb1Core.c]
SystemName [ABC: Logic synthesis and verification system.]
@@ -14,7 +14,7 @@
Date [Ver. 1.0. Started - June 20, 2005.]
- Revision [$Id: llbCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+ Revision [$Id: llb1Core.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
@@ -24,11 +24,10 @@
ABC_NAMESPACE_IMPL_START
-
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-
+
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
@@ -47,7 +46,7 @@ ABC_NAMESPACE_IMPL_START
void Llb_ManSetDefaultParams( Gia_ParLlb_t * p )
{
memset( p, 0, sizeof(Gia_ParLlb_t) );
- p->nBddMax = 1000000;
+ p->nBddMax = 10000000;
p->nIterMax = 10000000;
p->nClusterMax = 20;
p->nHintDepth = 0;
@@ -55,11 +54,14 @@ void Llb_ManSetDefaultParams( Gia_ParLlb_t * p )
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;
diff --git a/src/aig/llb/llbPart.c b/src/aig/llb/llb1Group.c
index 41de27d8..4ebfc3a3 100644
--- a/src/aig/llb/llbPart.c
+++ b/src/aig/llb/llb1Group.c
@@ -1,6 +1,6 @@
/**CFile****************************************************************
- FileName [llbPart.c]
+ FileName [llb1Group.c]
SystemName [ABC: Logic synthesis and verification system.]
@@ -14,7 +14,7 @@
Date [Ver. 1.0. Started - June 20, 2005.]
- Revision [$Id: llbPart.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+ Revision [$Id: llb1Group.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
diff --git a/src/aig/llb/llbHint.c b/src/aig/llb/llb1Hint.c
index acc674c8..d8ffecd3 100644
--- a/src/aig/llb/llbHint.c
+++ b/src/aig/llb/llb1Hint.c
@@ -1,6 +1,6 @@
/**CFile****************************************************************
- FileName [llbHint.c]
+ FileName [llb1Hint.c]
SystemName [ABC: Logic synthesis and verification system.]
@@ -14,7 +14,7 @@
Date [Ver. 1.0. Started - June 20, 2005.]
- Revision [$Id: llbHint.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+ Revision [$Id: llb1Hint.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
@@ -205,8 +205,8 @@ int Llb_ManModelCheckAigWithHints( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars )
Finish:
if ( ddGlo )
{
- if ( ddGlo->bReached )
- Cudd_RecursiveDeref( ddGlo, ddGlo->bReached );
+ if ( ddGlo->bFunc )
+ Cudd_RecursiveDeref( ddGlo, ddGlo->bFunc );
Extra_StopManager( ddGlo );
}
Vec_IntFreeP( &vHFCands );
diff --git a/src/aig/llb/llbMan.c b/src/aig/llb/llb1Man.c
index cd6fd3ff..d9c13a76 100644
--- a/src/aig/llb/llbMan.c
+++ b/src/aig/llb/llb1Man.c
@@ -1,6 +1,6 @@
/**CFile****************************************************************
- FileName [llbMan.c]
+ FileName [llb1Man.c]
SystemName [ABC: Logic synthesis and verification system.]
@@ -14,7 +14,7 @@
Date [Ver. 1.0. Started - June 20, 2005.]
- Revision [$Id: llbMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+ Revision [$Id: llb1Man.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
@@ -142,8 +142,8 @@ void Llb_ManStop( Llb_Man_t * p )
}
if ( p->ddG )
{
- if ( p->ddG->bReached )
- Cudd_RecursiveDeref( p->ddG, p->ddG->bReached );
+ if ( p->ddG->bFunc )
+ Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc );
Extra_StopManager( p->ddG );
}
Aig_ManStop( p->pAig );
diff --git a/src/aig/llb/llbMatrix.c b/src/aig/llb/llb1Matrix.c
index 484ee690..7aa9c744 100644
--- a/src/aig/llb/llbMatrix.c
+++ b/src/aig/llb/llb1Matrix.c
@@ -1,6 +1,6 @@
/**CFile****************************************************************
- FileName [llbMatrix.c]
+ FileName [llb1Matrix.c]
SystemName [ABC: Logic synthesis and verification system.]
@@ -14,7 +14,7 @@
Date [Ver. 1.0. Started - June 20, 2005.]
- Revision [$Id: llbMatrix.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+ Revision [$Id: llb1Matrix.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
diff --git a/src/aig/llb/llbPivot.c b/src/aig/llb/llb1Pivot.c
index 6a6fb321..d42bf659 100644
--- a/src/aig/llb/llbPivot.c
+++ b/src/aig/llb/llb1Pivot.c
@@ -1,6 +1,6 @@
/**CFile****************************************************************
- FileName [llbPivot.c]
+ FileName [llb1Pivot.c]
SystemName [ABC: Logic synthesis and verification system.]
@@ -14,7 +14,7 @@
Date [Ver. 1.0. Started - June 20, 2005.]
- Revision [$Id: llbPivot.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+ Revision [$Id: llb1Pivot.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
diff --git a/src/aig/llb/llbReach.c b/src/aig/llb/llb1Reach.c
index 76ee7147..45dec7ab 100644
--- a/src/aig/llb/llbReach.c
+++ b/src/aig/llb/llb1Reach.c
@@ -1,6 +1,6 @@
/**CFile****************************************************************
- FileName [llbReach.c]
+ FileName [llb1Reach.c]
SystemName [ABC: Logic synthesis and verification system.]
@@ -14,7 +14,7 @@
Date [Ver. 1.0. Started - June 20, 2005.]
- Revision [$Id: llbReach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+ Revision [$Id: llb1Reach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
@@ -346,6 +346,22 @@ DdNode * Llb_ManCreateConstraints( Llb_Man_t * p, Vec_Int_t * vHints, int fUseNs
/**Function*************************************************************
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Cex_t * Llb_ManDeriveCex( Llb_Man_t * p, DdNode * bInter, int iOutFail, int iIter )
+{
+ return NULL;
+}
+
+/**Function*************************************************************
+
Synopsis [Perform reachability with hints and returns reached states in ppGlo.]
Description []
@@ -358,7 +374,6 @@ DdNode * Llb_ManCreateConstraints( Llb_Man_t * p, Vec_Int_t * vHints, int fUseNs
int Llb_ManReachability( Llb_Man_t * p, Vec_Int_t * vHints, DdManager ** pddGlo )
{
int fCheckOutputs = !p->pPars->fSkipOutCheck;
- int fInternalReorder = 0;
int * pNs2Glo = Vec_IntArray( p->vNs2Glo );
int * pGlo2Cs = Vec_IntArray( p->vGlo2Cs );
DdNode * bCurrent, * bReached, * bNext, * bTemp, * bCube;
@@ -403,9 +418,9 @@ int Llb_ManReachability( Llb_Man_t * p, Vec_Int_t * vHints, DdManager ** pddGlo
// perform reachability analysis
// compute the starting set of states
- if ( p->ddG->bReached )
+ if ( p->ddG->bFunc )
{
- bReached = p->ddG->bReached; p->ddG->bReached = NULL;
+ bReached = p->ddG->bFunc; p->ddG->bFunc = NULL;
bCurrent = Extra_TransferPermute( p->ddG, p->dd, bReached, pGlo2Cs ); Cudd_Ref( bCurrent );
}
else
@@ -548,28 +563,22 @@ int Llb_ManReachability( Llb_Man_t * p, Vec_Int_t * vHints, DdManager ** pddGlo
if ( p->pPars->fVerbose )
{
- fprintf( stdout, "F =%3d : ", nIters );
- fprintf( stdout, "Image =%6d ", nBddSize );
- fprintf( stdout, "%8d (%4d %3d) ",
- Cudd_ReadKeys(p->dd), Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) );
- fprintf( stdout, "Reach =%6d ", Cudd_DagSize(bReached) );
- fprintf( stdout, "%8d (%4d %3d) ",
- Cudd_ReadKeys(p->ddG), Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) );
+ 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", clock() - clk2 );
}
- if ( fInternalReorder && p->pPars->fReorder && nBddSize > nThreshold )
+/*
+ if ( p->pPars->fVerbose )
{
- if ( p->pPars->fVerbose )
- fprintf( stdout, "Reordering... Before = %5d. ", Cudd_DagSize(bReached) );
- Cudd_ReduceHeap( p->dd, CUDD_REORDER_SYMM_SIFT, 100 );
-// Cudd_AutodynDisable( p->dd );
- if ( p->pPars->fVerbose )
- fprintf( stdout, "After = %5d.\r", Cudd_DagSize(bReached) );
- nThreshold *= 2;
+ 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, "\r" );
-// fprintf( stdout, "\n" );
- Abc_PrintTime( 1, "T", clock() - clk2 );
+*/
}
Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL;
Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL;
@@ -598,8 +607,8 @@ int Llb_ManReachability( Llb_Man_t * p, Vec_Int_t * vHints, DdManager ** pddGlo
}
if ( pddGlo )
{
- assert( p->ddG->bReached == NULL );
- p->ddG->bReached = bReached; bReached = NULL;
+ assert( p->ddG->bFunc == NULL );
+ p->ddG->bFunc = bReached; bReached = NULL;
assert( *pddGlo == NULL );
*pddGlo = p->ddG; p->ddG = NULL;
}
diff --git a/src/aig/llb/llbSched.c b/src/aig/llb/llb1Sched.c
index 0f7b9fab..6bdae42e 100644
--- a/src/aig/llb/llbSched.c
+++ b/src/aig/llb/llb1Sched.c
@@ -1,12 +1,12 @@
/**CFile****************************************************************
- FileName [llb.c]
+ FileName [llb1Sched.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [BDD based reachability.]
- Synopsis []
+ Synopsis [Partition scheduling algorithm.]
Author [Alan Mishchenko]
@@ -14,7 +14,7 @@
Date [Ver. 1.0. Started - June 20, 2005.]
- Revision [$Id: llb.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+ Revision [$Id: llb1Sched.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
diff --git a/src/aig/llb/llb2Bad.c b/src/aig/llb/llb2Bad.c
new file mode 100644
index 00000000..8322698b
--- /dev/null
+++ b/src/aig/llb/llb2Bad.c
@@ -0,0 +1,126 @@
+/**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 )
+{
+ Vec_Ptr_t * vNodes;
+ DdNode * bBdd0, * bBdd1, * bTemp, * bResult;
+ Aig_Obj_t * pObj;
+ int i;
+ assert( Cudd_ReadSize(dd) == Aig_ManPiNum(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->vPos), 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 = Cudd_bddAnd( dd, bBdd0, bBdd1 ); 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, 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;
+ assert( Cudd_ReadSize(dd) == Aig_ManPiNum(pInit) );
+ // 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 );
+ return bFunc;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/aig/llb/llb2Core.c b/src/aig/llb/llb2Core.c
new file mode 100644
index 00000000..e440438f
--- /dev/null
+++ b/src/aig/llb/llb2Core.c
@@ -0,0 +1,638 @@
+/**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;
+ 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 );
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives counter-example by backward reachability.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Cex_t * Llb_CoreDeriveCex( Llb_Img_t * p )
+{
+ extern Abc_Cex_t * Ssw_SmlAllocCounterExample( int nRegs, int nRealPis, int nFrames );
+ extern int Ssw_SmlFindOutputCounterExample( Aig_Man_t * pAig, Abc_Cex_t * p );
+ Abc_Cex_t * pCex;
+ Aig_Obj_t * pObj;
+ Vec_Ptr_t * vSupps, * vQuant0, * vQuant1;
+ DdNode * bState, * bImage, * bOneCube, * bTemp, * bRing;
+ int i, v, RetValue, nPiOffset;
+ char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) );
+ assert( Vec_PtrSize(p->vRings) > 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 = Ssw_SmlAllocCounterExample( 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, 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 )
+ Aig_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 )
+ Aig_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 = Ssw_SmlFindOutputCounterExample( 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;
+ int clk2, clk = clock(), nIters, nBddSize, iOutFail = -1;
+
+ // compute time to stop
+ if ( p->pPars->TimeLimit )
+ p->pPars->TimeTarget = clock() + p->pPars->TimeLimit * CLOCKS_PER_SEC;
+ else
+ p->pPars->TimeTarget = 0;
+
+ // compute initial states
+ if ( p->pPars->fBackward )
+ {
+ // create bad state in the ring manager
+ p->ddR->bFunc = Llb_CoreComputeCube( p->ddR, p->vVarsCs, 0, NULL ); Cudd_Ref( p->ddR->bFunc );
+ // create init state in the global manager
+ bTemp = Llb_BddComputeBad( p->pInit, p->ddR ); Cudd_Ref( bTemp );
+ 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 ); Cudd_Ref( bCurrent );
+ }
+ else
+ {
+ // create bad state in the ring manager
+ p->ddR->bFunc = Llb_BddComputeBad( p->pInit, p->ddR ); 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 = clock();
+ // check the runtime limit
+ if ( p->pPars->TimeLimit && 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->ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+
+ // save the onion ring
+ bTemp = Extra_TransferPermute( p->dd, p->ddR, bCurrent, pLoc2GloR ); 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 )
+ printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump a witness). ", p->pInit->pSeqModel->iPo, nIters );
+ else
+ printf( "Output ??? was asserted in frame %d (counter-example is not produced). ", nIters );
+ Abc_PrintTime( 1, "Time", clock() - clk );
+ }
+ 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 during image computation (%d seconds).\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 );
+ 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) ); 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 );
+
+ // 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", 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 )
+ 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", clock() - clk );
+ }
+ return -1; // undecided
+ }
+ if ( !p->pPars->fSilent )
+ {
+ printf( "The miter is proved unreachable after %d iterations. ", nIters );
+ Abc_PrintTime( 1, "Time", 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 )
+{
+ DdManager * dd;
+ Vec_Ptr_t * vDdMans;
+ Vec_Ptr_t * vLower, * vUpper;
+ 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 );
+ else
+ dd = Llb_DriverLastPartition( p, vVarsNs );
+ 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_ManPiNum(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;
+ 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_PtrFree( 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 )
+{
+ 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 );
+ 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;
+
+ 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->fSkipReach )
+ RetValue = Llb_CoreExperiment( pAig, p, pPars, vResult );
+ Vec_VecFree( (Vec_Vec_t *)vResult );
+
+ Aig_ManFanoutStop( p );
+ Aig_ManCleanMarkAB( p );
+ Aig_ManStop( p );
+ return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/aig/llb/llb2Driver.c b/src/aig/llb/llb2Driver.c
new file mode 100644
index 00000000..0115e51e
--- /dev/null
+++ b/src/aig/llb/llb2Driver.c
@@ -0,0 +1,208 @@
+/**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;
+ 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 );
+ return bCube;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute the last partition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdManager * Llb_DriverLastPartition( Aig_Man_t * p, Vec_Int_t * vVarsNs )
+{
+ 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 );
+ bRes = Cudd_ReadOne(dd); Cudd_Ref( bRes );
+
+ // mark the duplicated flop inputs
+ Aig_ManForEachNodeVec( p, vVarsNs, 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 );
+ 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;
+ return dd;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/aig/llb/llb2Dump.c b/src/aig/llb/llb2Dump.c
new file mode 100644
index 00000000..55f94907
--- /dev/null
+++ b/src/aig/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 = Extra_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 );
+ 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/aig/llb/llb2Flow.c b/src/aig/llb/llb2Flow.c
new file mode 100644
index 00000000..36b3ff1b
--- /dev/null
+++ b/src/aig/llb/llb2Flow.c
@@ -0,0 +1,1374 @@
+/**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;
+ 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_ObjPioNum(pObj)] == -1 )
+ piFirst[Aig_ObjPioNum(pObj)] = i;
+ piLast[Aig_ObjPioNum(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_ObjPioNum(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_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_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_PtrEntry( vMaps, i-1 );
+ vNext = (i == Vec_PtrSize(vMaps)-1)? NULL: 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 )
+ Aig_ManForEachObj( p, pObj, i )
+ {
+ if ( !Aig_ObjIsPi(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, Counter = 0;
+ Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i )
+ {
+ if ( Aig_ObjIsPi(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;
+ 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_ObjIsPi(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_ObjIsPi(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_ObjIsPo(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_ObjIsPi(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_ObjIsPi(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_ManForEachPi( 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;
+ 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_ManForEachPi( 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 = 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_MIN( 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_MIN( 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, * vLower, * vUpper;
+ int i, k, nVol, clk = 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", 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 );
+ extern void Llb_CoreExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult );
+
+ 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 );
+
+// 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/aig/llb/llb2Image.c b/src/aig/llb/llb2Image.c
new file mode 100644
index 00000000..afe99051
--- /dev/null
+++ b/src/aig/llb/llb2Image.c
@@ -0,0 +1,440 @@
+/**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 )
+ 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, 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 )
+{
+ 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 );
+
+ 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 );
+ }
+
+ 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 );
+ 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;
+ 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;
+ bProd = Cudd_ReadOne(dd); Cudd_Ref( bProd );
+ Aig_ManForEachNodeVec( pAig, vNodeIds, pObj, i )
+ {
+ bProd = Cudd_bddAnd( dd, bTemp = bProd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)) ); Cudd_Ref( bProd );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bProd );
+ 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, clk = 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", 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,
+ int TimeTarget, int fBackward, int fReorder, int fVerbose )
+{
+ int fCheckSupport = 0;
+ DdManager * ddPart;
+ DdNode * bImage, * bGroup, * bCube, * bTemp;
+ int i, clk, clk0 = 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 ); Cudd_Ref( bImage );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bCube );
+ }
+ // perform image computation
+ Vec_PtrForEachEntry( DdManager *, vDdMans, ddPart, i )
+ {
+ clk = clock();
+if ( fVerbose )
+printf( " %2d : ", i );
+ // transfer the BDD from the group manager to the main manager
+ bGroup = Cudd_bddTransfer( ddPart, dd, ddPart->bFunc ); 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 ); 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) );
+
+ // chech runtime
+ if ( TimeTarget && clock() >= TimeTarget )
+ {
+ Cudd_RecursiveDeref( dd, bImage );
+ return NULL;
+ }
+if ( fVerbose )
+printf( "Supp =%3d. ", Cudd_SupportSize(dd, bImage) );
+if ( fVerbose )
+Abc_PrintTime( 1, "T", 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", clock() - clk0 );
+// Abc_Print( 1, "\n" );
+ }
+
+ Cudd_Deref( bImage );
+ return bImage;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/aig/llb/llb3Image.c b/src/aig/llb/llb3Image.c
new file mode 100644
index 00000000..d040b342
--- /dev/null
+++ b/src/aig/llb/llb3Image.c
@@ -0,0 +1,905 @@
+/**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
+ DdNode * bCurrent; // current state functions in terms of vLeaves
+ 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
+int 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;
+ 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 );
+ 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;
+ 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 );
+ 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 Limit )
+{
+ 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, Limit );
+*/
+ return 1;
+ }
+ 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_MAX( 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 0;
+}
+
+/**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;
+
+ 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 = Cudd_bddAnd( dd, bBdd0, bBdd1 ); 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_NonlinStart( Llb_Mgr_t * p )
+{
+ Vec_Ptr_t * vRootBdds;
+ Llb_Prt_t * pPart;
+ DdNode * bFunc;
+ int i, k, nSuppSize;
+ // create and collect BDDs
+ vRootBdds = Llb_NonlinBuildBdds( p->pAig, p->vLeaves, p->vRoots, p->dd ); // come referenced
+ Vec_PtrPush( vRootBdds, p->bCurrent );
+ // add pairs (refs are consumed inside)
+ Vec_PtrForEachEntry( DdNode *, vRootBdds, bFunc, i )
+ {
+ 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_MAX( p->nSuppMax, nSuppSize );
+ }
+ Vec_PtrFree( vRootBdds );
+ // remove singles
+ Llb_MgrForEachPart( p, pPart, i )
+ if ( Llb_NonlinHasSingletonVars(p, pPart) )
+ Llb_NonlinQuantify1( p, pPart, 0 );
+}
+
+/**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 fVerbose )
+{
+ int clk = 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) );
+ 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", 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, DdNode * bCurrent )
+{
+ Llb_Mgr_t * p;
+ p = ABC_CALLOC( Llb_Mgr_t, 1 );
+ p->pAig = pAig;
+ p->vLeaves = vLeaves;
+ p->vRoots = vRoots;
+ p->dd = dd;
+ p->bCurrent = bCurrent;
+ p->pVars2Q = pVars2Q;
+ p->nVars = Cudd_ReadSize(dd);
+ p->iPartFree = Vec_PtrSize(vRoots) + 1;
+ p->pVars = ABC_CALLOC( Llb_Var_t *, p->nVars );
+ p->pParts = ABC_CALLOC( Llb_Prt_t *, 2 * p->iPartFree );
+ 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, int Limit )
+{
+ Llb_Prt_t * pPart, * pPart1, * pPart2;
+ Llb_Mgr_t * p;
+ DdNode * bFunc, * bTemp;
+ int i, nReorders, timeInside;
+ int clk = clock(), clk2;
+ // start the manager
+ clk2 = clock();
+ p = Llb_NonlinAlloc( pAig, vLeaves, vRoots, pVars2Q, dd, bCurrent );
+ Llb_NonlinStart( p );
+ timeBuild += clock() - clk2;
+ timeInside = clock() - clk2;
+ // compute scores
+ Llb_NonlinRecomputeScores( p );
+ // save permutation
+ memcpy( pOrder, dd->invperm, sizeof(int) * dd->size );
+ // iteratively quantify variables
+ while ( Llb_NonlinNextPartitions(p, &pPart1, &pPart2) )
+ {
+ clk2 = clock();
+ nReorders = Cudd_ReadReorderings(dd);
+ if ( Llb_NonlinQuantify2( p, pPart1, pPart2, Limit ) )
+ {
+ Llb_NonlinFree( p );
+ return NULL;
+ }
+ timeAndEx += clock() - clk2;
+ timeInside += 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, fVerbose );
+ timeOther += clock() - clk - timeInside;
+ // return
+ Cudd_Deref( bFunc );
+ return bFunc;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/aig/llb/llb3Nonlin.c b/src/aig/llb/llb3Nonlin.c
new file mode 100644
index 00000000..18562f5f
--- /dev/null
+++ b/src/aig/llb/llb3Nonlin.c
@@ -0,0 +1,711 @@
+/**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 * pOrder;
+
+ 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 timeImage;
+ int timeTran1;
+ int timeTran2;
+ int timeGloba;
+ int timeOther;
+ int timeTotal;
+ int timeReo;
+ int timeReoG;
+
+};
+
+extern int 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 )
+{
+ Aig_Obj_t * pObj;
+// Vec_Int_t * vVars;
+ DdNode * bCof, * bVar, * bTemp;
+ int i, iVar, iVarBest = -1, iValue, iValueBest = ABC_INFINITY;
+ int Size, Size0, Size1;
+ int clk = clock();
+// vVars = Vec_IntStartNatural( Cudd_ReadSize(dd) );
+ printf( "Original = %6d. SuppSize = %3d. Vars = %3d.\n",
+ Size = Cudd_DagSize(bFunc), Cudd_SupportSize(dd, bFunc), Aig_ManRegNum(pAig) );
+// Vec_IntForEachEntry( vVars, iVar, i )
+
+ Saig_ManForEachLo( pAig, pObj, i )
+ {
+ iVar = Aig_ObjId(pObj);
+/*
+ printf( "Var =%3d : ", iVar );
+ bVar = Cudd_bddIthVar(dd, iVar);
+
+ bCof = Cudd_Cofactor( dd, bFunc, Cudd_Not(bVar) ); Cudd_Ref( bCof );
+// bCof = Cudd_bddAnd( dd, bTemp = bCof, Cudd_Not(bVar) ); Cudd_Ref( bCof );
+// Cudd_RecursiveDeref( dd, bTemp );
+ printf( "Supp0 =%3d ", Cudd_SupportSize(dd, bCof) );
+ printf( "Size0 =%6d ", Size0 = Cudd_DagSize(bCof) );
+ Cudd_RecursiveDeref( dd, bCof );
+
+ bCof = Cudd_Cofactor( dd, bFunc, bVar ); Cudd_Ref( bCof );
+// bCof = Cudd_bddAnd( dd, bTemp = bCof, bVar ); Cudd_Ref( bCof );
+// Cudd_RecursiveDeref( dd, bTemp );
+ printf( "Supp1 =%3d ", Cudd_SupportSize(dd, bCof) );
+ printf( "Size1 =%6d ", Size1 = Cudd_DagSize(bCof) );
+ Cudd_RecursiveDeref( dd, bCof );
+
+ printf( "D =%6d ", Size0 + Size1 - Size );
+ printf( "B =%6d\n", ABC_MAX(Size0, Size1) - ABC_MIN(Size0, Size1) );
+*/
+
+// printf( "Var =%3d : ", iVar );
+ bVar = Cudd_bddIthVar(dd, iVar);
+
+ bCof = Cudd_Cofactor( dd, bFunc, Cudd_Not(bVar) ); Cudd_Ref( bCof );
+ bCof = Cudd_bddAnd( dd, bTemp = bCof, Cudd_Not(bVar) ); Cudd_Ref( bCof );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Size0 = Cudd_DagSize(bCof);
+// printf( "Supp0 =%3d ", Cudd_SupportSize(dd, bCof) );
+// printf( "Size0 =%6d ", Size0 );
+ Cudd_RecursiveDeref( dd, bCof );
+
+ bCof = Cudd_Cofactor( dd, bFunc, bVar ); Cudd_Ref( bCof );
+ bCof = Cudd_bddAnd( dd, bTemp = bCof, bVar ); Cudd_Ref( bCof );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Size1 = Cudd_DagSize(bCof);
+// printf( "Supp1 =%3d ", Cudd_SupportSize(dd, bCof) );
+// printf( "Size1 =%6d ", Size1 );
+ Cudd_RecursiveDeref( dd, bCof );
+
+ iValue = ABC_MAX(Size0, Size1) - ABC_MIN(Size0, Size1) + Size0 + Size1 - Size;
+// printf( "D =%6d ", Size0 + Size1 - Size );
+// printf( "B =%6d ", ABC_MAX(Size0, Size1) - ABC_MIN(Size0, Size1) );
+// printf( "S =%6d\n", iValue );
+
+ if ( iValueBest > iValue )
+ {
+ iValueBest = iValue;
+ iVarBest = i;
+ }
+ }
+// Vec_IntFree( vVars );
+ printf( "Best var = %d. Best value = %d. ", iVarBest, iValueBest );
+ Abc_PrintTime( 1, "Time", 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;
+ 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 );
+ return bRes;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Derives counter-example by backward reachability.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Cex_t * Llb_NonlinDeriveCex( Llb_Mnn_t * p )
+{
+ extern Abc_Cex_t * Ssw_SmlAllocCounterExample( int nRegs, int nRealPis, int nFrames );
+ extern int Ssw_SmlFindOutputCounterExample( Aig_Man_t * pAig, Abc_Cex_t * p );
+ Abc_Cex_t * pCex;
+ Aig_Obj_t * pObj;
+ Vec_Int_t * vVarsNs;
+ DdNode * bState, * bImage, * bOneCube, * bTemp, * bRing;
+ int i, v, RetValue, nPiOffset;
+ char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) );
+ assert( Vec_PtrSize(p->vRings) > 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) );
+ }
+
+ // allocate room for the counter-example
+ pCex = Ssw_SmlAllocCounterExample( 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, 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 )
+ Aig_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;
+ // compute the next states
+ bImage = Llb_NonlinImage( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->dd, bState,
+ p->pPars->fReorder, p->pPars->fVeryVerbose, p->pOrder, ABC_INFINITY ); // 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 )
+ Aig_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
+ RetValue = Ssw_SmlFindOutputCounterExample( 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_NonlinReachability( Llb_Mnn_t * p )
+{
+ DdNode * bCurrent, * bNext, * bTemp;
+ int nIters, nBddSize0, nBddSize;
+ int clk2, clk3, clk = clock();
+ assert( Aig_ManRegNum(p->pAig) > 0 );
+
+ // compute time to stop
+ if ( p->pPars->TimeLimit )
+ p->pPars->TimeTarget = clock() + p->pPars->TimeLimit * CLOCKS_PER_SEC;
+ else
+ p->pPars->TimeTarget = 0;
+
+ // create bad state in the ring manager
+ p->ddR->bFunc = Llb_BddComputeBad( p->pInit, p->ddR ); Cudd_Ref( p->ddR->bFunc );
+ // compute the starting set of states
+ bCurrent = Llb_NonlinComputeInitState( p->pAig, p->dd ); Cudd_Ref( bCurrent );
+ 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 = clock();
+ if ( p->pPars->TimeLimit && 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;
+ return -1;
+ }
+
+ // save the onion ring
+ bTemp = Extra_TransferPermute( p->dd, p->ddR, bCurrent, Vec_IntArray(p->vCs2Glo) ); 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 );
+ Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL;
+ if ( !p->pPars->fSilent )
+ {
+ if ( !p->pPars->fBackward )
+ printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump a witness). ", p->pInit->pSeqModel->iPo, nIters );
+ else
+ printf( "Output ??? was asserted in frame %d (counter-example is not produced). ", nIters );
+ Abc_PrintTime( 1, "Time", clock() - clk );
+ }
+ return 0;
+ }
+
+ // compute the next states
+ clk3 = clock();
+ nBddSize0 = Cudd_DagSize( bCurrent );
+ bNext = Llb_NonlinImage( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->dd, bCurrent,
+ p->pPars->fReorder, p->pPars->fVeryVerbose, p->pOrder, p->pPars->nBddMax );
+ if ( bNext == NULL ) // Llb_NonlimImage() consumes reference of bCurrent!!!
+ {
+ int iVar;
+ DdNode * bVar;
+// if ( !p->pPars->fSilent )
+// printf( "Reached timeout during image computation (%d seconds).\n", p->pPars->TimeLimit );
+// p->pPars->iFrame = nIters - 1;
+// return -1;
+
+ bCurrent = Extra_TransferPermute( p->ddG, p->dd, p->ddG->bFunc2, Vec_IntArray(p->vGlo2Cs) ); Cudd_Ref( bCurrent );
+
+ iVar = Llb_NonlinFindBestVar( p->dd, bCurrent, p->pAig );
+ bVar = Cudd_bddIthVar(p->dd, iVar);
+
+ bCurrent = Cudd_Cofactor( p->dd, bTemp = bCurrent, Cudd_Not(bVar) ); Cudd_Ref( bCurrent );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ bCurrent = Cudd_bddAnd( p->dd, bTemp = bCurrent, Cudd_Not(bVar) ); Cudd_Ref( bCurrent );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ continue;
+ }
+ Cudd_Ref( bNext );
+ nBddSize = Cudd_DagSize( bNext );
+ p->timeImage += clock() - clk3;
+
+ // transfer to the state manager
+ clk3 = clock();
+ Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc2 );
+ p->ddG->bFunc2 = Extra_TransferPermute( p->dd, p->ddG, bNext, Vec_IntArray(p->vNs2Glo) ); Cudd_Ref( p->ddG->bFunc2 );
+ Cudd_RecursiveDeref( p->dd, bNext );
+ p->timeTran1 += clock() - clk3;
+
+ // derive new states
+ clk3 = clock();
+ p->ddG->bFunc2 = Cudd_bddAnd( p->ddG, bTemp = p->ddG->bFunc2, Cudd_Not(p->ddG->bFunc) ); Cudd_Ref( p->ddG->bFunc2 );
+ Cudd_RecursiveDeref( p->ddG, bTemp );
+ if ( Cudd_IsConstant(p->ddG->bFunc2) )
+ break;
+ // add to the reached set
+ p->ddG->bFunc = Cudd_bddOr( p->ddG, bTemp = p->ddG->bFunc, p->ddG->bFunc2 ); Cudd_Ref( p->ddG->bFunc );
+ Cudd_RecursiveDeref( p->ddG, bTemp );
+ p->timeGloba += clock() - clk3;
+
+ // reset permutation
+// RetValue = Cudd_CheckZeroRef( dd );
+// assert( RetValue == 0 );
+// Cudd_ShuffleHeap( dd, pOrder );
+
+ // move new states to the working manager
+ clk3 = clock();
+ bCurrent = Extra_TransferPermute( p->ddG, p->dd, p->ddG->bFunc2, Vec_IntArray(p->vGlo2Cs) ); Cudd_Ref( bCurrent );
+ p->timeTran2 += clock() - clk3;
+
+ // report the results
+ if ( p->pPars->fVerbose )
+ {
+ printf( "I =%3d : ", nIters );
+ printf( "Fr =%7d ", nBddSize0 );
+ printf( "Im =%7d ", nBddSize );
+ printf( "(%4d %4d) ", Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) );
+ printf( "Rea =%6d ", Cudd_DagSize(p->ddG->bFunc) );
+ printf( "(%4d %4d) ", Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) );
+ printf( "S =%4d ", nSuppMax );
+ Abc_PrintTime( 1, "T", clock() - clk2 );
+ }
+/*
+ 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;
+ Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL;
+ return -1;
+ }
+// Llb_NonlinReorder( p->ddG, 1 );
+// Llb_NonlinFindBestVar( p->ddG, bReached, NULL );
+ }
+
+ // 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 );
+ 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", 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_ManPiNum(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_ManPiNum(pAig) );
+ Aig_ManForEachPi( pAig, pObj, i )
+ Vec_PtrPush( p->vLeaves, pObj );
+ // create roots
+ p->vRoots = Vec_PtrAlloc( Aig_ManPoNum(pAig) );
+ Saig_ManForEachLi( pAig, pObj, i )
+ Vec_PtrPush( p->vRoots, pObj );
+ // variables to quantify
+ p->pOrder = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) );
+ p->pVars2Q = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) );
+ Aig_ManForEachPi( pAig, pObj, i )
+ p->pVars2Q[Aig_ObjId(pObj)] = 1;
+ 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->timeReo = Cudd_ReadReorderingTime(p->dd);
+ 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->ddR->bFunc )
+ Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc );
+ if ( p->ddR->bFunc2 )
+ Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc2 );
+ Extra_StopManager( p->dd );
+ Extra_StopManager( p->ddG );
+ 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->pOrder );
+ 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;
+ int clk = 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 = 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 )
+ {
+ int clk = clock();
+ pMnn = Llb_MnnStart( pAig, p, pPars );
+ RetValue = Llb_NonlinReachability( pMnn );
+ pMnn->timeTotal = clock() - clk;
+ Llb_MnnStop( pMnn );
+ }
+
+ Aig_ManStop( p );
+ return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/aig/llb/llb3Nonlin_multi.c b/src/aig/llb/llb3Nonlin_multi.c
new file mode 100644
index 00000000..22ff2491
--- /dev/null
+++ b/src/aig/llb/llb3Nonlin_multi.c
@@ -0,0 +1,1490 @@
+/**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_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
+ Vec_Ptr_t * vFuncs; // current state functions in terms of vLeaves
+ 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++ )
+
+static int timeBuild, timeAndEx, timeOther;
+static int nSuppMax;
+
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Finds variable whose 0-cofactor is the smallest.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_NonlinFindBestVar( DdManager * dd, DdNode * bFunc, Vec_Int_t * vVars )
+{
+ DdNode * bCof, * bVar;
+ int i, iVar, iVarBest = -1;
+ int Size, Size0, Size1;
+ if ( vVars == NULL )
+ vVars = Vec_IntStartNatural( Cudd_ReadSize(dd) );
+ printf( "\nOriginal = %6d. SuppSize = %3d. Vars = %3d.\n",
+ Size = Cudd_DagSize(bFunc), Cudd_SupportSize(dd, bFunc), Vec_IntSize(vVars) );
+ Vec_IntForEachEntry( vVars, iVar, i )
+ {
+ printf( "Var =%3d : ", iVar );
+ bVar = Cudd_bddIthVar(dd, iVar);
+
+ bCof = Cudd_Cofactor( dd, bFunc, Cudd_Not(bVar) ); Cudd_Ref( bCof );
+ printf( "Supp0 =%3d ", Cudd_SupportSize(dd, bCof) );
+ printf( "Size0 =%6d ", Size0 = Cudd_DagSize(bCof) );
+ Cudd_RecursiveDeref( dd, bCof );
+
+ bCof = Cudd_Cofactor( dd, bFunc, bVar ); Cudd_Ref( bCof );
+ printf( "Supp1 =%3d ", Cudd_SupportSize(dd, bCof) );
+ printf( "Size1 =%6d ", Size1 = Cudd_DagSize(bCof) );
+ Cudd_RecursiveDeref( dd, bCof );
+
+ printf( "D =%6d ", Size0 + Size1 - Size );
+ printf( "B =%6d\n", ABC_MAX(Size0, Size1) - ABC_MIN(Size0, Size1) );
+ }
+ 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 [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;
+ 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 );
+ 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;
+ 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 );
+ 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 Limit )
+{
+ 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;
+/*
+ if ( iPart1 == 91 && iPart2 == 134 )
+ {
+ fVerbose = 1;
+ }
+*/
+ // 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, Limit );
+ return 1;
+ }
+ 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_MAX( 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 0;
+}
+
+/**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;
+
+ 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 = Cudd_bddAnd( dd, bBdd0, bBdd1 ); 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_NonlinStart( Llb_Mgr_t * p )
+{
+ Vec_Ptr_t * vRootBdds;
+ Llb_Prt_t * pPart;
+ DdNode * bFunc;
+ int i, k, nSuppSize;
+ // create and collect BDDs
+ vRootBdds = Llb_NonlinBuildBdds( p->pAig, p->vLeaves, p->vRoots, p->dd ); // come referenced
+ Vec_PtrForEachEntry( DdNode *, p->vFuncs, bFunc, i )
+ Vec_PtrPush( vRootBdds, bFunc );
+ // add pairs (refs are consumed inside)
+ Vec_PtrForEachEntry( DdNode *, vRootBdds, bFunc, i )
+ {
+ 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_MAX( p->nSuppMax, nSuppSize );
+ }
+ Vec_PtrFree( vRootBdds );
+ // remove singles
+ Llb_MgrForEachPart( p, pPart, i )
+ if ( Llb_NonlinHasSingletonVars(p, pPart) )
+ Llb_NonlinQuantify1( p, pPart, 0 );
+}
+
+/**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, Vec_Ptr_t * vFuncs )
+{
+ Llb_Mgr_t * p;
+ p = ABC_CALLOC( Llb_Mgr_t, 1 );
+ p->pAig = pAig;
+ p->vLeaves = vLeaves;
+ p->vRoots = vRoots;
+ p->dd = dd;
+ p->vFuncs = vFuncs;
+ p->pVars2Q = pVars2Q;
+ p->nVars = Cudd_ReadSize(dd);
+ p->iPartFree = Vec_PtrSize(vRoots) + Vec_PtrSize(vFuncs);
+ p->pVars = ABC_CALLOC( Llb_Var_t *, p->nVars );
+ p->pParts = ABC_CALLOC( Llb_Prt_t *, 2 * p->iPartFree );
+ 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 [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 fVerbose )
+{
+ int clk = 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) );
+ 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", 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 [Performs image computation.]
+
+ Description [Computes image of BDDs (vFuncs).]
+
+ SideEffects [BDDs in vFuncs are derefed inside. The result is refed.]
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_NonlinImage( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q,
+ DdManager * dd, Vec_Ptr_t * vFuncs, int fReorder, int fVerbose, int * pOrder, int * pfSubset, int Limit )
+{
+ Llb_Prt_t * pPart, * pPart1, * pPart2;
+ Llb_Mgr_t * p;
+ int i, nReorders, timeInside, fSubset = 0;
+ int clk = clock(), clk2;
+ // start the manager
+ clk2 = clock();
+ p = Llb_NonlinAlloc( pAig, vLeaves, vRoots, pVars2Q, dd, vFuncs );
+ Llb_NonlinStart( p );
+ timeBuild += clock() - clk2;
+ timeInside = clock() - clk2;
+ // reorder variables
+// if ( fReorder )
+// Llb_NonlinReorder( dd, fVerbose );
+ // compute scores
+ Llb_NonlinRecomputeScores( p );
+ // save permutation
+ memcpy( pOrder, dd->invperm, sizeof(int) * dd->size );
+ // iteratively quantify variables
+ while ( Llb_NonlinNextPartitions(p, &pPart1, &pPart2) )
+ {
+ nReorders = Cudd_ReadReorderings(dd);
+ clk2 = clock();
+ fSubset |= Llb_NonlinQuantify2( p, pPart1, pPart2, Limit );
+ timeAndEx += clock() - clk2;
+ timeInside += clock() - clk2;
+ if ( nReorders < Cudd_ReadReorderings(dd) )
+ Llb_NonlinRecomputeScores( p );
+// else
+// Llb_NonlinVerifyScores( p );
+ }
+ // load partitions
+ Vec_PtrClear( vFuncs );
+ Llb_MgrForEachPart( p, pPart, i )
+ {
+ Vec_PtrPush( vFuncs, pPart->bFunc );
+ Cudd_Ref( pPart->bFunc );
+ }
+ nSuppMax = p->nSuppMax;
+ Llb_NonlinFree( p );
+ // reorder variables
+ if ( fReorder )
+ Llb_NonlinReorder( dd, fVerbose );
+ timeOther += clock() - clk - timeInside;
+ if ( pfSubset )
+ *pfSubset |= fSubset;
+ return 1;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinPrepareVarMap( Aig_Man_t * pAig, Vec_Int_t ** pvNs2Glo, Vec_Int_t ** pvGlo2Cs )
+{
+ Aig_Obj_t * pObjLi, * pObjLo;
+ int i, iVarLi, iVarLo;
+ *pvNs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(pAig) );
+ *pvGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(pAig) );
+ Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
+ {
+ iVarLi = Aig_ObjId(pObjLi);
+ iVarLo = Aig_ObjId(pObjLo);
+ assert( iVarLi >= 0 && iVarLi < Aig_ManObjNumMax(pAig) );
+ assert( iVarLo >= 0 && iVarLo < Aig_ManObjNumMax(pAig) );
+ Vec_IntWriteEntry( *pvNs2Glo, iVarLi, i );
+ Vec_IntWriteEntry( *pvGlo2Cs, i, iVarLo );
+ }
+}
+
+
+/**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;
+ 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 );
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_NonlinComputeInitStateVec( Aig_Man_t * pAig, DdManager * dd )
+{
+ Vec_Ptr_t * vFuncs;
+ Aig_Obj_t * pObj;
+ DdNode * bVar;
+ int i;
+ vFuncs = Vec_PtrAlloc( Aig_ManRegNum(pAig) );
+ Saig_ManForEachLo( pAig, pObj, i )
+ {
+ bVar = Cudd_bddIthVar( dd, Aig_ObjId(pObj) ); Cudd_Ref( bVar );
+ Vec_PtrPush( vFuncs, Cudd_Not(bVar) );
+ }
+ return vFuncs;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinDerefVec( DdManager * dd, Vec_Ptr_t * vFuncs )
+{
+ DdNode * bFunc;
+ int i;
+ Vec_PtrForEachEntry( DdNode *, vFuncs, bFunc, i )
+ Cudd_RecursiveDeref( dd, bFunc );
+ Vec_PtrFree( vFuncs );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinTransferVec( DdManager * dd, DdManager * ddG, Vec_Ptr_t * vFuncs, Vec_Int_t * vNs2Glo )
+{
+ DdNode * bFunc, * bTemp;
+ int i;
+ Vec_PtrForEachEntry( DdNode *, vFuncs, bFunc, i )
+ {
+ bFunc = Extra_TransferPermute( dd, ddG, bTemp = bFunc, Vec_IntArray(vNs2Glo) ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Vec_PtrWriteEntry( vFuncs, i, bFunc );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinSharpVec( DdManager * ddG, DdNode * bReached, Vec_Ptr_t * vFuncs )
+{
+ DdNode * bFunc, * bTemp;
+ int i;
+ Vec_PtrForEachEntry( DdNode *, vFuncs, bFunc, i )
+ {
+ bFunc = Cudd_bddAnd( ddG, bTemp = bFunc, Cudd_Not(bReached) ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( ddG, bTemp );
+ Vec_PtrWriteEntry( vFuncs, i, bFunc );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_NonlinAddToReachVec( DdManager * ddG, DdNode * bReached, Vec_Ptr_t * vFuncs )
+{
+ DdNode * bFunc, * bProd, * bTemp;
+ int i;
+ bProd = Cudd_ReadOne( ddG ); Cudd_Ref( bProd );
+ Vec_PtrForEachEntry( DdNode *, vFuncs, bFunc, i )
+ {
+ bProd = Cudd_bddAnd( ddG, bTemp = bProd, bFunc ); Cudd_Ref( bProd );
+ Cudd_RecursiveDeref( ddG, bTemp );
+ }
+ if ( Cudd_IsConstant(bProd) )
+ {
+ Cudd_RecursiveDeref( ddG, bProd );
+ return NULL;
+ }
+ bTemp = Cudd_bddOr( ddG, bReached, bProd ); Cudd_Ref( bTemp );
+ Cudd_RecursiveDeref( ddG, bProd );
+ Cudd_Deref( bTemp );
+ return bTemp;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_NonlinCreateReachVec( DdManager * dd, DdManager * ddG, DdNode * bReachG, Vec_Int_t * vGlo2Cs )
+{
+ Vec_Ptr_t * vFuncs;
+ DdNode * bFunc;
+ vFuncs = Vec_PtrAlloc( 1 );
+ bFunc = Extra_TransferPermute( ddG, dd, bReachG, Vec_IntArray(vGlo2Cs) ); Cudd_Ref( bFunc );
+ Vec_PtrPush( vFuncs, bFunc );
+// Llb_NonlinReorder( dd, 1 );
+ return vFuncs;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinPrintVec( DdManager * dd, Vec_Ptr_t * vFuncs )
+{
+ DdNode * bFunc;
+ int i;
+ Vec_PtrForEachEntry( DdNode *, vFuncs, bFunc, i )
+ {
+ printf( "%2d : ", i );
+ printf( "Support =%5d ", Cudd_SupportSize(dd, bFunc) );
+ printf( "DagSize =%7d\n", Cudd_DagSize(bFunc) );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Perform reachability with hints.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_NonlinReachability( Aig_Man_t * pAig, Gia_ParLlb_t * pPars )
+{
+ Aig_Obj_t * pObj;
+ Vec_Ptr_t * vLeaves, * vRoots, * vParts;
+ Vec_Int_t * vNs2Glo, * vGlo2Cs;
+ DdManager * dd, * ddG;
+ DdNode * bReached, * bTemp;
+ int i, nIters, nBddSize0, nBddSize, Limit, fSubset, * pVars2Q, * pOrder;
+ int clk2, clk3, clk = clock();
+// int RetValue;
+ int timeImage = 0;
+ int timeTran1 = 0;
+ int timeTran2 = 0;
+ int timeGloba = 0;
+ int timeOther = 0;
+ int timeTotal = 0;
+ int timeReo = 0;
+ int timeReoG = 0;
+ assert( Aig_ManRegNum(pAig) > 0 );
+ timeBuild = timeAndEx = timeOther = 0;
+
+ // compute time to stop
+ if ( pPars->TimeLimit )
+ pPars->TimeTarget = clock() + pPars->TimeLimit * CLOCKS_PER_SEC;
+ else
+ pPars->TimeTarget = 0;
+
+ // create leaves
+ vLeaves = Vec_PtrAlloc( Aig_ManPiNum(pAig) );
+ Aig_ManForEachPi( pAig, pObj, i )
+ Vec_PtrPush( vLeaves, pObj );
+
+ // create roots
+ vRoots = Vec_PtrAlloc( Aig_ManPoNum(pAig) );
+ Saig_ManForEachLi( pAig, pObj, i )
+ Vec_PtrPush( vRoots, pObj );
+
+ // variables to quantify
+ pOrder = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) );
+ pVars2Q = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) );
+ Aig_ManForEachPi( pAig, pObj, i )
+ pVars2Q[Aig_ObjId(pObj)] = 1;
+
+ // start the managers
+ Llb_NonlinPrepareVarMap( pAig, &vNs2Glo, &vGlo2Cs );
+ dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ ddG = Cudd_Init( Aig_ManRegNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+ Cudd_AutodynEnable( ddG, CUDD_REORDER_SYMM_SIFT );
+
+ // compute the starting set of states
+ vParts = Llb_NonlinComputeInitStateVec( pAig, dd );
+ bReached = Llb_NonlinComputeInitState( pAig, ddG ); Cudd_Ref( bReached );
+ fSubset = 1;
+ for ( Limit = pPars->nBddMax; fSubset; Limit *= 2 )
+ {
+ if ( pPars->fVerbose )
+ printf( "*********** LIMIT %d ************\n", Limit );
+ fSubset = 0;
+ for ( nIters = 0; nIters < pPars->nIterMax; nIters++ )
+ {
+ clk2 = clock();
+ // check the runtime limit
+ if ( pPars->TimeLimit && clock() >= pPars->TimeTarget )
+ {
+ if ( !pPars->fSilent )
+ printf( "Reached timeout during image computation (%d seconds).\n", pPars->TimeLimit );
+ pPars->iFrame = nIters - 1;
+ Llb_NonlinDerefVec( dd, vParts ); vParts = NULL;
+ Cudd_RecursiveDeref( ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+
+// Llb_NonlinReorder( dd, 1 );
+
+ // compute the next states
+ clk3 = clock();
+ nBddSize0 = Cudd_SharingSize( (DdNode **)Vec_PtrArray(vParts), Vec_PtrSize(vParts) );
+ if ( !Llb_NonlinImage( pAig, vLeaves, vRoots, pVars2Q, dd, vParts, pPars->fReorder, pPars->fVeryVerbose, pOrder, &fSubset, Limit ) )
+ {
+ if ( !pPars->fSilent )
+ printf( "Reached timeout during image computation (%d seconds).\n", pPars->TimeLimit );
+ pPars->iFrame = nIters - 1;
+ Llb_NonlinDerefVec( dd, vParts ); vParts = NULL;
+ Cudd_RecursiveDeref( ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+ timeImage += clock() - clk3;
+ nBddSize = Cudd_SharingSize( (DdNode **)Vec_PtrArray(vParts), Vec_PtrSize(vParts) );
+// Llb_NonlinPrintVec( dd, vParts );
+
+ // check containment in reached and derive new frontier
+ clk3 = clock();
+ Llb_NonlinTransferVec( dd, ddG, vParts, vNs2Glo );
+ timeTran1 += clock() - clk3;
+
+ clk3 = clock();
+ Llb_NonlinSharpVec( ddG, bReached, vParts );
+ bReached = Llb_NonlinAddToReachVec( ddG, bTemp = bReached, vParts );
+ if ( bReached == NULL )
+ {
+ bReached = bTemp;
+ Llb_NonlinDerefVec( ddG, vParts ); vParts = NULL;
+ if ( fSubset )
+ vParts = Llb_NonlinCreateReachVec( dd, ddG, bReached, vGlo2Cs );
+ break;
+ }
+ Cudd_Ref( bReached );
+ Cudd_RecursiveDeref( ddG, bTemp );
+ timeGloba += clock() - clk3;
+
+ // reset permutation
+ // RetValue = Cudd_CheckZeroRef( dd );
+ // assert( RetValue == 0 );
+ // Cudd_ShuffleHeap( dd, pOrder );
+
+ clk3 = clock();
+ Llb_NonlinTransferVec( ddG, dd, vParts, vGlo2Cs );
+// Llb_NonlinDerefVec( ddG, vParts ); vParts = NULL;
+// vParts = Llb_NonlinCreateReachVec( dd, ddG, bReached, vGlo2Cs );
+ timeTran2 += clock() - clk3;
+
+ // report the results
+ if ( pPars->fVerbose )
+ {
+ printf( "I =%3d : ", nIters );
+ printf( "Fr =%6d ", nBddSize0 );
+ printf( "Im =%6d ", nBddSize );
+ printf( "(%4d %3d) ", Cudd_ReadReorderings(dd), Cudd_ReadGarbageCollections(dd) );
+ printf( "Rea =%6d ", Cudd_DagSize(bReached) );
+ printf( "(%4d %3d) ", Cudd_ReadReorderings(ddG), Cudd_ReadGarbageCollections(ddG) );
+ printf( "S =%4d ", nSuppMax );
+ printf( "P =%2d ", Vec_PtrSize(vParts) );
+ Abc_PrintTime( 1, "T", clock() - clk2 );
+ }
+ /*
+ 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 == pPars->nIterMax - 1 )
+ {
+ if ( !pPars->fSilent )
+ printf( "Reached limit on the number of timeframes (%d).\n", pPars->nIterMax );
+ pPars->iFrame = nIters;
+ Llb_NonlinDerefVec( dd, vParts ); vParts = NULL;
+ Cudd_RecursiveDeref( ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+
+// Llb_NonlinReorder( ddG, 1 );
+// Llb_NonlinFindBestVar( ddG, bReached, NULL );
+ }
+ }
+
+ if ( bReached == NULL )
+ return 0; // reachable
+ // report the stats
+ if ( pPars->fVerbose )
+ {
+ double nMints = Cudd_CountMinterm(ddG, bReached, Saig_ManRegNum(pAig) );
+ if ( nIters >= pPars->nIterMax || nBddSize > 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(pAig)) );
+ fflush( stdout );
+ }
+ if ( nIters >= pPars->nIterMax || nBddSize > pPars->nBddMax )
+ {
+ if ( !pPars->fSilent )
+ printf( "Verified only for states reachable in %d frames. ", nIters );
+ Cudd_RecursiveDeref( ddG, bReached );
+ return -1; // undecided
+ }
+ // cleanup
+ Cudd_RecursiveDeref( ddG, bReached );
+ timeReo = Cudd_ReadReorderingTime(dd);
+ timeReoG = Cudd_ReadReorderingTime(ddG);
+ Extra_StopManager( dd );
+ Extra_StopManager( ddG );
+ // cleanup
+ Vec_IntFree( vNs2Glo );
+ Vec_IntFree( vGlo2Cs );
+ Vec_PtrFree( vLeaves );
+ Vec_PtrFree( vRoots );
+ ABC_FREE( pVars2Q );
+ ABC_FREE( pOrder );
+ // report
+ if ( !pPars->fSilent )
+ printf( "The miter is proved unreachable after %d iterations. ", nIters );
+ pPars->iFrame = nIters - 1;
+ Abc_PrintTime( 1, "Time", clock() - clk );
+
+ if ( pPars->fVerbose )
+ {
+ timeTotal = clock() - clk;
+ timeOther = timeTotal - timeImage - timeTran1 - timeTran2 - timeGloba;
+ ABC_PRTP( "Image ", timeImage, timeTotal );
+ ABC_PRTP( " build ", timeBuild, timeTotal );
+ ABC_PRTP( " and-ex ", timeAndEx, timeTotal );
+ ABC_PRTP( " other ", timeOther, timeTotal );
+ ABC_PRTP( "Transfer1", timeTran1, timeTotal );
+ ABC_PRTP( "Transfer2", timeTran2, timeTotal );
+ ABC_PRTP( "Global ", timeGloba, timeTotal );
+ ABC_PRTP( "Other ", timeOther, timeTotal );
+ ABC_PRTP( "TOTAL ", timeTotal, timeTotal );
+ ABC_PRTP( " reo ", timeReo, timeTotal );
+ ABC_PRTP( " reoG ", timeReoG, timeTotal );
+ }
+ return 1; // unreachable
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds balanced cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinExperiment( Aig_Man_t * pAig, int Num )
+{
+ Gia_ParLlb_t Pars, * pPars = &Pars;
+ Aig_Man_t * p;
+
+ Llb_ManSetDefaultParams( pPars );
+ pPars->fVerbose = 1;
+
+ p = Aig_ManDupFlopsOnly( pAig );
+//Aig_ManShow( p, 0, NULL );
+ Aig_ManPrintStats( pAig );
+ Aig_ManPrintStats( p );
+
+ Llb_NonlinReachability( p, pPars );
+
+ Aig_ManStop( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds balanced cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_NonlinCoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars )
+{
+ 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 )
+ RetValue = Llb_NonlinReachability( p, pPars );
+
+ Aig_ManStop( p );
+ return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/aig/llb/llbCex.c b/src/aig/llb/llbCex.c
deleted file mode 100644
index 87059c0c..00000000
--- a/src/aig/llb/llbCex.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/**CFile****************************************************************
-
- FileName [llbCex.c]
-
- SystemName [ABC: Logic synthesis and verification system.]
-
- PackageName [BDD based reachability.]
-
- Synopsis [Deriving counter-example.]
-
- Author [Alan Mishchenko]
-
- Affiliation [UC Berkeley]
-
- Date [Ver. 1.0. Started - June 20, 2005.]
-
- Revision [$Id: llbCex.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 []
-
-***********************************************************************/
-Abc_Cex_t * Llb_ManDeriveCex( Llb_Man_t * p, DdNode * bInter, int iOutFail, int iIter )
-{
- return NULL;
-}
-
-////////////////////////////////////////////////////////////////////////
-/// END OF FILE ///
-////////////////////////////////////////////////////////////////////////
-
-
-ABC_NAMESPACE_IMPL_END
-
diff --git a/src/aig/llb/llbFlow.c b/src/aig/llb/llbFlow.c
deleted file mode 100644
index 55405c09..00000000
--- a/src/aig/llb/llbFlow.c
+++ /dev/null
@@ -1,639 +0,0 @@
-/**CFile****************************************************************
-
- FileName [llbFlow.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: llbFlow.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
-
-***********************************************************************/
-
-#include "llbInt.h"
-
-ABC_NAMESPACE_IMPL_START
-
-
-////////////////////////////////////////////////////////////////////////
-/// DECLARATIONS ///
-////////////////////////////////////////////////////////////////////////
-
-typedef struct Llb_Flw_t_ Llb_Flw_t;
-struct Llb_Flw_t_
-{
- unsigned Source : 1; // source of the graph
- unsigned Sink : 1; // sink of the graph
- unsigned Flow : 1; // node has flow
- unsigned Mark : 1; // visited node
- unsigned Id : 14; // ID of the corresponding node
- unsigned nFanins : 14; // number of fanins
- Llb_Flw_t * Fanins[0]; // fanins
-};
-
-////////////////////////////////////////////////////////////////////////
-/// FUNCTION DEFINITIONS ///
-////////////////////////////////////////////////////////////////////////
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Llb_Flw_t * Llb_FlwAlloc( Vec_Int_t * vMem, Vec_Ptr_t * vStore, int Id, int nFanins )
-{
- Llb_Flw_t * p;
- int nWords = (sizeof(Llb_Flw_t) + nFanins * sizeof(void *)) / sizeof(int);
- p = (Llb_Flw_t *)Vec_IntFetch( vMem, nWords );
- memset( p, 1, nWords * sizeof(int) );
- p->Id = Id;
- p->nFanins = 0;//nFanins;
- Vec_PtrWriteEntry( vStore, Id, p );
- return p;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Llb_FlwAddFanin( Llb_Flw_t * pFrom, Llb_Flw_t * pTo )
-{
- pFrom->Fanins[pFrom->nFanins++] = pTo;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Llb_AigCreateFlw( Aig_Man_t * p, Vec_Int_t ** pvMem, Vec_Ptr_t ** pvTops, Vec_Ptr_t ** pvBots )
-{
- Llb_Flw_t * pFlwTop, * pFlwBot;
- Vec_Ptr_t * vTops, * vBots;
- Vec_Int_t * vMem;
- Aig_Obj_t * pObj;
- int i;
- vMem = Vec_IntAlloc( Aig_ManObjNumMax(p) * (sizeof(Llb_Flw_t) + sizeof(void *) * 8) );
- vBots = Vec_PtrStart( Aig_ManObjNumMax(p) );
- vTops = Vec_PtrStart( Aig_ManObjNumMax(p) );
- Aig_ManForEachObj( p, pObj, i )
- {
- pFlwBot = Llb_FlwAlloc( vMem, vBots, i, Aig_ObjIsPo(pObj) + 2 * Aig_ObjIsNode(pObj) );
- pFlwTop = Llb_FlwAlloc( vMem, vTops, i, Aig_ObjRefs(pObj) + 1 );
- Llb_FlwAddFanin( pFlwBot, pFlwTop );
- Llb_FlwAddFanin( pFlwTop, pFlwBot );
- Llb_FlwAddFanin( pFlwBot, (Llb_Flw_t *)Vec_PtrEntry(vTops, Aig_ObjFaninId0(pObj)) );
- Llb_FlwAddFanin( pFlwBot, (Llb_Flw_t *)Vec_PtrEntry(vTops, Aig_ObjFaninId1(pObj)) );
- Llb_FlwAddFanin( (Llb_Flw_t *)Vec_PtrEntry(vTops, Aig_ObjFaninId0(pObj)), pFlwBot );
- Llb_FlwAddFanin( (Llb_Flw_t *)Vec_PtrEntry(vTops, Aig_ObjFaninId1(pObj)), pFlwBot );
- }
- Aig_ManForEachObj( p, pObj, i )
- {
- pFlwBot = (Llb_Flw_t *)Vec_PtrEntry( vBots, i );
- pFlwTop = (Llb_Flw_t *)Vec_PtrEntry( vTops, i );
- assert( pFlwBot->nFanins == (unsigned)Aig_ObjIsPo(pObj) + 2 * Aig_ObjIsNode(pObj) );
- assert( pFlwTop->nFanins == (unsigned)Aig_ObjRefs(pObj) + 1 );
- }
- *pvMem = vMem;
- *pvTops = vTops;
- *pvBots = vBots;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Llb_AigCleanMarks( Vec_Ptr_t * vFlw )
-{
- Llb_Flw_t * pFlw;
- int i;
- Vec_PtrForEachEntry( Llb_Flw_t *, vFlw, pFlw, i )
- pFlw->Mark = 0;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Llb_AigCleanFlow( Vec_Ptr_t * vFlw )
-{
- Llb_Flw_t * pFlw;
- int i;
- Vec_PtrForEachEntry( Llb_Flw_t *, vFlw, pFlw, i )
- pFlw->Flow = 0;
-}
-
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Vec_Int_t * Llb_AigCollectCut( Vec_Ptr_t * vNodes, Vec_Ptr_t * vBots, Vec_Ptr_t * vTops )
-{
- Vec_Int_t * vCut;
- Llb_Flw_t * pFlwBot, * pFlwTop;
- Aig_Obj_t * pObj;
- int i;
- vCut = Vec_IntAlloc( 100 );
- Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
- {
- pFlwBot = (Llb_Flw_t *)Vec_PtrEntry( vBots, i );
- pFlwTop = (Llb_Flw_t *)Vec_PtrEntry( vTops, i );
- if ( pFlwBot->Mark && !pFlwTop->Mark )
- Vec_IntPush( vCut, i );
- }
- return vCut;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-int Llb_AigPushFlow_rec( Llb_Flw_t * pFlw, Llb_Flw_t * pFlwPrev, Vec_Ptr_t * vMarked, Vec_Ptr_t * vFlowed )
-{
- int i;
- if ( pFlw->Mark )
- return 0;
- pFlw->Mark = 1;
- Vec_PtrPush( vMarked, pFlw );
- if ( pFlw->Source )
- return 0;
- if ( pFlw->Sink )
- {
- pFlw->Flow = 1;
- Vec_PtrPush( vFlowed, pFlw );
- return 1;
- }
-// assert( Aig_ObjIsNode(pObj) );
- for ( i = 0; i < (int)pFlw->nFanins; i++ )
- {
- if ( pFlw->Fanins[i] == pFlwPrev )
- continue;
- if ( Llb_AigPushFlow_rec( pFlw->Fanins[i], pFlw, vMarked, vFlowed ) )
- break;
- }
- if ( i == (int)pFlw->nFanins )
- return 0;
- if ( i == 0 )
- {
- pFlw->Flow = 1;
- Vec_PtrPush( vFlowed, pFlw );
- }
- return 1;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-int Llb_AigPushFlow( Vec_Ptr_t * vFlwBots, Vec_Ptr_t * vMarked, Vec_Ptr_t * vFlowed )
-{
- Llb_Flw_t * pFlw;
- int i, Counter = 0;
- Vec_PtrForEachEntry( Llb_Flw_t *, vFlwBots, pFlw, i )
- {
- pFlw->Mark = 1;
- if ( Llb_AigPushFlow_rec( pFlw->Fanins[0], pFlw, vMarked, vFlowed ) )
- {
- Counter++;
- pFlw->Flow = 1;
- Vec_PtrPush( vFlowed, pFlw );
- }
- }
- return Counter;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Vec_Int_t * Llb_AigFindMinCut( Vec_Ptr_t * vNodes, Vec_Ptr_t * vFlwBots, Vec_Ptr_t * vFlwTop, Vec_Ptr_t * vFlwBots2, Vec_Ptr_t * vFlwTop2 )
-{
- Vec_Int_t * vCut;
- Vec_Ptr_t * vMarked, * vFlowed;
- int Value;
- vMarked = Vec_PtrAlloc( 100 );
- vFlowed = Vec_PtrAlloc( 100 );
- Value = Llb_AigPushFlow( vFlwBots2, vMarked, vFlowed );
- Llb_AigCleanMarks( vMarked );
- Value = Llb_AigPushFlow( vFlwBots2, vMarked, vFlowed );
- assert( Value == 0 );
- vCut = Llb_AigCollectCut( vNodes, vFlwBots, vFlwTop );
- Llb_AigCleanMarks( vMarked );
- Llb_AigCleanFlow( vFlowed );
- return vCut;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Vec_Ptr_t * Llb_AigCollectFlowTerminals( Aig_Man_t * p, Vec_Ptr_t * vFlws, Vec_Int_t * vCut )
-{
- Vec_Ptr_t * pFlwRes;
- Aig_Obj_t * pObj;
- int i;
- pFlwRes = Vec_PtrAlloc( Vec_IntSize(vCut) );
- Aig_ManForEachNodeVec( p, vCut, pObj, i )
- Vec_PtrPush( pFlwRes, Vec_PtrEntry( vFlws, Aig_ObjId(pObj) ) );
- return pFlwRes;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Llb_AigMarkFlowTerminals( Vec_Ptr_t * vFlws, int fSource, int fSink )
-{
- Llb_Flw_t * pFlw;
- int i;
- Vec_PtrForEachEntry( Llb_Flw_t *, vFlws, pFlw, i )
- {
- pFlw->Source = fSource;
- pFlw->Sink = fSink;
- }
-}
-
-/**Function*************************************************************
-
- Synopsis [Collects internal nodes in the DFS order.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Llb_ManCollectNodes_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_ManCollectNodes_rec( p, Aig_ObjFanin0(pObj), vNodes );
- Llb_ManCollectNodes_rec( p, Aig_ObjFanin1(pObj), vNodes );
- Vec_PtrPush( vNodes, pObj );
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Vec_Ptr_t * Llb_ManCollectNodes( Aig_Man_t * p, Vec_Int_t * vCut1, Vec_Int_t * vCut2 )
-{
- Vec_Ptr_t * vNodes;
- Aig_Obj_t * pObj;
- int i;
- Aig_ManIncrementTravId( p );
- Aig_ManForEachNodeVec( p, vCut1, pObj, i )
- Aig_ObjSetTravIdCurrent( p, pObj );
- vNodes = Vec_PtrAlloc( Aig_ManObjNumMax(p) );
- Aig_ManForEachNodeVec( p, vCut2, pObj, i )
- Llb_ManCollectNodes_rec( p, pObj, vNodes );
- return vNodes;
-}
-
-/**Function*************************************************************
-
- Synopsis [Collects internal nodes in the DFS order.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-int Llb_ManCountNodes_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_ManCountNodes_rec( p, Aig_ObjFanin0(pObj) ) +
- Llb_ManCountNodes_rec( p, Aig_ObjFanin1(pObj) );
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-int Llb_ManCountNodes( Aig_Man_t * p, Vec_Int_t * vCut1, Vec_Int_t * vCut2 )
-{
- Aig_Obj_t * pObj;
- int i, Counter = 0;
- Aig_ManIncrementTravId( p );
- Aig_ManForEachNodeVec( p, vCut1, pObj, i )
- Aig_ObjSetTravIdCurrent( p, pObj );
- Aig_ManForEachNodeVec( p, vCut2, pObj, i )
- Counter += Llb_ManCountNodes_rec( p, pObj );
- return Counter;
-}
-
-/**Function*************************************************************
-
- Synopsis [Computes starting cuts.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Vec_Int_t * Llb_ManComputeCioCut( Aig_Man_t * pAig, int fCollectCos )
-{
- Vec_Int_t * vCut;
- Aig_Obj_t * pObj;
- int i;
- vCut = Vec_IntAlloc( 500 );
- if ( fCollectCos )
- Aig_ManForEachPo( pAig, pObj, i )
- Vec_IntPush( vCut, Aig_ObjId(pObj) );
- else
- Aig_ManForEachPi( pAig, pObj, i )
- Vec_IntPush( vCut, Aig_ObjId(pObj) );
- return vCut;
-}
-
-/**Function*************************************************************
-
- Synopsis [Inserts the new cut into the array.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Llb_ManCutInsert( Aig_Man_t * p, Vec_Ptr_t * vCuts, Vec_Int_t * vVols, int iEntry, Vec_Int_t * vCutNew )
-{
- Vec_Int_t * vCut1, * vCut2;
- int Vol1, Vol2;
- Vec_PtrInsert( vCuts, iEntry, vCutNew );
- Vec_IntInsert( vVols, iEntry, -1 );
- vCut1 = (Vec_Int_t *)Vec_PtrEntry( vCuts, iEntry );
- vCut2 = (Vec_Int_t *)Vec_PtrEntry( vCuts, iEntry+1 );
- Vol1 = Llb_ManCountNodes( p, vCut1, vCutNew );
- Vol2 = Llb_ManCountNodes( p, vCutNew, vCut2 );
- Vec_IntWriteEntry( vVols, iEntry-1, Vol1 );
- Vec_IntWriteEntry( vVols, iEntry, Vol2 );
-}
-
-/**Function*************************************************************
-
- Synopsis [Returns the set of cuts resulting from the flow computation.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Vec_Ptr_t * Llb_ManComputePartitioning( Aig_Man_t * p, int nVolumeMin, int nVolumeMax )
-{
- Vec_Ptr_t * vCuts, * vFlwTops, * vFlwBots;
- Vec_Int_t * vVols, * vCut1, * vCut2, * vCut, * vMem;
- int nMaxValue, iEntry;
- vCuts = Vec_PtrAlloc( 1000 );
- vVols = Vec_IntAlloc( 1000 );
- // prepare flow computation
- Llb_AigCreateFlw( p, &vMem, &vFlwTops, &vFlwBots );
- // start with regular cuts
- Vec_PtrPush( vCuts, Llb_ManComputeCioCut(p, 0) );
- Vec_PtrPush( vCuts, Llb_ManComputeCioCut(p, 1) );
- Vec_IntPush( vVols, Aig_ManNodeNum(p) );
- // split cuts with the largest volume
- while ( (nMaxValue = Vec_IntFindMax(vVols)) > nVolumeMax )
- {
- Vec_Ptr_t * vNodes, * vFlwBots2, * vFlwTops2;
- iEntry = Vec_IntFind( vVols, nMaxValue ); assert( iEntry >= 0 );
- vCut1 = (Vec_Int_t *)Vec_PtrEntry( vCuts, iEntry );
- vCut2 = (Vec_Int_t *)Vec_PtrEntry( vCuts, iEntry+1 );
- // collect nodes
- vNodes = Llb_ManCollectNodes( p, vCut1, vCut1 );
- assert( Vec_PtrSize(vNodes) == nMaxValue );
- assert( Llb_ManCountNodes(p, vCut1, vCut2) == nMaxValue );
- // collect sources and sinks
- vFlwBots2 = Llb_AigCollectFlowTerminals( p, vFlwBots, vCut1 );
- vFlwTops2 = Llb_AigCollectFlowTerminals( p, vFlwTops, vCut2 );
- // mark sources and sinks
- Llb_AigMarkFlowTerminals( vFlwBots2, 1, 0 );
- Llb_AigMarkFlowTerminals( vFlwTops2, 0, 1 );
- vCut = Llb_AigFindMinCut( vNodes, vFlwBots, vFlwTops, vFlwBots2, vFlwTops2 );
- Llb_AigMarkFlowTerminals( vFlwBots2, 0, 0 );
- Llb_AigMarkFlowTerminals( vFlwTops2, 0, 0 );
- // insert new cut
- Llb_ManCutInsert( p, vCuts, vVols, iEntry+1, vCut );
- // deallocate
- Vec_PtrFree( vNodes );
- Vec_PtrFree( vFlwBots2 );
- Vec_PtrFree( vFlwTops2 );
- }
- Vec_IntFree( vMem );
- Vec_PtrFree( vFlwTops );
- Vec_PtrFree( vFlwBots );
- return vCuts;
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Vec_Int_t * Llb_ManMarkPivotNodesFlow( Aig_Man_t * p, Vec_Ptr_t * vCuts )
-{
- Vec_Int_t * vVar2Obj, * vCut;
- Aig_Obj_t * pObj;
- int i, k;
- // mark inputs/outputs
- Aig_ManForEachPi( p, pObj, i )
- pObj->fMarkA = 1;
- Saig_ManForEachLi( p, pObj, i )
- pObj->fMarkA = 1;
-
- // mark internal pivot nodes
- Vec_PtrForEachEntry( Vec_Int_t *, vCuts, vCut, i )
- Aig_ManForEachNodeVec( p, vCut, pObj, k )
- pObj->fMarkA = 1;
-
- // assign variable numbers
- Aig_ManConst1(p)->fMarkA = 0;
- vVar2Obj = Vec_IntAlloc( 100 );
- Aig_ManForEachPi( 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;
-}
-
-/**Function*************************************************************
-
- Synopsis [Returns the set of cuts resulting from the flow computation.]
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-void Llb_ManPartitionUsingFlow( Llb_Man_t * p, Vec_Ptr_t * vCuts )
-{
- Vec_Int_t * vCut1, * vCut2;
- int i;
- vCut1 = (Vec_Int_t *)Vec_PtrEntry( vCuts, 0 );
- Vec_PtrForEachEntryStart( Vec_Int_t *, vCuts, vCut1, i, 1 )
- {
- vCut2 = (Vec_Int_t *)Vec_PtrEntry( vCuts, i );
- Llb_ManGroupCreateFromCuts( p, vCut1, vCut2 );
- vCut1 = vCut2;
- }
-}
-
-/**Function*************************************************************
-
- Synopsis []
-
- Description []
-
- SideEffects []
-
- SeeAlso []
-
-***********************************************************************/
-Llb_Man_t * Llb_ManStartFlow( Aig_Man_t * pAigGlo, Aig_Man_t * pAig, Gia_ParLlb_t * pPars )
-{
- Vec_Ptr_t * vCuts;
- Llb_Man_t * p;
- vCuts = Llb_ManComputePartitioning( pAig, pPars->nVolumeMin, pPars->nVolumeMax );
- Aig_ManCleanMarkA( pAig );
- p = ABC_CALLOC( Llb_Man_t, 1 );
- p->pAigGlo = pAigGlo;
- p->pPars = pPars;
- p->pAig = pAig;
- p->vVar2Obj = Llb_ManMarkPivotNodesFlow( p->pAig, vCuts );
- p->vObj2Var = Vec_IntInvert( p->vVar2Obj, -1 );
- Llb_ManPrepareVarMap( p );
- Aig_ManCleanMarkA( pAig );
- Llb_ManPartitionUsingFlow( p, vCuts );
- Vec_VecFreeP( (Vec_Vec_t **)&vCuts );
- return p;
-}
-
-////////////////////////////////////////////////////////////////////////
-/// END OF FILE ///
-////////////////////////////////////////////////////////////////////////
-
-
-ABC_NAMESPACE_IMPL_END
-
diff --git a/src/aig/llb/llbInt.h b/src/aig/llb/llbInt.h
index dc448954..80f391fe 100644
--- a/src/aig/llb/llbInt.h
+++ b/src/aig/llb/llbInt.h
@@ -37,11 +37,8 @@
/// PARAMETERS ///
////////////////////////////////////////////////////////////////////////
-
-
ABC_NAMESPACE_HEADER_START
-
////////////////////////////////////////////////////////////////////////
/// BASIC TYPES ///
////////////////////////////////////////////////////////////////////////
@@ -109,8 +106,6 @@ struct Llb_Grp_t_
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
-/*=== llbCex.c =======================================================*/
-extern Abc_Cex_t * Llb_ManDeriveCex( Llb_Man_t * p, DdNode * bInter, int iOutFail, int iIter );
/*=== llbConstr.c ======================================================*/
extern Vec_Int_t * Llb_ManDeriveConstraints( Aig_Man_t * p );
extern void Llb_ManPrintEntries( Aig_Man_t * p, Vec_Int_t * vCands );
@@ -118,8 +113,10 @@ extern void Llb_ManPrintEntries( Aig_Man_t * p, Vec_Int_t * vCands );
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 Llb_Man_t * Llb_ManStartFlow( Aig_Man_t * pAigGlo, Aig_Man_t * pAig, Gia_ParLlb_t * pPars );
+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 );
@@ -148,7 +145,30 @@ extern int Llb_ManReachability( Llb_Man_t * p, Vec_Int_t * vHints, D
/*=== llbSched.c =====================================================*/
extern void Llb_MtrSchedule( Llb_Mtr_t * p );
-
+/*=== llb2Bad.c ======================================================*/
+extern DdNode * Llb_BddComputeBad( Aig_Man_t * pInit, DdManager * dd );
+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 );
+/*=== 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 );
+/*=== 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 );
+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,
+ int TimeTarget, int fBackward, int fReorder, int fVerbose );
+
+/*=== 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, int Limit );
ABC_NAMESPACE_HEADER_END
diff --git a/src/aig/llb/module.make b/src/aig/llb/module.make
index 60b6ce07..56beca25 100644
--- a/src/aig/llb/module.make
+++ b/src/aig/llb/module.make
@@ -1,11 +1,19 @@
-SRC += src/aig/llb/llbCex.c \
- src/aig/llb/llbCluster.c \
- src/aig/llb/llbConstr.c \
- src/aig/llb/llbCore.c \
- src/aig/llb/llbHint.c \
- src/aig/llb/llbMan.c \
- src/aig/llb/llbMatrix.c \
- src/aig/llb/llbPart.c \
- src/aig/llb/llbPivot.c \
- src/aig/llb/llbReach.c \
- src/aig/llb/llbSched.c
+SRC += src/aig/llb/llb.c \
+ src/aig/llb/llb1Cluster.c \
+ src/aig/llb/llb1Constr.c \
+ src/aig/llb/llb1Core.c \
+ src/aig/llb/llb1Group.c \
+ src/aig/llb/llb1Hint.c \
+ src/aig/llb/llb1Man.c \
+ src/aig/llb/llb1Matrix.c \
+ src/aig/llb/llb1Pivot.c \
+ src/aig/llb/llb1Reach.c \
+ src/aig/llb/llb1Sched.c \
+ src/aig/llb/llb2Bad.c \
+ src/aig/llb/llb2Core.c \
+ src/aig/llb/llb2Driver.c \
+ src/aig/llb/llb2Dump.c \
+ src/aig/llb/llb2Flow.c \
+ src/aig/llb/llb2Image.c \
+ src/aig/llb/llb3Image.c \
+ src/aig/llb/llb3Nonlin.c
diff --git a/src/aig/nwk/nwkAig.c b/src/aig/nwk/nwkAig.c
index 54e84237..b38fbdfa 100644
--- a/src/aig/nwk/nwkAig.c
+++ b/src/aig/nwk/nwkAig.c
@@ -83,7 +83,7 @@ Nwk_Man_t * Nwk_ManDeriveFromAig( Aig_Man_t * p )
***********************************************************************/
Vec_Ptr_t * Nwk_ManDeriveRetimingCut( Aig_Man_t * p, int fForward, int fVerbose )
-{
+{
Vec_Ptr_t * vNodes;
Nwk_Man_t * pNtk;
Nwk_Obj_t * pNode;
@@ -99,7 +99,7 @@ Vec_Ptr_t * Nwk_ManDeriveRetimingCut( Aig_Man_t * p, int fForward, int fVerbose
Vec_PtrForEachEntry( Nwk_Obj_t *, vNodes, pNode, i )
Vec_PtrWriteEntry( vNodes, i, pNode->pCopy );
Nwk_ManFree( pNtk );
- assert( Vec_PtrSize(vNodes) <= Aig_ManRegNum(p) );
+// assert( Vec_PtrSize(vNodes) <= Aig_ManRegNum(p) );
return vNodes;
}
diff --git a/src/aig/saig/saigAbs.c b/src/aig/saig/saigAbs.c
index 194add25..938a66e2 100644
--- a/src/aig/saig/saigAbs.c
+++ b/src/aig/saig/saigAbs.c
@@ -22,6 +22,7 @@
#include "ssw.h"
#include "fra.h"
#include "bbr.h"
+#include "pdr.h"
ABC_NAMESPACE_IMPL_START
@@ -173,15 +174,32 @@ Aig_Man_t * Saig_ManCexRefine( Aig_Man_t * p, Aig_Man_t * pAbs, Vec_Int_t * vFlo
{
extern int Saig_BmcPerform( Aig_Man_t * pAig, int nStart, int nFramesMax, int nNodesMax, int nTimeOut, int nConfMaxOne, int nConfMaxAll, int fVerbose, int fVerbOverwrite, int * piFrames );
Vec_Int_t * vFlopsNew;
- int i, Entry;
+ int i, Entry, RetValue;
*piRetValue = -1;
if ( fUseDprove && Aig_ManRegNum(pAbs) > 0 )
{
+/*
Fra_Sec_t SecPar, * pSecPar = &SecPar;
- int RetValue;
Fra_SecSetDefaultParams( pSecPar );
pSecPar->fVerbose = fVerbose;
RetValue = Fra_FraigSec( pAbs, pSecPar, NULL );
+*/
+ Abc_Cex_t * pCex = NULL;
+ Aig_Man_t * pAbsOrpos = Saig_ManDupOrpos( pAbs );
+ Pdr_Par_t Pars, * pPars = &Pars;
+ Pdr_ManSetDefaultParams( pPars );
+ pPars->nTimeOut = 10;
+ pPars->fVerbose = fVerbose;
+ if ( pPars->fVerbose )
+ printf( "Running property directed reachability...\n" );
+ RetValue = Pdr_ManSolve( pAbsOrpos, pPars, &pCex );
+ if ( pCex )
+ pCex->iPo = Ssw_SmlFindOutputCounterExample( pAbs, pCex );
+ Aig_ManStop( pAbsOrpos );
+ pAbs->pSeqModel = pCex;
+ if ( RetValue )
+ *piRetValue = 1;
+
}
else if ( fUseBdds && (Aig_ManRegNum(pAbs) > 0 && Aig_ManRegNum(pAbs) <= 80) )
{
@@ -195,7 +213,9 @@ Aig_Man_t * Saig_ManCexRefine( Aig_Man_t * p, Aig_Man_t * pAbs, Vec_Int_t * vFlo
pPars->fReorderImage = 1;
pPars->fVerbose = fVerbose;
pPars->fSilent = 0;
- Aig_ManVerifyUsingBdds( pAbs, pPars );
+ RetValue = Aig_ManVerifyUsingBdds( pAbs, pPars );
+ if ( RetValue )
+ *piRetValue = 1;
}
else
{
diff --git a/src/aig/saig/saigPhase.c b/src/aig/saig/saigPhase.c
index 4a23ecf3..fad77020 100644
--- a/src/aig/saig/saigPhase.c
+++ b/src/aig/saig/saigPhase.c
@@ -222,7 +222,7 @@ int Saig_TsiStateHash( unsigned * pState, int nWords, int nTableSize )
SeeAlso []
***********************************************************************/
-int Saig_TsiCountNonXValuedRegisters( Saig_Tsim_t * p, int nWords, int nPref )
+int Saig_TsiCountNonXValuedRegisters( Saig_Tsim_t * p, int nPref )
{
unsigned * pState;
int nRegs = p->pAig->nRegs;
@@ -242,6 +242,53 @@ int Saig_TsiCountNonXValuedRegisters( Saig_Tsim_t * p, int nWords, int nPref )
Vec_IntPush( p->vNonXRegs, i );
}
return Vec_IntSize(p->vNonXRegs);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes flops that are stuck-at constant.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Saig_TsiComputeTransient( Saig_Tsim_t * p, int nPref )
+{
+ Vec_Int_t * vCounters;
+ unsigned * pState;
+ int ValueThis, ValuePrev = -1, StepPrev = -1;
+ int i, k, nRegs = p->pAig->nRegs;
+ vCounters = Vec_IntStart( nPref );
+ for ( i = 0; i < nRegs; i++ )
+ {
+ Vec_PtrForEachEntry( unsigned *, p->vStates, pState, k )
+ {
+ ValueThis = (Aig_InfoHasBit( pState, 2 * i + 1 ) << 1) | Aig_InfoHasBit( pState, 2 * i );
+//printf( "%s", (ValueThis == 1)? "0" : ((ValueThis == 2)? "1" : "x") );
+ assert( ValueThis != 0 );
+ if ( ValuePrev != ValueThis )
+ {
+ ValuePrev = ValueThis;
+ StepPrev = k;
+ }
+ }
+//printf( "\n" );
+ if ( ValueThis == SAIG_XVSX )
+ continue;
+ if ( StepPrev >= nPref )
+ continue;
+ Vec_IntAddToEntry( vCounters, StepPrev, 1 );
+ }
+ Vec_IntForEachEntry( vCounters, ValueThis, i )
+ {
+ if ( ValueThis == 0 )
+ continue;
+// printf( "%3d : %3d\n", i, ValueThis );
+ }
+ return vCounters;
}
/**Function*************************************************************
@@ -821,7 +868,7 @@ int Saig_ManPhaseFrameNum( Aig_Man_t * p, Vec_Int_t * vInits )
SeeAlso []
***********************************************************************/
-int Saig_ManPhasePrefixLength( Aig_Man_t * p, int fVerbose, int fVeryVerbose )
+int Saig_ManPhasePrefixLength( Aig_Man_t * p, int fVerbose, int fVeryVerbose, Vec_Int_t ** pvTrans )
{
Saig_Tsim_t * pTsi;
int nFrames, nPrefix, nNonXRegs;
@@ -835,7 +882,11 @@ int Saig_ManPhasePrefixLength( Aig_Man_t * p, int fVerbose, int fVeryVerbose )
// derive information
nPrefix = Saig_TsiComputePrefix( pTsi, (unsigned *)Vec_PtrEntryLast(pTsi->vStates), pTsi->nWords );
nFrames = Vec_PtrSize(pTsi->vStates) - 1 - nPrefix;
- nNonXRegs = Saig_TsiCountNonXValuedRegisters( pTsi, pTsi->nWords, nPrefix );
+ nNonXRegs = Saig_TsiCountNonXValuedRegisters( pTsi, nPrefix );
+
+ if ( pvTrans )
+ *pvTrans = Saig_TsiComputeTransient( pTsi, nPrefix );
+
// print statistics
if ( fVerbose )
printf( "Lead = %5d. Loop = %5d. Total flops = %5d. Binary flops = %5d.\n", nPrefix, nFrames, p->nRegs, nNonXRegs );
@@ -871,7 +922,7 @@ Aig_Man_t * Saig_ManPhaseAbstract( Aig_Man_t * p, Vec_Int_t * vInits, int nFrame
// derive information
pTsi->nPrefix = Saig_TsiComputePrefix( pTsi, (unsigned *)Vec_PtrEntryLast(pTsi->vStates), pTsi->nWords );
pTsi->nCycle = Vec_PtrSize(pTsi->vStates) - 1 - pTsi->nPrefix;
- pTsi->nNonXRegs = Saig_TsiCountNonXValuedRegisters(pTsi, pTsi->nWords, ABC_MIN(pTsi->nPrefix,nPref));
+ pTsi->nNonXRegs = Saig_TsiCountNonXValuedRegisters(pTsi, ABC_MIN(pTsi->nPrefix,nPref));
// print statistics
if ( fVerbose )
{
@@ -927,7 +978,7 @@ Aig_Man_t * Saig_ManPhaseAbstractAuto( Aig_Man_t * p, int fVerbose )
// derive information
pTsi->nPrefix = Saig_TsiComputePrefix( pTsi, (unsigned *)Vec_PtrEntryLast(pTsi->vStates), pTsi->nWords );
pTsi->nCycle = Vec_PtrSize(pTsi->vStates) - 1 - pTsi->nPrefix;
- pTsi->nNonXRegs = Saig_TsiCountNonXValuedRegisters(pTsi, pTsi->nWords, 0);
+ pTsi->nNonXRegs = Saig_TsiCountNonXValuedRegisters(pTsi, 0);
// print statistics
if ( fVerbose )
{
diff --git a/src/aig/saig/saigTempor.c b/src/aig/saig/saigTempor.c
index 80bde75c..74f4a9d3 100644
--- a/src/aig/saig/saigTempor.c
+++ b/src/aig/saig/saigTempor.c
@@ -147,6 +147,32 @@ Aig_Man_t * Saig_ManTemporDecompose( Aig_Man_t * pAig, int nFrames )
/**Function*************************************************************
+ Synopsis [Find index of first non-zero entry.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Vec_IntLastNonZeroBeforeLimit( Vec_Int_t * vTemp, int Limit )
+{
+ int Entry, i;
+ if ( vTemp == NULL )
+ return -1;
+ Vec_IntForEachEntryReverse( vTemp, Entry, i )
+ {
+ if ( i >= Limit )
+ continue;
+ if ( Entry )
+ return i;
+ }
+ return -1;
+}
+
+/**Function*************************************************************
+
Synopsis []
Description []
@@ -156,19 +182,33 @@ Aig_Man_t * Saig_ManTemporDecompose( Aig_Man_t * pAig, int nFrames )
SeeAlso []
***********************************************************************/
-Aig_Man_t * Saig_ManTempor( Aig_Man_t * pAig, int nFrames, int TimeOut, int nConfLimit, int fUseBmc, int fVerbose, int fVeryVerbose )
+Aig_Man_t * Saig_ManTempor( Aig_Man_t * pAig, int nFrames, int TimeOut, int nConfLimit, int fUseBmc, int fUseTransSigs, int fVerbose, int fVeryVerbose )
{
- extern int Saig_ManPhasePrefixLength( Aig_Man_t * p, int fVerbose, int fVeryVerbose );
+ extern int Saig_ManPhasePrefixLength( Aig_Man_t * p, int fVerbose, int fVeryVerbose, Vec_Int_t ** pvTrans );
+
+ Vec_Int_t * vTransSigs = NULL;
int RetValue, nFramesFinished = -1;
assert( nFrames >= 0 );
if ( nFrames == 0 )
{
- nFrames = Saig_ManPhasePrefixLength( pAig, fVerbose, fVeryVerbose );
+ nFrames = Saig_ManPhasePrefixLength( pAig, fVerbose, fVeryVerbose, &vTransSigs );
if ( nFrames == 1 )
{
+ Vec_IntFreeP( &vTransSigs );
printf( "The leading sequence has length 1. Temporal decomposition is not performed.\n" );
return NULL;
}
+ if ( fUseTransSigs )
+ {
+ int Entry, i, iLast = -1;
+ Vec_IntForEachEntry( vTransSigs, Entry, i )
+ iLast = Entry ? i :iLast;
+ if ( iLast > 0 && iLast < nFrames )
+ {
+ Abc_Print( 1, "Reducing frame count from %d to %d to fit the last transient.\n", nFrames, iLast );
+ nFrames = iLast;
+ }
+ }
Abc_Print( 1, "Using computed frame number (%d).\n", nFrames );
}
else
@@ -176,18 +216,27 @@ Aig_Man_t * Saig_ManTempor( Aig_Man_t * pAig, int nFrames, int TimeOut, int nCon
// run BMC2
if ( fUseBmc )
{
- RetValue = Saig_BmcPerform( pAig, 0, nFrames, 5000, TimeOut, nConfLimit, 0, fVerbose, 0, &nFramesFinished );
+ RetValue = Saig_BmcPerform( pAig, 0, nFrames, 2000, TimeOut, nConfLimit, 0, fVerbose, 0, &nFramesFinished );
if ( RetValue == 0 )
{
+ Vec_IntFreeP( &vTransSigs );
printf( "A cex found in the first %d frames.\n", nFrames );
return NULL;
}
if ( nFramesFinished < nFrames )
{
- printf( "BMC for %d frames could not be completed. A cex may exist!\n", nFrames );
- return NULL;
+ int iLastBefore = Vec_IntLastNonZeroBeforeLimit( vTransSigs, nFramesFinished );
+ if ( iLastBefore < 1 || !fUseTransSigs )
+ {
+ Vec_IntFreeP( &vTransSigs );
+ printf( "BMC for %d frames could not be completed. A cex may exist!\n", nFrames );
+ return NULL;
+ }
+ assert( iLastBefore < nFramesFinished );
+ printf( "BMC succeeded to frame %d. Adjusting frame count to be (%d) based on the last transient signal.\n", nFramesFinished, iLastBefore );
}
}
+ Vec_IntFreeP( &vTransSigs );
return Saig_ManTemporDecompose( pAig, nFrames );
}
diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c
index 2973eb6e..804bd058 100644
--- a/src/base/abci/abc.c
+++ b/src/base/abci/abc.c
@@ -370,6 +370,8 @@ static int Abc_CommandAbc9PbaStart ( Abc_Frame_t * pAbc, int argc, cha
static int Abc_CommandAbc9Reparam ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandAbc9Posplit ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandAbc9Reach ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Reach2 ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandAbc9Reach3 ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandAbc9Undo ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandAbc9Test ( Abc_Frame_t * pAbc, int argc, char ** argv );
@@ -766,6 +768,8 @@ void Abc_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "ABC9", "&reparam", Abc_CommandAbc9Reparam, 0 );
Cmd_CommandAdd( pAbc, "ABC9", "&posplit", Abc_CommandAbc9Posplit, 0 );
Cmd_CommandAdd( pAbc, "ABC9", "&reach", Abc_CommandAbc9Reach, 0 );
+ Cmd_CommandAdd( pAbc, "ABC9", "&reach2", Abc_CommandAbc9Reach2, 0 );
+ Cmd_CommandAdd( pAbc, "ABC9", "&reach3", Abc_CommandAbc9Reach3, 0 );
Cmd_CommandAdd( pAbc, "ABC9", "&undo", Abc_CommandAbc9Undo, 0 );
Cmd_CommandAdd( pAbc, "ABC9", "&test", Abc_CommandAbc9Test, 0 );
@@ -8414,9 +8418,8 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
// extern Abc_Ntk_t * Abc_NtkTestExor( Abc_Ntk_t * pNtk, int fVerbose );
// extern Abc_Ntk_t * Abc_NtkNtkTest( Abc_Ntk_t * pNtk, If_Lib_t * pLutLib );
extern Abc_Ntk_t * Abc_NtkDarRetimeStep( Abc_Ntk_t * pNtk, int fVerbose );
- extern void Abc_NtkDarTest( Abc_Ntk_t * pNtk );
+ extern void Abc_NtkDarTest( Abc_Ntk_t * pNtk, int Num );
// extern void Aig_ProcedureTest();
- extern void Abc_NtkDarTest( Abc_Ntk_t * pNtk );
extern Abc_Ntk_t * Abc_NtkDarTestNtk( Abc_Ntk_t * pNtk );
extern void Amap_LibertyTest( char * pFileName );
extern void Bbl_ManTest( Abc_Ntk_t * pNtk );
@@ -8435,7 +8438,7 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
fVerbose = 1;
fBmc = 0;
nFrames = 1;
- nLevels = 200;
+ nLevels = 10;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "FNbvwh" ) ) != EOF )
{
@@ -8489,11 +8492,8 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Print( -1, "Only works for sequential networks.\n" );
return 1;
}
- {
- extern void Abc_NtkDarTest( Abc_Ntk_t * pNtk );
- Abc_NtkDarTest( pNtk );
- }
+ Abc_NtkDarTest( pNtk, nLevels );
// Abc_NtkTestEsop( pNtk );
// Abc_NtkTestSop( pNtk );
@@ -18975,17 +18975,18 @@ usage:
***********************************************************************/
int Abc_CommandTempor( Abc_Frame_t * pAbc, int argc, char ** argv )
{
- extern Abc_Ntk_t * Abc_NtkDarTempor( Abc_Ntk_t * pNtk, int nFrames, int TimeOut, int nConfLimit, int fUseBmc, int fVerbose, int fVeryVerbose );
+ extern Abc_Ntk_t * Abc_NtkDarTempor( Abc_Ntk_t * pNtk, int nFrames, int TimeOut, int nConfLimit, int fUseBmc, int fUseTransSigs, int fVerbose, int fVeryVerbose );
Abc_Ntk_t * pNtkRes, * pNtk = Abc_FrameReadNtk(pAbc);
- int nFrames = 0;
- int TimeOut = 300;
- int nConfMax = 100000;
- int fUseBmc = 1;
- int fVerbose = 0;
- int fVeryVerbose = 0;
+ int nFrames = 0;
+ int TimeOut = 300;
+ int nConfMax = 100000;
+ int fUseBmc = 1;
+ int fUseTransSigs = 0;
+ int fVerbose = 0;
+ int fVeryVerbose = 0;
int c;
Extra_UtilGetoptReset();
- while ( ( c = Extra_UtilGetopt( argc, argv, "FTCbvwh" ) ) != EOF )
+ while ( ( c = Extra_UtilGetopt( argc, argv, "FTCbsvwh" ) ) != EOF )
{
switch ( c )
{
@@ -19025,6 +19026,9 @@ int Abc_CommandTempor( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'b':
fUseBmc ^= 1;
break;
+ case 's':
+ fUseTransSigs ^= 1;
+ break;
case 'v':
fVerbose ^= 1;
break;
@@ -19052,7 +19056,7 @@ int Abc_CommandTempor( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
}
// modify the current network
- pNtkRes = Abc_NtkDarTempor( pNtk, nFrames, TimeOut, nConfMax, fUseBmc, fVerbose, fVeryVerbose );
+ pNtkRes = Abc_NtkDarTempor( pNtk, nFrames, TimeOut, nConfMax, fUseBmc, fUseTransSigs, fVerbose, fVeryVerbose );
if ( pNtkRes == NULL )
{
Abc_Print( -1, "Temporal decomposition has failed.\n" );
@@ -19063,12 +19067,13 @@ int Abc_CommandTempor( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
- Abc_Print( -2, "usage: tempor [-FTC <num>] [-bvwh]\n" );
+ Abc_Print( -2, "usage: tempor [-FTC <num>] [-bsvwh]\n" );
Abc_Print( -2, "\t performs temporal decomposition\n" );
Abc_Print( -2, "\t-F <num> : init logic timeframe count (0 = use leading length) [default = %d]\n", nFrames );
Abc_Print( -2, "\t-T <num> : runtime limit in seconds for BMC (0=unused) [default = %d]\n", TimeOut );
Abc_Print( -2, "\t-C <num> : max number of SAT conflicts in BMC (0=unused) [default = %d]\n", nConfMax );
Abc_Print( -2, "\t-b : toggle running BMC2 on the init frames [default = %s]\n", fUseBmc? "yes": "no" );
+ Abc_Print( -2, "\t-s : toggle using transient signals [default = %s]\n", fUseTransSigs? "yes": "no" );
Abc_Print( -2, "\t-v : toggle printing verbose output [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-w : toggle printing ternary state space [default = %s]\n", fVeryVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
@@ -19311,7 +19316,8 @@ usage:
Abc_Print( -2, "\t-R num : the %% of abstracted flops when refinement stops (0<=num<=100) [default = %d]\n", pPars->nRatio );
Abc_Print( -2, "\t-c : toggle dynamic addition of constraints [default = %s]\n", pPars->fConstr? "yes": "no" );
Abc_Print( -2, "\t-r : toggle using BDD-based reachability for filtering [default = %s]\n", pPars->fUseBdds? "yes": "no" );
- Abc_Print( -2, "\t-p : toggle using \"dprove\" for filtering [default = %s]\n", pPars->fUseDprove? "yes": "no" );
+// Abc_Print( -2, "\t-p : toggle using \"dprove\" for filtering [default = %s]\n", pPars->fUseDprove? "yes": "no" );
+ Abc_Print( -2, "\t-p : toggle using \"pdr\" for filtering [default = %s]\n", pPars->fUseDprove? "yes": "no" );
Abc_Print( -2, "\t-f : toggle starting BMC from a later frame [default = %s]\n", pPars->fUseStart? "yes": "no" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
@@ -26943,7 +26949,8 @@ usage:
Abc_Print( -2, "\t-C num : the max number of conflicts by SAT solver for BMC [default = %d]\n", pPars->nConfMaxBmc );
Abc_Print( -2, "\t-R num : the %% of abstracted flops when refinement stops (0<=num<=100) [default = %d]\n", pPars->nRatio );
Abc_Print( -2, "\t-r : toggle using BDD-based reachability for filtering [default = %s]\n", pPars->fUseBdds? "yes": "no" );
- Abc_Print( -2, "\t-p : toggle using \"dprove\" for filtering [default = %s]\n", pPars->fUseDprove? "yes": "no" );
+// Abc_Print( -2, "\t-p : toggle using \"dprove\" for filtering [default = %s]\n", pPars->fUseDprove? "yes": "no" );
+ Abc_Print( -2, "\t-p : toggle using \"pdr\" for filtering [default = %s]\n", pPars->fUseDprove? "yes": "no" );
Abc_Print( -2, "\t-f : toggle starting BMC from a later frame [default = %s]\n", pPars->fUseStart? "yes": "no" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
@@ -27592,7 +27599,7 @@ int Abc_CommandAbc9Reach( Abc_Frame_t * pAbc, int argc, char ** argv )
usage:
Abc_Print( -2, "usage: &reach [-TBFCHS num] [-L file] [-ripcsyzvwh]\n" );
- Abc_Print( -2, "\t verifies sequential miter using BDD-based reachability\n" );
+ Abc_Print( -2, "\t model checking via BDD-based reachability (similar to IWLS'95)\n" );
Abc_Print( -2, "\t-T num : approximate time limit in seconds (0=infinite) [default = %d]\n", pPars->TimeLimit );
Abc_Print( -2, "\t-B num : max number of nodes in the intermediate BDDs [default = %d]\n", pPars->nBddMax );
Abc_Print( -2, "\t-F num : max number of reachability iterations [default = %d]\n", pPars->nIterMax );
@@ -27624,6 +27631,276 @@ usage:
SeeAlso []
***********************************************************************/
+int Abc_CommandAbc9Reach2( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ Gia_ParLlb_t Pars, * pPars = &Pars;
+ Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+ Aig_Man_t * pMan;
+ char * pLogFileName = NULL;
+ int c;
+ extern int Llb_ManReachMinCut( Aig_Man_t * pAig, Gia_ParLlb_t * pPars );
+
+ // set defaults
+ Llb_ManSetDefaultParams( pPars );
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "NBFTLrbyzdvwh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'N':
+ if ( globalUtilOptind >= argc )
+ {
+ Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nPartValue = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nPartValue < 0 )
+ goto usage;
+ break;
+ case 'B':
+ if ( globalUtilOptind >= argc )
+ {
+ Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nBddMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nBddMax < 0 )
+ goto usage;
+ break;
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nIterMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nIterMax < 0 )
+ goto usage;
+ break;
+ case 'T':
+ if ( globalUtilOptind >= argc )
+ {
+ Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->TimeLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->TimeLimit < 0 )
+ goto usage;
+ break;
+ case 'L':
+ if ( globalUtilOptind >= argc )
+ {
+ Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" );
+ goto usage;
+ }
+ pLogFileName = argv[globalUtilOptind];
+ globalUtilOptind++;
+ break;
+ case 'r':
+ pPars->fReorder ^= 1;
+ break;
+ case 'b':
+ pPars->fBackward ^= 1;
+ break;
+ case 'y':
+ pPars->fSkipOutCheck ^= 1;
+ break;
+ case 'z':
+ pPars->fSkipReach ^= 1;
+ break;
+ case 'd':
+ pPars->fDumpReached ^= 1;
+ break;
+ case 'v':
+ pPars->fVerbose ^= 1;
+ break;
+ case 'w':
+ pPars->fVeryVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pAbc->pGia == NULL )
+ {
+ Abc_Print( -1, "Abc_CommandAbc9Reach(): There is no AIG.\n" );
+ return 1;
+ }
+ if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+ {
+ Abc_Print( -1, "Abc_CommandAbc9Reach(): The current AIG has no latches.\n" );
+ return 0;
+ }
+ pMan = Gia_ManToAigSimple( pAbc->pGia );
+ pAbc->Status = Llb_ManReachMinCut( pMan, pPars );
+ pAbc->nFrames = pPars->iFrame;
+ Abc_FrameReplaceCex( pAbc, &pMan->pSeqModel );
+ if ( pLogFileName )
+ Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, "&reach2" );
+ Aig_ManStop( pMan );
+ return 0;
+
+usage:
+ Abc_Print( -2, "usage: &reach2 [-NFT num] [-L file] [-rbyzdvwh]\n" );
+ Abc_Print( -2, "\t model checking via BDD-based reachability (min-cut-based)\n" );
+ Abc_Print( -2, "\t-N num : partitioning value (MinVol=nANDs/N/2; MaxVol=nANDs/N) [default = %d]\n", pPars->nPartValue );
+// Abc_Print( -2, "\t-B num : the BDD node increase when hints kick in [default = %d]\n", pPars->nBddMax );
+ Abc_Print( -2, "\t-F num : max number of reachability iterations [default = %d]\n", pPars->nIterMax );
+ Abc_Print( -2, "\t-T num : approximate time limit in seconds (0=infinite) [default = %d]\n", pPars->TimeLimit );
+ Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" );
+ Abc_Print( -2, "\t-r : enable dynamic BDD variable reordering [default = %s]\n", pPars->fReorder? "yes": "no" );
+ Abc_Print( -2, "\t-b : perform backward reachability analysis [default = %s]\n", pPars->fBackward? "yes": "no" );
+ Abc_Print( -2, "\t-y : skip checking property outputs [default = %s]\n", pPars->fSkipOutCheck? "yes": "no" );
+ Abc_Print( -2, "\t-z : skip reachability (run preparation phase only) [default = %s]\n", pPars->fSkipReach? "yes": "no" );
+ Abc_Print( -2, "\t-d : dump BDD of reached states into file \"reached.blif\" [default = %s]\n", pPars->fDumpReached? "yes": "no" );
+ Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
+ Abc_Print( -2, "\t-w : prints additional information [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+ Abc_Print( -2, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Abc_CommandAbc9Reach3( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ Gia_ParLlb_t Pars, * pPars = &Pars;
+ Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);
+ Aig_Man_t * pMan;
+ char * pLogFileName = NULL;
+ int c;
+ extern int Llb_NonlinCoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars );
+
+ // set defaults
+ Llb_ManSetDefaultParams( pPars );
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "BFTLryzvwh" ) ) != EOF )
+ {
+ switch ( c )
+ {
+ case 'B':
+ if ( globalUtilOptind >= argc )
+ {
+ Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nBddMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nBddMax < 0 )
+ goto usage;
+ break;
+ case 'F':
+ if ( globalUtilOptind >= argc )
+ {
+ Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->nIterMax = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->nIterMax < 0 )
+ goto usage;
+ break;
+ case 'T':
+ if ( globalUtilOptind >= argc )
+ {
+ Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" );
+ goto usage;
+ }
+ pPars->TimeLimit = atoi(argv[globalUtilOptind]);
+ globalUtilOptind++;
+ if ( pPars->TimeLimit < 0 )
+ goto usage;
+ break;
+ case 'L':
+ if ( globalUtilOptind >= argc )
+ {
+ Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" );
+ goto usage;
+ }
+ pLogFileName = argv[globalUtilOptind];
+ globalUtilOptind++;
+ break;
+ case 'r':
+ pPars->fReorder ^= 1;
+ break;
+ case 'y':
+ pPars->fSkipOutCheck ^= 1;
+ break;
+ case 'z':
+ pPars->fSkipReach ^= 1;
+ break;
+ case 'v':
+ pPars->fVerbose ^= 1;
+ break;
+ case 'w':
+ pPars->fVeryVerbose ^= 1;
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ if ( pAbc->pGia == NULL )
+ {
+ Abc_Print( -1, "Abc_CommandAbc9Reach(): There is no AIG.\n" );
+ return 1;
+ }
+ if ( Gia_ManRegNum(pAbc->pGia) == 0 )
+ {
+ Abc_Print( -1, "Abc_CommandAbc9Reach(): The current AIG has no latches.\n" );
+ return 0;
+ }
+ pMan = Gia_ManToAigSimple( pAbc->pGia );
+ pAbc->Status = Llb_NonlinCoreReach( pMan, pPars );
+ pAbc->nFrames = pPars->iFrame;
+ Abc_FrameReplaceCex( pAbc, &pMan->pSeqModel );
+ if ( pLogFileName )
+ Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, "&reach2" );
+ Aig_ManStop( pMan );
+ return 0;
+
+usage:
+ Abc_Print( -2, "usage: &reach3 [-BFT num] [-L file] [-ryzvh]\n" );
+ Abc_Print( -2, "\t model checking via BDD-based reachability (non-linear QS)\n" );
+ Abc_Print( -2, "\t-B num : the BDD node increase when hints kick in [default = %d]\n", pPars->nBddMax );
+ Abc_Print( -2, "\t-F num : max number of reachability iterations [default = %d]\n", pPars->nIterMax );
+ Abc_Print( -2, "\t-T num : approximate time limit in seconds (0=infinite) [default = %d]\n", pPars->TimeLimit );
+ Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" );
+ Abc_Print( -2, "\t-r : enable dynamic BDD variable reordering [default = %s]\n", pPars->fReorder? "yes": "no" );
+ Abc_Print( -2, "\t-y : skip checking property outputs [default = %s]\n", pPars->fSkipOutCheck? "yes": "no" );
+ Abc_Print( -2, "\t-z : skip reachability (run preparation phase only) [default = %s]\n", pPars->fSkipReach? "yes": "no" );
+ Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
+// Abc_Print( -2, "\t-w : prints additional information [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
+ Abc_Print( -2, "\t-h : print the command usage\n");
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
int Abc_CommandAbc9Undo( Abc_Frame_t * pAbc, int argc, char ** argv )
{
int c;
diff --git a/src/base/abci/abcDar.c b/src/base/abci/abcDar.c
index 85880882..a6fa9ce6 100644
--- a/src/base/abci/abcDar.c
+++ b/src/base/abci/abcDar.c
@@ -2940,15 +2940,15 @@ Abc_Ntk_t * Abc_NtkDarEnlarge( Abc_Ntk_t * pNtk, int nFrames, int fVerbose )
SeeAlso []
***********************************************************************/
-Abc_Ntk_t * Abc_NtkDarTempor( Abc_Ntk_t * pNtk, int nFrames, int TimeOut, int nConfLimit, int fUseBmc, int fVerbose, int fVeryVerbose )
+Abc_Ntk_t * Abc_NtkDarTempor( Abc_Ntk_t * pNtk, int nFrames, int TimeOut, int nConfLimit, int fUseBmc, int fUseTransSigs, int fVerbose, int fVeryVerbose )
{
- extern Aig_Man_t * Saig_ManTempor( Aig_Man_t * pAig, int nFrames, int TimeOut, int nConfLimit, int fUseBmc, int fVerbose, int fVeryVerbose );
+ extern Aig_Man_t * Saig_ManTempor( Aig_Man_t * pAig, int nFrames, int TimeOut, int nConfLimit, int fUseBmc, int fUseTransSigs, int fVerbose, int fVeryVerbose );
Abc_Ntk_t * pNtkAig;
Aig_Man_t * pMan, * pTemp;
pMan = Abc_NtkToDar( pNtk, 0, 1 );
if ( pMan == NULL )
return NULL;
- pTemp = Saig_ManTempor( pMan, nFrames, TimeOut, nConfLimit, fUseBmc, fVerbose, fVeryVerbose );
+ pTemp = Saig_ManTempor( pMan, nFrames, TimeOut, nConfLimit, fUseBmc, fUseTransSigs, fVerbose, fVeryVerbose );
Aig_ManStop( pMan );
if ( pTemp == NULL )
return Abc_NtkDup( pNtk );
@@ -3937,11 +3937,13 @@ void Abc_NtkDarConstrProfile( Abc_Ntk_t * pNtk, int fVerbose )
SeeAlso []
***********************************************************************/
-void Abc_NtkDarTest( Abc_Ntk_t * pNtk )
+void Abc_NtkDarTest( Abc_Ntk_t * pNtk, int Num )
{
// extern void Saig_ManDetectConstr( Aig_Man_t * p );
// extern void Saig_ManDetectConstrFuncTest( Aig_Man_t * p );
- extern void Saig_ManFoldConstrTest( Aig_Man_t * pAig );
+// extern void Saig_ManFoldConstrTest( Aig_Man_t * pAig );
+ extern void Llb_ManComputeDomsTest( Aig_Man_t * pAig, int Num );
+
// extern void Fsim_ManTest( Aig_Man_t * pAig );
@@ -3992,6 +3994,15 @@ Aig_ManPrintStats( pMan );
// Pdr_ManEquivClasses( pMan );
}
+// Llb_ManComputeDomsTest( pMan, Num );
+ {
+ extern void Llb_ManMinCutTest( Aig_Man_t * pMan, int Num );
+ extern void Llb_BddStructAnalysis( Aig_Man_t * pMan );
+ extern void Llb_NonlinExperiment( Aig_Man_t * pAig, int Num );
+// Llb_BddStructAnalysis( pMan );
+ Llb_ManMinCutTest( pMan, Num );
+// Llb_NonlinExperiment( pMan, Num );
+ }
// Saig_MvManSimulate( pMan, 1 );
// Saig_ManDetectConstr( pMan );
diff --git a/src/bdd/cudd/cudd.h b/src/bdd/cudd/cudd.h
index 14f67abf..658e4eaf 100644
--- a/src/bdd/cudd/cudd.h
+++ b/src/bdd/cudd/cudd.h
@@ -720,6 +720,7 @@ EXTERN DdNode * Cudd_addRoundOff ARGS((DdManager *dd, DdNode *f, int N));
EXTERN DdNode * Cudd_addWalsh ARGS((DdManager *dd, DdNode **x, DdNode **y, int n));
EXTERN DdNode * Cudd_addResidue ARGS((DdManager *dd, int n, int m, int options, int top));
EXTERN DdNode * Cudd_bddAndAbstract ARGS((DdManager *manager, DdNode *f, DdNode *g, DdNode *cube));
+EXTERN DdNode * Cudd_bddAndAbstractLimit ARGS((DdManager *manager, DdNode *f, DdNode *g, DdNode *cube, unsigned int limit));
EXTERN int Cudd_ApaNumberOfDigits ARGS((int binaryDigits));
EXTERN DdApaNumber Cudd_NewApaNumber ARGS((int digits));
EXTERN void Cudd_ApaCopy ARGS((int digits, DdApaNumber source, DdApaNumber dest));
diff --git a/src/bdd/cudd/cuddAndAbs.c b/src/bdd/cudd/cuddAndAbs.c
index 9ee70498..cd928e80 100644
--- a/src/bdd/cudd/cuddAndAbs.c
+++ b/src/bdd/cudd/cuddAndAbs.c
@@ -109,6 +109,46 @@ Cudd_bddAndAbstract(
} /* end of Cudd_bddAndAbstract */
+/**Function********************************************************************
+
+ Synopsis [Takes the AND of two BDDs and simultaneously abstracts the
+ variables in cube. Returns NULL if too many nodes are required.]
+
+ Description [Takes the AND of two BDDs and simultaneously abstracts
+ the variables in cube. The variables are existentially abstracted.
+ Returns a pointer to the result is successful; NULL otherwise.
+ In particular, if the number of new nodes created exceeds
+ <code>limit</code>, this function returns NULL.]
+
+ SideEffects [None]
+
+ SeeAlso [Cudd_bddAndAbstract]
+
+******************************************************************************/
+DdNode *
+Cudd_bddAndAbstractLimit(
+ DdManager * manager,
+ DdNode * f,
+ DdNode * g,
+ DdNode * cube,
+ unsigned int limit)
+{
+ DdNode *res;
+ unsigned int saveLimit = manager->maxLive;
+
+ manager->maxLive = (manager->keys - manager->dead) +
+ (manager->keysZ - manager->deadZ) + limit;
+ do {
+ manager->reordered = 0;
+ res = cuddBddAndAbstractRecur(manager, f, g, cube);
+ } while (manager->reordered == 1);
+ manager->maxLive = saveLimit;
+ return(res);
+
+} /* end of Cudd_bddAndAbstractLimit */
+
+
+
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
diff --git a/src/bdd/cudd/cuddInit.c b/src/bdd/cudd/cuddInit.c
index 43b2ac29..6be35970 100644
--- a/src/bdd/cudd/cuddInit.c
+++ b/src/bdd/cudd/cuddInit.c
@@ -174,7 +174,8 @@ Cudd_Init(
unique->memused += sizeof(DdNode *) * unique->maxSize;
- unique->bReached = NULL;
+ unique->bFunc = NULL;
+ unique->bFunc2 = NULL;
return(unique);
} /* end of Cudd_Init */
diff --git a/src/bdd/cudd/cuddInt.h b/src/bdd/cudd/cuddInt.h
index 84146132..f5becf84 100644
--- a/src/bdd/cudd/cuddInt.h
+++ b/src/bdd/cudd/cuddInt.h
@@ -439,7 +439,8 @@ struct DdManager { /* specialized DD symbol table */
int nvars; /* variables used so far */
int threshold; /* for pseudo var threshold value*/
#endif
- DdNode * bReached;
+ DdNode * bFunc;
+ DdNode * bFunc2;
};
typedef struct Move {
diff --git a/src/misc/extra/extra.h b/src/misc/extra/extra.h
index 96ff6072..33303fac 100644
--- a/src/misc/extra/extra.h
+++ b/src/misc/extra/extra.h
@@ -196,6 +196,8 @@ extern DdNode * Extra_bddCreateExor( DdManager * dd, int nVars );
extern DdNode * Extra_zddPrimes( DdManager * dd, DdNode * F );
extern void Extra_bddPermuteArray( DdManager * dd, DdNode ** bNodesIn, DdNode ** bNodesOut, int nNodes, int *permut );
extern DdNode * Extra_bddComputeCube( DdManager * dd, DdNode ** bXVars, int nVars );
+extern DdNode * Extra_bddChangePolarity( DdManager * dd, DdNode * bFunc, DdNode * bVars );
+extern DdNode * extraBddChangePolarity( DdManager * dd, DdNode * bFunc, DdNode * bVars );
#ifndef ABC_PRB
#define ABC_PRB(dd,f) printf("%s = ", #f); Extra_bddPrint(dd,f); printf("\n")
diff --git a/src/misc/extra/extraBddMisc.c b/src/misc/extra/extraBddMisc.c
index cdded9b8..69309a4d 100644
--- a/src/misc/extra/extraBddMisc.c
+++ b/src/misc/extra/extraBddMisc.c
@@ -1013,6 +1013,32 @@ DdNode * Extra_bddComputeCube( DdManager * dd, DdNode ** bXVars, int nVars )
return bRes;
}
+/**Function********************************************************************
+
+ Synopsis [Changes the polarity of vars listed in the cube.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * Extra_bddChangePolarity(
+ DdManager * dd, /* the DD manager */
+ DdNode * bFunc,
+ DdNode * bVars)
+{
+ DdNode *res;
+ do {
+ dd->reordered = 0;
+ res = extraBddChangePolarity( dd, bFunc, bVars );
+ } while (dd->reordered == 1);
+ return(res);
+
+} /* end of Extra_bddChangePolarity */
+
+
/*---------------------------------------------------------------------------*/
/* Definition of internal functions */
/*---------------------------------------------------------------------------*/
@@ -1659,6 +1685,121 @@ cuddBddPermuteRecur( DdManager * manager /* DD manager */ ,
} /* end of cuddBddPermuteRecur */
+/**Function********************************************************************
+
+ Synopsis [Performs the reordering-sensitive step of Extra_bddChangePolarity().]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * extraBddChangePolarity(
+ DdManager * dd, /* the DD manager */
+ DdNode * bFunc,
+ DdNode * bVars)
+{
+ DdNode * bRes;
+
+ if ( bVars == b1 )
+ return bFunc;
+ if ( Cudd_IsConstant(bFunc) )
+ return bFunc;
+
+ if ( bRes = cuddCacheLookup2(dd, extraBddChangePolarity, bFunc, bVars) )
+ return bRes;
+ else
+ {
+ DdNode * bFR = Cudd_Regular(bFunc);
+ int LevelF = dd->perm[bFR->index];
+ int LevelV = dd->perm[bVars->index];
+
+ if ( LevelV < LevelF )
+ bRes = extraBddChangePolarity( dd, bFunc, cuddT(bVars) );
+ else // if ( LevelF <= LevelV )
+ {
+ DdNode * bRes0, * bRes1;
+ DdNode * bF0, * bF1;
+ DdNode * bVarsNext;
+
+ // cofactor the functions
+ if ( bFR != bFunc ) // bFunc is complemented
+ {
+ bF0 = Cudd_Not( cuddE(bFR) );
+ bF1 = Cudd_Not( cuddT(bFR) );
+ }
+ else
+ {
+ bF0 = cuddE(bFR);
+ bF1 = cuddT(bFR);
+ }
+
+ if ( LevelF == LevelV )
+ bVarsNext = cuddT(bVars);
+ else
+ bVarsNext = bVars;
+
+ bRes0 = extraBddChangePolarity( dd, bF0, bVarsNext );
+ if ( bRes0 == NULL )
+ return NULL;
+ cuddRef( bRes0 );
+
+ bRes1 = extraBddChangePolarity( dd, bF1, bVarsNext );
+ if ( bRes1 == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bRes0 );
+ return NULL;
+ }
+ cuddRef( bRes1 );
+
+ if ( LevelF == LevelV )
+ { // swap the cofactors
+ DdNode * bTemp;
+ bTemp = bRes0;
+ bRes0 = bRes1;
+ bRes1 = bTemp;
+ }
+
+ /* only aRes0 and aRes1 are referenced at this point */
+
+ /* consider the case when Res0 and Res1 are the same node */
+ if ( bRes0 == bRes1 )
+ bRes = bRes1;
+ /* consider the case when Res1 is complemented */
+ else if ( Cudd_IsComplement(bRes1) )
+ {
+ bRes = cuddUniqueInter(dd, bFR->index, Cudd_Not(bRes1), Cudd_Not(bRes0));
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref(dd,bRes0);
+ Cudd_RecursiveDeref(dd,bRes1);
+ return NULL;
+ }
+ bRes = Cudd_Not(bRes);
+ }
+ else
+ {
+ bRes = cuddUniqueInter( dd, bFR->index, bRes1, bRes0 );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref(dd,bRes0);
+ Cudd_RecursiveDeref(dd,bRes1);
+ return NULL;
+ }
+ }
+ cuddDeref( bRes0 );
+ cuddDeref( bRes1 );
+ }
+
+ /* insert the result into cache */
+ cuddCacheInsert2(dd, extraBddChangePolarity, bFunc, bVars, bRes);
+ return bRes;
+ }
+} /* end of extraBddChangePolarity */
+
+
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
diff --git a/src/misc/hash/hashFlt.h b/src/misc/hash/hashFlt.h
index b4a8fb49..74e8503d 100644
--- a/src/misc/hash/hashFlt.h
+++ b/src/misc/hash/hashFlt.h
@@ -311,14 +311,15 @@ static inline void Hash_FltRemove( Hash_Flt_t *p, int key )
***********************************************************************/
static inline void Hash_FltFree( Hash_Flt_t *p ) {
int bin;
- Hash_Flt_Entry_t *pEntry;
+ Hash_Flt_Entry_t *pEntry, *pTemp;
// free bins
for(bin = 0; bin < p->nBins; bin++) {
pEntry = p->pArray[bin];
while(pEntry) {
+ pTemp = pEntry;
pEntry = pEntry->pNext;
- ABC_FREE( pEntry );
+ ABC_FREE( pTemp );
}
}
diff --git a/src/misc/hash/hashPtr.h b/src/misc/hash/hashPtr.h
index 9e510866..a10fb548 100644
--- a/src/misc/hash/hashPtr.h
+++ b/src/misc/hash/hashPtr.h
@@ -115,19 +115,17 @@ static inline Hash_Ptr_t * Hash_PtrAlloc( int nBins )
static inline int Hash_PtrExists( Hash_Ptr_t *p, int key )
{
int bin;
- Hash_Ptr_Entry_t *pEntry, **pLast;
+ Hash_Ptr_Entry_t *pEntry;
// find the bin where this key would live
bin = (*(p->fHash))(key, p->nBins);
// search for key
- pLast = &(p->pArray[bin]);
pEntry = p->pArray[bin];
while(pEntry) {
if (pEntry->key == key) {
return 1;
}
- pLast = &(pEntry->pNext);
pEntry = pEntry->pNext;
}
@@ -310,16 +308,18 @@ static inline void* Hash_PtrRemove( Hash_Ptr_t *p, int key )
SeeAlso []
***********************************************************************/
-static inline void Hash_PtrFree( Hash_Ptr_t *p ) {
+static inline void Hash_PtrFree( Hash_Ptr_t *p )
+{
int bin;
- Hash_Ptr_Entry_t *pEntry;
+ Hash_Ptr_Entry_t *pEntry, *pTemp;
// free bins
for(bin = 0; bin < p->nBins; bin++) {
pEntry = p->pArray[bin];
while(pEntry) {
+ pTemp = pEntry;
pEntry = pEntry->pNext;
- ABC_FREE( pEntry );
+ ABC_FREE( pTemp );
}
}