From d4291dab37a647ac3d8d0f4e91e571bbb4e3553b Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Tue, 1 Feb 2011 15:47:55 -0800 Subject: Cumulative changes of the last two weeks. --- src/aig/aig/aig.h | 2 + src/aig/aig/aigDfs.c | 64 ++ src/aig/aig/aigDoms.c | 959 ++++++++++++++++++++++ src/aig/aig/aigDup.c | 27 + src/aig/bbr/bbrReach.c | 9 + src/aig/live/liveness_old.c | 1756 ---------------------------------------- src/aig/llb/llb.h | 4 +- src/aig/llb/llb1Cluster.c | 357 ++++++++ src/aig/llb/llb1Constr.c | 313 +++++++ src/aig/llb/llb1Core.c | 221 +++++ src/aig/llb/llb1Group.c | 474 +++++++++++ src/aig/llb/llb1Hint.c | 226 ++++++ src/aig/llb/llb1Man.c | 189 +++++ src/aig/llb/llb1Matrix.c | 430 ++++++++++ src/aig/llb/llb1Pivot.c | 254 ++++++ src/aig/llb/llb1Reach.c | 629 ++++++++++++++ src/aig/llb/llb1Sched.c | 257 ++++++ src/aig/llb/llb2Bad.c | 126 +++ src/aig/llb/llb2Core.c | 638 +++++++++++++++ src/aig/llb/llb2Driver.c | 208 +++++ src/aig/llb/llb2Dump.c | 104 +++ src/aig/llb/llb2Flow.c | 1374 +++++++++++++++++++++++++++++++ src/aig/llb/llb2Image.c | 440 ++++++++++ src/aig/llb/llb3Image.c | 905 +++++++++++++++++++++ src/aig/llb/llb3Nonlin.c | 711 ++++++++++++++++ src/aig/llb/llb3Nonlin_multi.c | 1490 ++++++++++++++++++++++++++++++++++ src/aig/llb/llbCex.c | 56 -- src/aig/llb/llbCluster.c | 357 -------- src/aig/llb/llbConstr.c | 313 ------- src/aig/llb/llbCore.c | 219 ----- src/aig/llb/llbFlow.c | 639 --------------- src/aig/llb/llbHint.c | 226 ------ src/aig/llb/llbInt.h | 34 +- src/aig/llb/llbMan.c | 189 ----- src/aig/llb/llbMatrix.c | 430 ---------- src/aig/llb/llbPart.c | 474 ----------- src/aig/llb/llbPivot.c | 254 ------ src/aig/llb/llbReach.c | 620 -------------- src/aig/llb/llbSched.c | 257 ------ src/aig/llb/module.make | 30 +- src/aig/nwk/nwkAig.c | 4 +- src/aig/saig/saigAbs.c | 26 +- src/aig/saig/saigPhase.c | 61 +- src/aig/saig/saigTempor.c | 61 +- src/base/abci/abc.c | 317 +++++++- src/base/abci/abcDar.c | 21 +- src/bdd/cudd/cudd.h | 1 + src/bdd/cudd/cuddAndAbs.c | 40 + src/bdd/cudd/cuddInit.c | 3 +- src/bdd/cudd/cuddInt.h | 3 +- src/misc/extra/extra.h | 2 + src/misc/extra/extraBddMisc.c | 141 ++++ src/misc/hash/hashFlt.h | 5 +- src/misc/hash/hashGen.h | 360 ++++++++ src/misc/hash/hashPtr.h | 12 +- 55 files changed, 11462 insertions(+), 5860 deletions(-) create mode 100644 src/aig/aig/aigDoms.c delete mode 100644 src/aig/live/liveness_old.c create mode 100644 src/aig/llb/llb1Cluster.c create mode 100644 src/aig/llb/llb1Constr.c create mode 100644 src/aig/llb/llb1Core.c create mode 100644 src/aig/llb/llb1Group.c create mode 100644 src/aig/llb/llb1Hint.c create mode 100644 src/aig/llb/llb1Man.c create mode 100644 src/aig/llb/llb1Matrix.c create mode 100644 src/aig/llb/llb1Pivot.c create mode 100644 src/aig/llb/llb1Reach.c create mode 100644 src/aig/llb/llb1Sched.c create mode 100644 src/aig/llb/llb2Bad.c create mode 100644 src/aig/llb/llb2Core.c create mode 100644 src/aig/llb/llb2Driver.c create mode 100644 src/aig/llb/llb2Dump.c create mode 100644 src/aig/llb/llb2Flow.c create mode 100644 src/aig/llb/llb2Image.c create mode 100644 src/aig/llb/llb3Image.c create mode 100644 src/aig/llb/llb3Nonlin.c create mode 100644 src/aig/llb/llb3Nonlin_multi.c delete mode 100644 src/aig/llb/llbCex.c delete mode 100644 src/aig/llb/llbCluster.c delete mode 100644 src/aig/llb/llbConstr.c delete mode 100644 src/aig/llb/llbCore.c delete mode 100644 src/aig/llb/llbFlow.c delete mode 100644 src/aig/llb/llbHint.c delete mode 100644 src/aig/llb/llbMan.c delete mode 100644 src/aig/llb/llbMatrix.c delete mode 100644 src/aig/llb/llbPart.c delete mode 100644 src/aig/llb/llbPivot.c delete mode 100644 src/aig/llb/llbReach.c delete mode 100644 src/aig/llb/llbSched.c create mode 100644 src/misc/hash/hashGen.h (limited to 'src') 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 @@ -167,6 +167,70 @@ Vec_Ptr_t * Aig_ManDfs( Aig_Man_t * p, int fNodesOnly ) return vNodes; } +/**Function************************************************************* + + Synopsis [Collects internal nodes in the DFS order.] + + Description [] + + SideEffects [] + + 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.] 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 -#include "main.h" -#include "aig.h" -#include "saig.h" -#include - -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; ipName = 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/llb1Cluster.c b/src/aig/llb/llb1Cluster.c new file mode 100644 index 00000000..8a41fe58 --- /dev/null +++ b/src/aig/llb/llb1Cluster.c @@ -0,0 +1,357 @@ +/**CFile**************************************************************** + + FileName [llb1Cluster.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Clustering algorithm.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Cluster.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" +#include "extra.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManComputeCommonQuant( Llb_Mtr_t * p, int iCol1, int iCol2 ) +{ + int iVar, Weight = 0; + for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ ) + { + // count each removed variable as 2 + if ( p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 1 && p->pRowSums[iVar] == 2 ) + Weight += 2; + // count each added variale as -1 + else if ( (p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 0) || + (p->pMatrix[iCol1][iVar] == 0 && p->pMatrix[iCol2][iVar] == 1) ) + Weight--; + } + return Weight; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManComputeBestQuant( Llb_Mtr_t * p ) +{ + int i, k, WeightBest = -100000, WeightCur, RetValue = -1; + for ( i = 1; i < p->nCols-1; i++ ) + for ( k = i+1; k < p->nCols-1; k++ ) + { + if ( p->pColSums[i] == 0 || p->pColSums[i] > p->pMan->pPars->nClusterMax ) + continue; + if ( p->pColSums[k] == 0 || p->pColSums[k] > p->pMan->pPars->nClusterMax ) + continue; + + WeightCur = Llb_ManComputeCommonQuant( p, i, k ); + if ( WeightCur <= 0 ) + continue; + if ( WeightBest < WeightCur ) + { + WeightBest = WeightCur; + RetValue = (i << 16) | k; + } + } +// printf( "Choosing best quant Weight %4d\n", WeightCur ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float ** Llb_ManComputeQuant( Llb_Mtr_t * p ) +{ + float ** pCosts; + int i, k; + // alloc and clean + pCosts = (float **)Extra_ArrayAlloc( p->nCols, p->nCols, sizeof(float) ); + for ( i = 0; i < p->nCols; i++ ) + for ( k = 0; k < p->nCols; k++ ) + pCosts[i][i] = 0.0; + // fill up + for ( i = 1; i < p->nCols-1; i++ ) + for ( k = i+1; k < p->nCols-1; k++ ) + pCosts[i][k] = pCosts[k][i] = Llb_ManComputeCommonQuant( p, i, k ); + return pCosts; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Llb_ManComputeCommonAttr( Llb_Mtr_t * p, int iCol1, int iCol2 ) +{ + int iVar, CountComm = 0, CountDiff = 0; + for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ ) + { + if ( p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 1 ) + CountComm++; + else if ( p->pMatrix[iCol1][iVar] == 1 || p->pMatrix[iCol2][iVar] == 1 ) + CountDiff++; + } +/* + printf( "Attr cost for %4d and %4d: %4d %4d (%5.2f)\n", + iCol1, iCol2, + CountDiff, CountComm, + -1.0 * CountDiff / ( CountComm + CountDiff ) ); +*/ + return -1.0 * CountDiff / ( CountComm + CountDiff ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManComputeBestAttr( Llb_Mtr_t * p ) +{ + float WeightBest = -100000, WeightCur; + int i, k, RetValue = -1; + for ( i = 1; i < p->nCols-1; i++ ) + for ( k = i+1; k < p->nCols-1; k++ ) + { + if ( p->pColSums[i] == 0 || p->pColSums[i] > p->pMan->pPars->nClusterMax ) + continue; + if ( p->pColSums[k] == 0 || p->pColSums[k] > p->pMan->pPars->nClusterMax ) + continue; + WeightCur = Llb_ManComputeCommonAttr( p, i, k ); + if ( WeightBest < WeightCur ) + { + WeightBest = WeightCur; + RetValue = (i << 16) | k; + } + } + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float ** Llb_ManComputeAttr( Llb_Mtr_t * p ) +{ + float ** pCosts; + int i, k; + // alloc and clean + pCosts = (float **)Extra_ArrayAlloc( p->nCols, p->nCols, sizeof(float) ); + for ( i = 0; i < p->nCols; i++ ) + for ( k = 0; k < p->nCols; k++ ) + pCosts[i][i] = 0.0; + // fill up + for ( i = 1; i < p->nCols-1; i++ ) + for ( k = i+1; k < p->nCols-1; k++ ) + pCosts[i][k] = pCosts[k][i] = Llb_ManComputeCommonAttr( p, i, k ); + return pCosts; +} + + +/**Function************************************************************* + + Synopsis [Returns the number of variables that will be saved.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrCombineSelectedColumns( Llb_Mtr_t * p, int iGrp1, int iGrp2 ) +{ + int iVar; + assert( iGrp1 >= 1 && iGrp1 < p->nCols - 1 ); + assert( iGrp2 >= 1 && iGrp2 < p->nCols - 1 ); + assert( p->pColGrps[iGrp1] != NULL ); + assert( p->pColGrps[iGrp2] != NULL ); + for ( iVar = 0; iVar < p->nRows; iVar++ ) + { + if ( p->pMatrix[iGrp1][iVar] == 1 && p->pMatrix[iGrp2][iVar] == 1 ) + p->pRowSums[iVar]--; + if ( p->pMatrix[iGrp1][iVar] == 0 && p->pMatrix[iGrp2][iVar] == 1 ) + { + p->pMatrix[iGrp1][iVar] = 1; + p->pColSums[iGrp1]++; + } + if ( p->pMatrix[iGrp2][iVar] == 1 ) + p->pMatrix[iGrp2][iVar] = 0; + } + p->pColSums[iGrp2] = 0; +} + + +/**Function************************************************************* + + Synopsis [Combines one pair of columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManClusterOne( Llb_Mtr_t * p, int iCol1, int iCol2 ) +{ + int fVerbose = 0; + Llb_Grp_t * pGrp; + int iVar; + + if ( fVerbose ) + { + printf( "Combining %d and %d\n", iCol1, iCol2 ); + for ( iVar = 0; iVar < p->nRows; iVar++ ) + { + if ( p->pMatrix[iCol1][iVar] == 0 && p->pMatrix[iCol2][iVar] == 0 ) + continue; + printf( "%3d : %c%c\n", iVar, + p->pMatrix[iCol1][iVar]? '*':' ', + p->pMatrix[iCol2][iVar]? '*':' ' ); + } + } + pGrp = Llb_ManGroupsCombine( p->pColGrps[iCol1], p->pColGrps[iCol2] ); + Llb_MtrCombineSelectedColumns( p, iCol1, iCol2 ); + p->pColGrps[iCol1] = pGrp; + p->pColGrps[iCol2] = NULL; +} + +/**Function************************************************************* + + Synopsis [Removes empty columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManClusterCompress( Llb_Mtr_t * p ) +{ + int i, k = 0; + for ( i = 0; i < p->nCols; i++ ) + { + if ( p->pColGrps[i] == NULL ) + { + assert( p->pColSums[i] == 0 ); + assert( p->pMatrix[i] != NULL ); + ABC_FREE( p->pMatrix[i] ); + continue; + } + p->pMatrix[k] = p->pMatrix[i]; + p->pColGrps[k] = p->pColGrps[i]; + p->pColSums[k] = p->pColSums[i]; + k++; + } + p->nCols = k; +} + +/**Function************************************************************* + + Synopsis [Combines one pair of columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManCluster( Llb_Mtr_t * p ) +{ + int RetValue; + do + { + do { + RetValue = Llb_ManComputeBestQuant( p ); + if ( RetValue > 0 ) + Llb_ManClusterOne( p, RetValue >> 16, RetValue & 0xffff ); + } + while ( RetValue > 0 ); + + RetValue = Llb_ManComputeBestAttr( p ); + if ( RetValue > 0 ) + Llb_ManClusterOne( p, RetValue >> 16, RetValue & 0xffff ); + + Llb_MtrVerifyMatrix( p ); + } + while ( RetValue > 0 ); + + Llb_ManClusterCompress( p ); + + Llb_MtrVerifyMatrix( p ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/aig/llb/llb1Constr.c b/src/aig/llb/llb1Constr.c new file mode 100644 index 00000000..67fb30ba --- /dev/null +++ b/src/aig/llb/llb1Constr.c @@ -0,0 +1,313 @@ +/**CFile**************************************************************** + + FileName [llb1Constr.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Computing inductive constraints.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Constr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the array of constraint candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManCountEntries( Vec_Int_t * vCands ) +{ + int i, Entry, Counter = 0; + Vec_IntForEachEntry( vCands, Entry, i ) + Counter += ((Entry == 0) || (Entry == 1)); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns the array of constraint candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrintEntries( Aig_Man_t * p, Vec_Int_t * vCands ) +{ + int i, Entry; + if ( vCands == NULL ) + { + printf( "There is no hints.\n" ); + return; + } + Entry = Llb_ManCountEntries(vCands); + printf( "\n*** Using %d hint%s:\n", Entry, (Entry != 1 ? "s":"") ); + Vec_IntForEachEntry( vCands, Entry, i ) + { + if ( Entry != 0 && Entry != 1 ) + continue; + printf( "%c", Entry ? '+' : '-' ); + printf( "%-6d : ", i ); + Aig_ObjPrint( p, Aig_ManObj(p, i) ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Dereference BDD nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManDerefenceBdds( Aig_Man_t * p, DdManager * dd ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachObj( p, pObj, i ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); +} + +/**Function************************************************************* + + Synopsis [Returns the array of constraint candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManComputeIndCase_rec( Aig_Man_t * p, Aig_Obj_t * pObj, DdManager * dd, Vec_Ptr_t * vBdds ) +{ + DdNode * bBdd0, * bBdd1; + DdNode * bFunc = (DdNode *)Vec_PtrEntry( vBdds, Aig_ObjId(pObj) ); + if ( bFunc != NULL ) + return bFunc; + assert( Aig_ObjIsNode(pObj) ); + bBdd0 = Llb_ManComputeIndCase_rec( p, Aig_ObjFanin0(pObj), dd, vBdds ); + bBdd1 = Llb_ManComputeIndCase_rec( p, Aig_ObjFanin1(pObj), dd, vBdds ); + bBdd0 = Cudd_NotCond( bBdd0, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( bBdd1, Aig_ObjFaninC1(pObj) ); + bFunc = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bFunc ); + Vec_PtrWriteEntry( vBdds, Aig_ObjId(pObj), bFunc ); + return bFunc; +} + +/**Function************************************************************* + + Synopsis [Returns the array of constraint candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManComputeIndCase( Aig_Man_t * p, DdManager * dd, Vec_Int_t * vNodes ) +{ + Vec_Ptr_t * vBdds; + Aig_Obj_t * pObj; + DdNode * bFunc; + int i, Entry; + vBdds = Vec_PtrStart( Aig_ManObjNumMax(p) ); + bFunc = Cudd_ReadOne(dd); Cudd_Ref( bFunc ); + Vec_PtrWriteEntry( vBdds, Aig_ObjId(Aig_ManConst1(p)), bFunc ); + Saig_ManForEachPi( p, pObj, i ) + { + bFunc = Cudd_bddIthVar( dd, Aig_ManPiNum(p) + i ); Cudd_Ref( bFunc ); + Vec_PtrWriteEntry( vBdds, Aig_ObjId(pObj), bFunc ); + } + Saig_ManForEachLi( p, pObj, i ) + { + bFunc = (DdNode *)pObj->pData; Cudd_Ref( bFunc ); + Vec_PtrWriteEntry( vBdds, Aig_ObjId(Saig_ObjLiToLo(p, pObj)), bFunc ); + } + Vec_IntForEachEntry( vNodes, Entry, i ) + { + if ( Entry != 0 && Entry != 1 ) + continue; + pObj = Aig_ManObj( p, i ); + bFunc = Llb_ManComputeIndCase_rec( p, pObj, dd, vBdds ); + if ( Entry == 0 ) + { +// Extra_bddPrint( dd, Cudd_Not(pObj->pData) ); printf( "\n" ); +// Extra_bddPrint( dd, Cudd_Not(bFunc) ); printf( "\n" ); + if ( !Cudd_bddLeq( dd, Cudd_Not(pObj->pData), Cudd_Not(bFunc) ) ) + Vec_IntWriteEntry( vNodes, i, -1 ); + } + else if ( Entry == 1 ) + { +// Extra_bddPrint( dd, pObj->pData ); printf( "\n" ); +// Extra_bddPrint( dd, bFunc ); printf( "\n" ); + if ( !Cudd_bddLeq( dd, (DdNode *)pObj->pData, bFunc ) ) + Vec_IntWriteEntry( vNodes, i, -1 ); + } + } + Vec_PtrForEachEntry( DdNode *, vBdds, bFunc, i ) + if ( bFunc ) + Cudd_RecursiveDeref( dd, bFunc ); + Vec_PtrFree( vBdds ); +} + +/**Function************************************************************* + + Synopsis [Returns the array of constraint candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_ManComputeBaseCase( Aig_Man_t * p, DdManager * dd ) +{ + Vec_Int_t * vNodes; + Aig_Obj_t * pObj, * pRoot; + int i; + pRoot = Aig_ManPo( p, 0 ); + vNodes = Vec_IntStartFull( Aig_ManObjNumMax(p) ); + Aig_ManForEachObj( p, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) ) + continue; + if ( Cudd_bddLeq( dd, (DdNode *)pObj->pData, Cudd_Not(pRoot->pData) ) ) + Vec_IntWriteEntry( vNodes, i, 1 ); + else if ( Cudd_bddLeq( dd, Cudd_Not((DdNode *)pObj->pData), Cudd_Not(pRoot->pData) ) ) + Vec_IntWriteEntry( vNodes, i, 0 ); + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Constructs global BDDs for each object in the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdManager * Llb_ManConstructGlobalBdds( Aig_Man_t * p ) +{ + DdManager * dd; + DdNode * bBdd0, * bBdd1; + Aig_Obj_t * pObj; + int i; + dd = Cudd_Init( Aig_ManPiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + pObj = Aig_ManConst1(p); + pObj->pData = Cudd_ReadOne(dd); Cudd_Ref( (DdNode *)pObj->pData ); + Aig_ManForEachPi( p, pObj, i ) + { + pObj->pData = Cudd_bddIthVar(dd, i); Cudd_Ref( (DdNode *)pObj->pData ); + } + Aig_ManForEachNode( p, pObj, i ) + { + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); + pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData ); + } + Aig_ManForEachPo( p, pObj, i ) + { + pObj->pData = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); Cudd_Ref( (DdNode *)pObj->pData ); + } + return dd; +} + +/**Function************************************************************* + + Synopsis [Derives inductive constraints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_ManDeriveConstraints( Aig_Man_t * p ) +{ + DdManager * dd; + Vec_Int_t * vNodes; + if ( Saig_ManPoNum(p) != 1 ) + { + printf( "The AIG has %d property outputs.\n", Saig_ManPoNum(p) ); + return NULL; + } + assert( Saig_ManPoNum(p) == 1 ); + dd = Llb_ManConstructGlobalBdds( p ); + vNodes = Llb_ManComputeBaseCase( p, dd ); + if ( Llb_ManCountEntries(vNodes) > 0 ) + Llb_ManComputeIndCase( p, dd, vNodes ); + if ( Llb_ManCountEntries(vNodes) == 0 ) + Vec_IntFreeP( &vNodes ); + Llb_ManDerefenceBdds( p, dd ); + Extra_StopManager( dd ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Tests derived constraints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManConstrTest( Aig_Man_t * p ) +{ + Vec_Int_t * vNodes; + vNodes = Llb_ManDeriveConstraints( p ); + Llb_ManPrintEntries( p, vNodes ); + Vec_IntFreeP( &vNodes ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/aig/llb/llb1Core.c b/src/aig/llb/llb1Core.c new file mode 100644 index 00000000..ff7eadbb --- /dev/null +++ b/src/aig/llb/llb1Core.c @@ -0,0 +1,221 @@ +/**CFile**************************************************************** + + FileName [llb1Core.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Top-level procedure.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Core.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" +#include "gia.h" +#include "giaAig.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManSetDefaultParams( Gia_ParLlb_t * p ) +{ + memset( p, 0, sizeof(Gia_ParLlb_t) ); + p->nBddMax = 10000000; + p->nIterMax = 10000000; + p->nClusterMax = 20; + p->nHintDepth = 0; + p->HintFirst = 0; + p->fUseFlow = 0; // use flow + p->nVolumeMax = 100; // max volume + p->nVolumeMin = 30; // min volume + p->nPartValue = 5; // partitioning value + p->fBackward = 0; // forward by default + p->fReorder = 1; + p->fIndConstr = 0; + p->fUsePivots = 0; + p->fCluster = 0; + p->fSchedule = 0; + p->fDumpReached = 0; + p->fVerbose = 0; + p->fVeryVerbose = 0; + p->fSilent = 0; + p->TimeLimit = 0; +// p->TimeLimit = 0; + p->TimeLimitGlo = 0; + p->TimeTarget = 0; + p->iFrame = -1; +} + + +/**Function************************************************************* + + Synopsis [Prints statistics about MFFCs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrintAig( Llb_Man_t * p ) +{ + Abc_Print( 1, "pi =%3d ", Saig_ManPiNum(p->pAig) ); + Abc_Print( 1, "po =%3d ", Saig_ManPoNum(p->pAig) ); + Abc_Print( 1, "ff =%3d ", Saig_ManRegNum(p->pAig) ); + Abc_Print( 1, "int =%5d ", Vec_IntSize(p->vVar2Obj)-Aig_ManPiNum(p->pAig)-Saig_ManRegNum(p->pAig) ); + Abc_Print( 1, "var =%5d ", Vec_IntSize(p->vVar2Obj) ); + Abc_Print( 1, "part =%5d ", Vec_PtrSize(p->vGroups)-2 ); + Abc_Print( 1, "and =%5d ", Aig_ManNodeNum(p->pAig) ); + Abc_Print( 1, "lev =%4d ", Aig_ManLevelNum(p->pAig) ); +// Abc_Print( 1, "cut =%4d ", Llb_ManCrossCut(p->pAig) ); + Abc_Print( 1, "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManModelCheckAig( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars, Vec_Int_t * vHints, DdManager ** pddGlo ) +{ + Llb_Man_t * p = NULL; + Aig_Man_t * pAig; + int RetValue = -1; + int clk = clock(); + + if ( pPars->fIndConstr ) + { + assert( vHints == NULL ); + vHints = Llb_ManDeriveConstraints( pAigGlo ); + } + + // derive AIG for hints + if ( vHints == NULL ) + pAig = Aig_ManDupSimple( pAigGlo ); + else + { + if ( pPars->fVerbose ) + Llb_ManPrintEntries( pAigGlo, vHints ); + pAig = Aig_ManDupSimpleWithHints( pAigGlo, vHints ); + } + + + if ( pPars->fUseFlow ) + { +// p = Llb_ManStartFlow( pAigGlo, pAig, pPars ); + } + else + { + p = Llb_ManStart( pAigGlo, pAig, pPars ); + if ( pPars->fVerbose ) + { + Llb_ManPrintAig( p ); + printf( "Original matrix: " ); + Llb_MtrPrintMatrixStats( p->pMatrix ); + if ( pPars->fVeryVerbose ) + Llb_MtrPrint( p->pMatrix, 1 ); + } + if ( pPars->fCluster ) + { + Llb_ManCluster( p->pMatrix ); + if ( pPars->fVerbose ) + { + printf( "Matrix after clustering: " ); + Llb_MtrPrintMatrixStats( p->pMatrix ); + if ( pPars->fVeryVerbose ) + Llb_MtrPrint( p->pMatrix, 1 ); + } + } + if ( pPars->fSchedule ) + { + Llb_MtrSchedule( p->pMatrix ); + if ( pPars->fVerbose ) + { + printf( "Matrix after scheduling: " ); + Llb_MtrPrintMatrixStats( p->pMatrix ); + if ( pPars->fVeryVerbose ) + Llb_MtrPrint( p->pMatrix, 1 ); + } + } + } + + if ( !p->pPars->fSkipReach ) + RetValue = Llb_ManReachability( p, vHints, pddGlo ); + Llb_ManStop( p ); + + Abc_PrintTime( 1, "Time", clock() - clk ); + + if ( pPars->fIndConstr ) + Vec_IntFreeP( &vHints ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManModelCheckGia( Gia_Man_t * pGia, Gia_ParLlb_t * pPars ) +{ + Gia_Man_t * pGia2; + Aig_Man_t * pAig; + int RetValue = -1; + pGia2 = Gia_ManDupDfs( pGia ); + pAig = Gia_ManToAigSimple( pGia2 ); + Gia_ManStop( pGia2 ); +//Aig_ManShow( pAig, 0, NULL ); + + if ( pPars->nHintDepth == 0 ) + RetValue = Llb_ManModelCheckAig( pAig, pPars, NULL, NULL ); + else + RetValue = Llb_ManModelCheckAigWithHints( pAig, pPars ); + Aig_ManStop( pAig ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/aig/llb/llb1Group.c b/src/aig/llb/llb1Group.c new file mode 100644 index 00000000..4ebfc3a3 --- /dev/null +++ b/src/aig/llb/llb1Group.c @@ -0,0 +1,474 @@ +/**CFile**************************************************************** + + FileName [llb1Group.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Initial partition computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Group.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Grp_t * Llb_ManGroupAlloc( Llb_Man_t * pMan ) +{ + Llb_Grp_t * p; + p = ABC_CALLOC( Llb_Grp_t, 1 ); + p->pMan = pMan; + p->vIns = Vec_PtrAlloc( 8 ); + p->vOuts = Vec_PtrAlloc( 8 ); + p->Id = Vec_PtrSize( pMan->vGroups ); + Vec_PtrPush( pMan->vGroups, p ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManGroupStop( Llb_Grp_t * p ) +{ + if ( p == NULL ) + return; + Vec_PtrWriteEntry( p->pMan->vGroups, p->Id, NULL ); + Vec_PtrFreeP( &p->vIns ); + Vec_PtrFreeP( &p->vOuts ); + Vec_PtrFreeP( &p->vNodes ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManGroupCollect_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return; + Aig_ObjSetTravIdCurrent(pAig, pObj); + if ( Aig_ObjIsConst1(pObj) ) + return; + if ( Aig_ObjIsPo(pObj) ) + { + Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin0(pObj), vNodes ); + return; + } + assert( Aig_ObjIsAnd(pObj) ); + Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin0(pObj), vNodes ); + Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin1(pObj), vNodes ); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Collects the support of MFFC.] + + Description [Returns the number of internal nodes in the MFFC.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManGroupCollect( Llb_Grp_t * pGroup ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + vNodes = Vec_PtrAlloc( 100 ); + Aig_ManIncrementTravId( pGroup->pMan->pAig ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) + Aig_ObjSetTravIdCurrent( pGroup->pMan->pAig, pObj ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + Aig_ObjSetTravIdPrevious( pGroup->pMan->pAig, pObj ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + Llb_ManGroupCollect_rec( pGroup->pMan->pAig, pObj, vNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManGroupCreate_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vSupp ) +{ + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return; + Aig_ObjSetTravIdCurrent(pAig, pObj); + if ( Aig_ObjIsConst1(pObj) ) + return; + if ( pObj->fMarkA ) + { + Vec_PtrPush( vSupp, pObj ); + return; + } + assert( Aig_ObjIsAnd(pObj) ); + Llb_ManGroupCreate_rec( pAig, Aig_ObjFanin0(pObj), vSupp ); + Llb_ManGroupCreate_rec( pAig, Aig_ObjFanin1(pObj), vSupp ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Grp_t * Llb_ManGroupCreate( Llb_Man_t * pMan, Aig_Obj_t * pObj ) +{ + Llb_Grp_t * p; + assert( pObj->fMarkA == 1 ); + // derive group + p = Llb_ManGroupAlloc( pMan ); + Vec_PtrPush( p->vOuts, pObj ); + Aig_ManIncrementTravId( pMan->pAig ); + if ( Aig_ObjIsPo(pObj) ) + Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin0(pObj), p->vIns ); + else + { + Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin0(pObj), p->vIns ); + Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin1(pObj), p->vIns ); + } + // derive internal objects + assert( p->vNodes == NULL ); + p->vNodes = Llb_ManGroupCollect( p ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Grp_t * Llb_ManGroupCreateFirst( Llb_Man_t * pMan ) +{ + Llb_Grp_t * p; + Aig_Obj_t * pObj; + int i; + p = Llb_ManGroupAlloc( pMan ); + Saig_ManForEachLo( pMan->pAig, pObj, i ) + Vec_PtrPush( p->vOuts, pObj ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Grp_t * Llb_ManGroupCreateLast( Llb_Man_t * pMan ) +{ + Llb_Grp_t * p; + Aig_Obj_t * pObj; + int i; + p = Llb_ManGroupAlloc( pMan ); + Saig_ManForEachLi( pMan->pAig, pObj, i ) + Vec_PtrPush( p->vIns, pObj ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Grp_t * Llb_ManGroupsCombine( Llb_Grp_t * p1, Llb_Grp_t * p2 ) +{ + Llb_Grp_t * p; + Aig_Obj_t * pObj; + int i; + p = Llb_ManGroupAlloc( p1->pMan ); + // create inputs + Vec_PtrForEachEntry( Aig_Obj_t *, p1->vIns, pObj, i ) + Vec_PtrPush( p->vIns, pObj ); + Vec_PtrForEachEntry( Aig_Obj_t *, p2->vIns, pObj, i ) + Vec_PtrPushUnique( p->vIns, pObj ); + // create outputs + Vec_PtrForEachEntry( Aig_Obj_t *, p1->vOuts, pObj, i ) + Vec_PtrPush( p->vOuts, pObj ); + Vec_PtrForEachEntry( Aig_Obj_t *, p2->vOuts, pObj, i ) + Vec_PtrPushUnique( p->vOuts, pObj ); + + // derive internal objects + assert( p->vNodes == NULL ); + p->vNodes = Llb_ManGroupCollect( p ); + return p; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManGroupMarkNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + if ( Aig_ObjIsTravIdPrevious(p, pObj) ) + { + Aig_ObjSetTravIdCurrent(p, pObj); + return; + } + Aig_ObjSetTravIdCurrent(p, pObj); + assert( Aig_ObjIsNode(pObj) ); + Llb_ManGroupMarkNodes_rec( p, Aig_ObjFanin0(pObj) ); + Llb_ManGroupMarkNodes_rec( p, Aig_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Creates group from two cuts derived by the flow computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Grp_t * Llb_ManGroupCreateFromCuts( Llb_Man_t * pMan, Vec_Int_t * vCut1, Vec_Int_t * vCut2 ) +{ + Llb_Grp_t * p; + Aig_Obj_t * pObj; + int i; + p = Llb_ManGroupAlloc( pMan ); + + // mark Cut1 + Aig_ManIncrementTravId( pMan->pAig ); + Aig_ManForEachNodeVec( pMan->pAig, vCut1, pObj, i ) + Aig_ObjSetTravIdCurrent( pMan->pAig, pObj ); + // collect unmarked Cut2 + Aig_ManForEachNodeVec( pMan->pAig, vCut2, pObj, i ) + if ( !Aig_ObjIsTravIdCurrent( pMan->pAig, pObj ) ) + Vec_PtrPush( p->vOuts, pObj ); + + // mark nodes reachable from Cut2 + Aig_ManIncrementTravId( pMan->pAig ); + Aig_ManForEachNodeVec( pMan->pAig, vCut2, pObj, i ) + Llb_ManGroupMarkNodes_rec( pMan->pAig, pObj ); + // collect marked Cut1 + Aig_ManForEachNodeVec( pMan->pAig, vCut1, pObj, i ) + if ( Aig_ObjIsTravIdCurrent( pMan->pAig, pObj ) ) + Vec_PtrPush( p->vIns, pObj ); + + // derive internal objects + assert( p->vNodes == NULL ); + p->vNodes = Llb_ManGroupCollect( p ); + return p; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrepareGroups( Llb_Man_t * pMan ) +{ + Aig_Obj_t * pObj; + int i; + assert( pMan->vGroups == NULL ); + pMan->vGroups = Vec_PtrAlloc( 1000 ); + Llb_ManGroupCreateFirst( pMan ); + Aig_ManForEachNode( pMan->pAig, pObj, i ) + { + if ( pObj->fMarkA ) + Llb_ManGroupCreate( pMan, pObj ); + } + Saig_ManForEachLi( pMan->pAig, pObj, i ) + { + if ( pObj->fMarkA ) + Llb_ManGroupCreate( pMan, pObj ); + } + Llb_ManGroupCreateLast( pMan ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrintSpan( Llb_Man_t * p ) +{ + Llb_Grp_t * pGroup; + Aig_Obj_t * pVar; + int i, k, Span = 0, SpanMax = 0; + Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGroup, i ) + { + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) + if ( Vec_IntEntry(p->vVarBegs, pVar->Id) == i ) + Span++; + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) + if ( Vec_IntEntry(p->vVarBegs, pVar->Id) == i ) + Span++; + + SpanMax = ABC_MAX( SpanMax, Span ); +printf( "%d ", Span ); + + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) + if ( Vec_IntEntry(p->vVarEnds, pVar->Id) == i ) + Span--; + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) + if ( Vec_IntEntry(p->vVarEnds, pVar->Id) == i ) + Span--; + } +printf( "\n" ); +printf( "Max = %d\n", SpanMax ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManGroupHasVar( Llb_Man_t * p, int iGroup, int iVar ) +{ + Llb_Grp_t * pGroup = (Llb_Grp_t *)Vec_PtrEntry( p->vGroups, iGroup ); + Aig_Obj_t * pObj; + int i; + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) + if ( pObj->Id == iVar ) + return 1; + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + if ( pObj->Id == iVar ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrintHisto( Llb_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, k; + Aig_ManForEachObj( p->pAig, pObj, i ) + { + if ( Vec_IntEntry(p->vObj2Var, i) < 0 ) + continue; + printf( "%3d :", i ); + for ( k = 0; k < Vec_IntEntry(p->vVarBegs, i); k++ ) + printf( " " ); + for ( ; k <= Vec_IntEntry(p->vVarEnds, i); k++ ) + printf( "%c", Llb_ManGroupHasVar(p, k, i)? '*':'-' ); + printf( "\n" ); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/aig/llb/llb1Hint.c b/src/aig/llb/llb1Hint.c new file mode 100644 index 00000000..d8ffecd3 --- /dev/null +++ b/src/aig/llb/llb1Hint.c @@ -0,0 +1,226 @@ +/**CFile**************************************************************** + + FileName [llb1Hint.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Cofactors the circuit w.r.t. the high-fanout variables.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Hint.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns CI index with the largest number of fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManMaxFanoutCi( Aig_Man_t * pAig ) +{ + Aig_Obj_t * pObj; + int i, WeightMax = -ABC_INFINITY, iInput = -1; + Aig_ManForEachPi( pAig, pObj, i ) + if ( WeightMax < Aig_ObjRefs(pObj) ) + { + WeightMax = Aig_ObjRefs(pObj); + iInput = i; + } + assert( iInput >= 0 ); + return iInput; +} + +/**Function************************************************************* + + Synopsis [Derives AIG whose PI is substituted by a constant.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Llb_ManPerformHints( Aig_Man_t * pAig, int nHintDepth ) +{ + Aig_Man_t * pNew, * pTemp; + int i, iInput; + pNew = Aig_ManDupDfs( pAig ); + for ( i = 0; i < nHintDepth; i++ ) + { + iInput = Llb_ManMaxFanoutCi( pNew ); + Abc_Print( 1, "%d %3d\n", i, iInput ); + pNew = Aig_ManDupCof( pTemp = pNew, iInput, 1 ); + Aig_ManStop( pTemp ); + } + return pNew; +} + +/**Function************************************************************* + + Synopsis [Returns CI index with the largest number of fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_ManCollectHighFanoutObjects( Aig_Man_t * pAig, int nCandMax, int fCisOnly ) +{ + Vec_Int_t * vFanouts, * vResult; + Aig_Obj_t * pObj; + int i, fChanges, PivotValue; +// int Entry; + // collect fanout counts + vFanouts = Vec_IntAlloc( 100 ); + Aig_ManForEachObj( pAig, pObj, i ) + { +// if ( !Aig_ObjIsPi(pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) + if ( !Saig_ObjIsLo(pAig,pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) + continue; + Vec_IntPush( vFanouts, Aig_ObjRefs(pObj) ); + } + Vec_IntSort( vFanouts, 1 ); + // pick the separator + nCandMax = ABC_MIN( nCandMax, Vec_IntSize(vFanouts) - 1 ); + PivotValue = Vec_IntEntry( vFanouts, nCandMax ); + Vec_IntFree( vFanouts ); + // collect obj satisfying the constraints + vResult = Vec_IntAlloc( 100 ); + Aig_ManForEachObj( pAig, pObj, i ) + { +// if ( !Aig_ObjIsPi(pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) + if ( !Saig_ObjIsLo(pAig,pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) + continue; + if ( Aig_ObjRefs(pObj) < PivotValue ) + continue; + Vec_IntPush( vResult, Aig_ObjId(pObj) ); + } + assert( Vec_IntSize(vResult) >= nCandMax ); + // order in the decreasing order of fanouts + do + { + fChanges = 0; + for ( i = 0; i < Vec_IntSize(vResult) - 1; i++ ) + if ( Aig_ObjRefs(Aig_ManObj(pAig, Vec_IntEntry(vResult, i))) < + Aig_ObjRefs(Aig_ManObj(pAig, Vec_IntEntry(vResult, i+1))) ) + { + int Temp = Vec_IntEntry( vResult, i ); + Vec_IntWriteEntry( vResult, i, Vec_IntEntry(vResult, i+1) ); + Vec_IntWriteEntry( vResult, i+1, Temp ); + fChanges = 1; + } + } + while ( fChanges ); +/* + Vec_IntForEachEntry( vResult, Entry, i ) + printf( "%d ", Aig_ObjRefs(Aig_ManObj(pAig, Entry)) ); +printf( "\n" ); +*/ + return vResult; +} + +/**Function************************************************************* + + Synopsis [Derives AIG whose PI is substituted by a constant.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManModelCheckAigWithHints( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars ) +{ + DdManager * ddGlo = NULL; + Vec_Int_t * vHints; + Vec_Int_t * vHFCands; + int i, Entry, RetValue = -1; + int clk = clock(); + assert( pPars->nHintDepth > 0 ); +/* + // perform reachability without hints + RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, NULL, NULL ); + if ( RetValue >= 0 ) + return RetValue; +*/ + // create hints representation + vHFCands = Llb_ManCollectHighFanoutObjects( pAigGlo, pPars->nHintDepth+pPars->HintFirst, 1 ); + vHints = Vec_IntStartFull( Aig_ManObjNumMax(pAigGlo) ); + // add one hint at a time till the problem is solved + Vec_IntForEachEntryStart( vHFCands, Entry, i, pPars->HintFirst ) + { + Vec_IntWriteEntry( vHints, Entry, 1 ); // change to 1 to start from zero cof!!! + // solve under hints + RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, vHints, &ddGlo ); + if ( RetValue == 0 ) + goto Finish; + if ( RetValue == 1 ) + break; + } + if ( RetValue == -1 ) + goto Finish; + // undo the hints one at a time + for ( ; i >= pPars->HintFirst; i-- ) + { + Entry = Vec_IntEntry( vHFCands, i ); + Vec_IntWriteEntry( vHints, Entry, -1 ); + // solve under relaxed hints + RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, vHints, &ddGlo ); + if ( RetValue == 0 ) + goto Finish; + if ( RetValue == 1 ) + continue; + break; + } +Finish: + if ( ddGlo ) + { + if ( ddGlo->bFunc ) + Cudd_RecursiveDeref( ddGlo, ddGlo->bFunc ); + Extra_StopManager( ddGlo ); + } + Vec_IntFreeP( &vHFCands ); + Vec_IntFreeP( &vHints ); + if ( pPars->fVerbose ) + Abc_PrintTime( 1, "Total runtime", clock() - clk ); + return RetValue; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/aig/llb/llb1Man.c b/src/aig/llb/llb1Man.c new file mode 100644 index 00000000..d9c13a76 --- /dev/null +++ b/src/aig/llb/llb1Man.c @@ -0,0 +1,189 @@ +/**CFile**************************************************************** + + FileName [llb1Man.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Reachability manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Man.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrepareVarMap( Llb_Man_t * p ) +{ + Aig_Obj_t * pObjLi, * pObjLo; + int i, iVarLi, iVarLo; + assert( p->vNs2Glo == NULL ); + assert( p->vGlo2Cs == NULL ); + p->vNs2Glo = Vec_IntStartFull( Vec_IntSize(p->vVar2Obj) ); + p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); + Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) + { + iVarLi = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLi)); + iVarLo = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLo)); + assert( iVarLi >= 0 && iVarLi < Vec_IntSize(p->vVar2Obj) ); + assert( iVarLo >= 0 && iVarLo < Vec_IntSize(p->vVar2Obj) ); + Vec_IntWriteEntry( p->vNs2Glo, iVarLi, i ); + Vec_IntWriteEntry( p->vGlo2Cs, i, iVarLo ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrepareVarLimits( Llb_Man_t * p ) +{ + Llb_Grp_t * pGroup; + Aig_Obj_t * pVar; + int i, k; + assert( p->vVarBegs == NULL ); + assert( p->vVarEnds == NULL ); + p->vVarEnds = Vec_IntStart( Aig_ManObjNumMax(p->pAig) ); + p->vVarBegs = Vec_IntStart( Aig_ManObjNumMax(p->pAig) ); + Vec_IntFill( p->vVarBegs, Aig_ManObjNumMax(p->pAig), p->pMatrix->nCols ); + + for ( i = 0; i < p->pMatrix->nCols; i++ ) + { + pGroup = p->pMatrix->pColGrps[i]; + + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) + if ( Vec_IntEntry(p->vVarBegs, pVar->Id) > i ) + Vec_IntWriteEntry( p->vVarBegs, pVar->Id, i ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) + if ( Vec_IntEntry(p->vVarBegs, pVar->Id) > i ) + Vec_IntWriteEntry( p->vVarBegs, pVar->Id, i ); + + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) + if ( Vec_IntEntry(p->vVarEnds, pVar->Id) < i ) + Vec_IntWriteEntry( p->vVarEnds, pVar->Id, i ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) + if ( Vec_IntEntry(p->vVarEnds, pVar->Id) < i ) + Vec_IntWriteEntry( p->vVarEnds, pVar->Id, i ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManStop( Llb_Man_t * p ) +{ + Llb_Grp_t * pGrp; + int i; + +// Vec_IntFreeP( &p->vMem ); +// Vec_PtrFreeP( &p->vTops ); +// Vec_PtrFreeP( &p->vBots ); +// Vec_VecFreeP( (Vec_Vec_t **)&p->vCuts ); + + if ( p->pMatrix ) + Llb_MtrFree( p->pMatrix ); + Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGrp, i ) + Llb_ManGroupStop( pGrp ); + Vec_PtrFreeP( &p->vGroups ); + Vec_IntFreeP( &p->vVar2Obj ); + Vec_IntFreeP( &p->vObj2Var ); + Vec_IntFreeP( &p->vVarBegs ); + Vec_IntFreeP( &p->vVarEnds ); + Vec_IntFreeP( &p->vNs2Glo ); + Vec_IntFreeP( &p->vGlo2Cs ); +// Vec_IntFreeP( &p->vHints ); + if ( p->dd ) + { + Extra_StopManager( p->dd ); + } + if ( p->ddG ) + { + if ( p->ddG->bFunc ) + Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc ); + Extra_StopManager( p->ddG ); + } + Aig_ManStop( p->pAig ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Man_t * Llb_ManStart( Aig_Man_t * pAigGlo, Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) +{ + Llb_Man_t * p; + Aig_ManCleanMarkA( pAig ); + p = ABC_CALLOC( Llb_Man_t, 1 ); + p->pAigGlo = pAigGlo; + p->pPars = pPars; + p->pAig = pAig; + p->vVar2Obj = Llb_ManMarkPivotNodes( p->pAig, pPars->fUsePivots ); + p->vObj2Var = Vec_IntInvert( p->vVar2Obj, -1 ); + Llb_ManPrepareVarMap( p ); + Llb_ManPrepareGroups( p ); + Aig_ManCleanMarkA( pAig ); + p->pMatrix = Llb_MtrCreate( p ); + p->pMatrix->pMan = p; + return p; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/aig/llb/llb1Matrix.c b/src/aig/llb/llb1Matrix.c new file mode 100644 index 00000000..7aa9c744 --- /dev/null +++ b/src/aig/llb/llb1Matrix.c @@ -0,0 +1,430 @@ +/**CFile**************************************************************** + + FileName [llb1Matrix.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Partition clustering as a matrix problem.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Matrix.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// 0123 nCols +// +---------------------> +// pi 0 | 111 row0 pRowSums[0] +// pi 1 | 1 11 row1 pRowSums[1] +// pi 2 | 1 11 row2 pRowSums[2] +// CS |1 1 +// CS |1 111 +// CS |111 111 +// int | 11111 +// int | 111 +// int | 111 +// int | 111 +// NS | 11 11 +// NS | 11 1 +// NS | 111 +// nRows | +// v +// cccc pColSums[0] +// oooo pColSums[1] +// llll pColSums[2] +// 0123 pColSums[3] + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Verify columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrVerifyRowsAll( Llb_Mtr_t * p ) +{ + int iRow, iCol, Counter; + for ( iCol = 0; iCol < p->nCols; iCol++ ) + { + Counter = 0; + for ( iRow = 0; iRow < p->nRows; iRow++ ) + if ( p->pMatrix[iCol][iRow] == 1 ) + Counter++; + assert( Counter == p->pColSums[iCol] ); + } +} + +/**Function************************************************************* + + Synopsis [Verify columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrVerifyColumnsAll( Llb_Mtr_t * p ) +{ + int iRow, iCol, Counter; + for ( iRow = 0; iRow < p->nRows; iRow++ ) + { + Counter = 0; + for ( iCol = 0; iCol < p->nCols; iCol++ ) + if ( p->pMatrix[iCol][iRow] == 1 ) + Counter++; + assert( Counter == p->pRowSums[iRow] ); + } +} + +/**Function************************************************************* + + Synopsis [Verify columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrVerifyMatrix( Llb_Mtr_t * p ) +{ + Llb_MtrVerifyRowsAll( p ); + Llb_MtrVerifyColumnsAll( p ); +} + +/**Function************************************************************* + + Synopsis [Sort variables in the order of removal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Llb_MtrFindVarOrder( Llb_Mtr_t * p ) +{ + int * pOrder, * pLast; + int i, k, fChanges, Temp; + pOrder = ABC_CALLOC( int, p->nRows ); + pLast = ABC_CALLOC( int, p->nRows ); + for ( i = 0; i < p->nRows; i++ ) + { + pOrder[i] = i; + for ( k = p->nCols - 1; k >= 0; k-- ) + if ( p->pMatrix[k][i] ) + { + pLast[i] = k; + break; + } + } + do + { + fChanges = 0; + for ( i = 0; i < p->nRows - 1; i++ ) + if ( pLast[i] > pLast[i+1] ) + { + Temp = pOrder[i]; + pOrder[i] = pOrder[i+1]; + pOrder[i+1] = Temp; + + Temp = pLast[i]; + pLast[i] = pLast[i+1]; + pLast[i+1] = Temp; + + fChanges = 1; + } + } + while ( fChanges ); + ABC_FREE( pLast ); + return pOrder; +} + +/**Function************************************************************* + + Synopsis [Returns type of a variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Llb_MtrVarName( Llb_Mtr_t * p, int iVar ) +{ + static char Buffer[10]; + if ( iVar < p->nPis ) + strcpy( Buffer, "pi" ); + else if ( iVar < p->nPis + p->nFfs ) + strcpy( Buffer, "CS" ); + else if ( iVar >= p->nRows - p->nFfs ) + strcpy( Buffer, "NS" ); + else + strcpy( Buffer, "int" ); + return Buffer; +} + +/**Function************************************************************* + + Synopsis [Creates one column with vars in the array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrPrint( Llb_Mtr_t * p, int fOrder ) +{ + int * pOrder = NULL; + int i, iRow, iCol; + if ( fOrder ) + pOrder = Llb_MtrFindVarOrder( p ); + for ( i = 0; i < p->nRows; i++ ) + { + iRow = pOrder ? pOrder[i] : i; + printf( "%3d : ", iRow ); + printf( "%3d ", p->pRowSums[iRow] ); + printf( "%3s ", Llb_MtrVarName(p, iRow) ); + for ( iCol = 0; iCol < p->nCols; iCol++ ) + printf( "%c", p->pMatrix[iCol][iRow] ? '*' : ' ' ); + printf( "\n" ); + } + ABC_FREE( pOrder ); +} + +/**Function************************************************************* + + Synopsis [Verify columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrPrintMatrixStats( Llb_Mtr_t * p ) +{ + int iVar, iGrp, iGrp1, iGrp2, Span = 0, nCutSize = 0, nCutSizeMax = 0; + int * pGrp1 = ABC_CALLOC( int, p->nRows ); + int * pGrp2 = ABC_CALLOC( int, p->nRows ); + for ( iVar = 0; iVar < p->nRows; iVar++ ) + { + if ( p->pRowSums[iVar] == 0 ) + continue; + for ( iGrp1 = 0; iGrp1 < p->nCols; iGrp1++ ) + if ( p->pMatrix[iGrp1][iVar] == 1 ) + break; + for ( iGrp2 = p->nCols - 1; iGrp2 >= 0; iGrp2-- ) + if ( p->pMatrix[iGrp2][iVar] == 1 ) + break; + assert( iGrp1 <= iGrp2 ); + pGrp1[iVar] = iGrp1; + pGrp2[iVar] = iGrp2; + Span += iGrp2 - iGrp1; + } + // compute span + for ( iGrp = 0; iGrp < p->nCols; iGrp++ ) + { + for ( iVar = 0; iVar < p->nRows; iVar++ ) + if ( pGrp1[iVar] == iGrp ) + nCutSize++; + if ( nCutSizeMax < nCutSize ) + nCutSizeMax = nCutSize; + for ( iVar = 0; iVar < p->nRows; iVar++ ) + if ( pGrp2[iVar] == iGrp ) + nCutSize--; + } + ABC_FREE( pGrp1 ); + ABC_FREE( pGrp2 ); + printf( "[%4d x %4d] Life-span =%6.2f Max-cut =%5d\n", + p->nCols, p->nRows, 1.0*Span/p->nRows, nCutSizeMax ); + if ( nCutSize ) + Abc_Print( -1, "Cut size is not zero (%d).\n", nCutSize ); +} + + + +/**Function************************************************************* + + Synopsis [Starts the matrix representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Mtr_t * Llb_MtrAlloc( int nPis, int nFfs, int nCols, int nRows ) +{ + Llb_Mtr_t * p; + int i; + p = ABC_CALLOC( Llb_Mtr_t, 1 ); + p->nPis = nPis; + p->nFfs = nFfs; + p->nRows = nRows; + p->nCols = nCols; + p->pRowSums = ABC_CALLOC( int, nRows ); + p->pColSums = ABC_CALLOC( int, nCols ); + p->pColGrps = ABC_CALLOC( Llb_Grp_t *, nCols ); + p->pMatrix = ABC_CALLOC( char *, nCols ); + for ( i = 0; i < nCols; i++ ) + p->pMatrix[i] = ABC_CALLOC( char, nRows ); + // partial product + p->pProdVars = ABC_CALLOC( char, nRows ); // variables in the partial product + p->pProdNums = ABC_CALLOC( int, nRows ); // var counts in the remaining partitions + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the matrix representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrFree( Llb_Mtr_t * p ) +{ + int i; + ABC_FREE( p->pProdVars ); + ABC_FREE( p->pProdNums ); + for ( i = 0; i < p->nCols; i++ ) + ABC_FREE( p->pMatrix[i] ); + ABC_FREE( p->pRowSums ); + ABC_FREE( p->pColSums ); + ABC_FREE( p->pMatrix ); + ABC_FREE( p->pColGrps ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Creates one column with vars in the array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrAddColumn( Llb_Mtr_t * p, Llb_Grp_t * pGrp ) +{ + Aig_Obj_t * pVar; + int i, iRow, iCol = pGrp->Id; + assert( iCol >= 0 && iCol < p->nCols ); + p->pColGrps[iCol] = pGrp; + Vec_PtrForEachEntry( Aig_Obj_t *, pGrp->vIns, pVar, i ) + { + iRow = Vec_IntEntry( pGrp->pMan->vObj2Var, Aig_ObjId(pVar) ); + assert( iRow >= 0 && iRow < p->nRows ); + p->pMatrix[iCol][iRow] = 1; + p->pColSums[iCol]++; + p->pRowSums[iRow]++; + } + Vec_PtrForEachEntry( Aig_Obj_t *, pGrp->vOuts, pVar, i ) + { + iRow = Vec_IntEntry( pGrp->pMan->vObj2Var, Aig_ObjId(pVar) ); + assert( iRow >= 0 && iRow < p->nRows ); + p->pMatrix[iCol][iRow] = 1; + p->pColSums[iCol]++; + p->pRowSums[iRow]++; + } +} + +/**Function************************************************************* + + Synopsis [Matrix reduce.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrRemoveSingletonRows( Llb_Mtr_t * p ) +{ + int i, k; + for ( i = 0; i < p->nRows; i++ ) + if ( p->pRowSums[i] < 2 ) + { + p->pRowSums[i] = 0; + for ( k = 0; k < p->nCols; k++ ) + { + if ( p->pMatrix[k][i] == 1 ) + { + p->pMatrix[k][i] = 0; + p->pColSums[k]--; + } + } + } +} + +/**Function************************************************************* + + Synopsis [Matrix reduce.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Mtr_t * Llb_MtrCreate( Llb_Man_t * p ) +{ + Llb_Mtr_t * pMatrix; + Llb_Grp_t * pGroup; + int i; + pMatrix = Llb_MtrAlloc( Saig_ManPiNum(p->pAig), Saig_ManRegNum(p->pAig), + Vec_PtrSize(p->vGroups), Vec_IntSize(p->vVar2Obj) ); + Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGroup, i ) + Llb_MtrAddColumn( pMatrix, pGroup ); +// Llb_MtrRemoveSingletonRows( pMatrix ); + return pMatrix; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/aig/llb/llb1Pivot.c b/src/aig/llb/llb1Pivot.c new file mode 100644 index 00000000..d42bf659 --- /dev/null +++ b/src/aig/llb/llb1Pivot.c @@ -0,0 +1,254 @@ +/**CFile**************************************************************** + + FileName [llb1Pivot.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Determining pivot variables.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Pivot.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManTracePaths_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pPivot ) +{ + Aig_Obj_t * pFanout; + int k, iFan; + if ( Aig_ObjIsTravIdPrevious(p, pObj) ) + return 0; + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return 1; + if ( Saig_ObjIsLi(p, pObj) ) + return 0; + if ( Saig_ObjIsPo(p, pObj) ) + return 0; + if ( pObj == pPivot ) + return 1; + assert( Aig_ObjIsCand(pObj) ); + Aig_ObjForEachFanout( p, pObj, pFanout, iFan, k ) + if ( !Llb_ManTracePaths_rec( p, pFanout, pPivot ) ) + { + Aig_ObjSetTravIdPrevious(p, pObj); + return 0; + } + Aig_ObjSetTravIdCurrent(p, pObj); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManTracePaths( Aig_Man_t * p, Aig_Obj_t * pPivot ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + Aig_ManIncrementTravId( p ); // prev = visited with path to LI (value 0) + Aig_ManIncrementTravId( p ); // cur = visited w/o path to LI (value 1) + Saig_ManForEachLo( p, pObj, i ) + Counter += Llb_ManTracePaths_rec( p, pObj, pPivot ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManTestCuts( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, Count; + Aig_ManFanoutStart( p ); + Aig_ManForEachNode( p, pObj, i ) + { + if ( Aig_ObjRefs(pObj) <= 1 ) + continue; + Count = Llb_ManTracePaths( p, pObj ); + printf( "Obj =%5d. Lev =%3d. Fanout =%5d. Count = %3d.\n", + i, Aig_ObjLevel(pObj), Aig_ObjRefs(pObj), Count ); + } + Aig_ManFanoutStop( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManLabelLiCones_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + if ( pObj->fMarkB ) + return; + pObj->fMarkB = 1; + assert( Aig_ObjIsNode(pObj) ); + Llb_ManLabelLiCones_rec( p, Aig_ObjFanin0(pObj) ); + Llb_ManLabelLiCones_rec( p, Aig_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Determine starting cut-points.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManLabelLiCones( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + // mark const and PIs + Aig_ManConst1(p)->fMarkB = 1; + Aig_ManForEachPi( p, pObj, i ) + pObj->fMarkB = 1; + // mark cones + Saig_ManForEachLi( p, pObj, i ) + Llb_ManLabelLiCones_rec( p, Aig_ObjFanin0(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Determine starting cut-points.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManMarkInternalPivots( Aig_Man_t * p ) +{ + Vec_Ptr_t * vMuxes; + Aig_Obj_t * pObj; + int i, Counter = 0; + + // remove refs due to MUXes + vMuxes = Aig_ManMuxesCollect( p ); + Aig_ManMuxesDeref( p, vMuxes ); + + // mark nodes feeding into LIs + Aig_ManCleanMarkB( p ); + Llb_ManLabelLiCones( p ); + + // mark internal nodes + Aig_ManFanoutStart( p ); + Aig_ManForEachNode( p, pObj, i ) + if ( pObj->fMarkB && pObj->nRefs > 1 ) + { + if ( Llb_ManTracePaths(p, pObj) > 0 ) + pObj->fMarkA = 1; + Counter++; + } + Aig_ManFanoutStop( p ); +// printf( "TracePath tried = %d.\n", Counter ); + + // mark nodes feeding into LIs + Aig_ManCleanMarkB( p ); + + // add refs due to MUXes + Aig_ManMuxesRef( p, vMuxes ); + Vec_PtrFree( vMuxes ); +} + +/**Function************************************************************* + + Synopsis [Determine starting cut-points.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_ManMarkPivotNodes( Aig_Man_t * p, int fUseInternal ) +{ + Vec_Int_t * vVar2Obj; + Aig_Obj_t * pObj; + int i; + // mark inputs/outputs + Aig_ManForEachPi( p, pObj, i ) + pObj->fMarkA = 1; + Saig_ManForEachLi( p, pObj, i ) + pObj->fMarkA = 1; + + // mark internal pivot nodes + if ( fUseInternal ) + Llb_ManMarkInternalPivots( p ); + + // assign variable numbers + Aig_ManConst1(p)->fMarkA = 0; + vVar2Obj = Vec_IntAlloc( 100 ); + Aig_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; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/aig/llb/llb1Reach.c b/src/aig/llb/llb1Reach.c new file mode 100644 index 00000000..45dec7ab --- /dev/null +++ b/src/aig/llb/llb1Reach.c @@ -0,0 +1,629 @@ +/**CFile**************************************************************** + + FileName [llb1Reach.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Reachability analysis.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Reach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" +#include "extra.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Derives global BDD for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManConstructOutBdd( Aig_Man_t * pAig, Aig_Obj_t * pNode, DdManager * dd ) +{ + DdNode * bBdd0, * bBdd1, * bFunc; + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + if ( Aig_ObjFanin0(pNode) == Aig_ManConst1(pAig) ) + return Cudd_NotCond( Cudd_ReadOne(dd), Aig_ObjFaninC0(pNode) ); + vNodes = Aig_ManDfsNodes( pAig, &pNode, 1 ); + assert( Vec_PtrSize(vNodes) > 0 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) ) + continue; + bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); + pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData ); + } + bFunc = (DdNode *)pObj->pData; Cudd_Ref( bFunc ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) ) + continue; + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + } + Vec_PtrFree( vNodes ); + if ( Aig_ObjIsPo(pNode) ) + bFunc = Cudd_NotCond( bFunc, Aig_ObjFaninC0(pNode) ); + Cudd_Deref( bFunc ); + return bFunc; +} + +/**Function************************************************************* + + Synopsis [Derives BDD for the group.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManConstructGroupBdd( Llb_Man_t * p, Llb_Grp_t * pGroup ) +{ + Aig_Obj_t * pObj; + DdNode * bBdd0, * bBdd1, * bRes, * bXor, * bTemp; + int i; + Aig_ManConst1(p->pAig)->pData = Cudd_ReadOne( p->dd ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) + pObj->pData = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vNodes, pObj, i ) + { + bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); + pObj->pData = Cudd_bddAnd( p->dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData ); + } + bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + { + if ( Aig_ObjIsPo(pObj) ) + bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + else + bBdd0 = (DdNode *)pObj->pData; + bBdd1 = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + bXor = Cudd_bddXor( p->dd, bBdd0, bBdd1 ); Cudd_Ref( bXor ); + bRes = Cudd_bddAnd( p->dd, bTemp = bRes, Cudd_Not(bXor) ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bXor ); + } + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vNodes, pObj, i ) + Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData ); + Cudd_Deref( bRes ); + return bRes; +} + +/**Function************************************************************* + + Synopsis [Derives quantification cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManConstructQuantCubeIntern( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace ) +{ + Aig_Obj_t * pObj; + DdNode * bRes, * bTemp, * bVar; + int i, iGroupFirst, iGroupLast; + bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) + { + iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); + iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); + assert( iGroupFirst <= iGroupLast ); + if ( iGroupFirst < iGroupLast ) + continue; + bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + { + iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); + iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); + assert( iGroupFirst <= iGroupLast ); + if ( iGroupFirst < iGroupLast ) + continue; + bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Cudd_Deref( bRes ); + return bRes; +} + +/**Function************************************************************* + + Synopsis [Derives quantification cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManConstructQuantCube( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace ) +{ + Aig_Obj_t * pObj; + DdNode * bRes, * bTemp, * bVar; + int i, iGroupLast; + bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) + { + iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); + assert( iGroupLast >= iGrpPlace ); + if ( iGroupLast > iGrpPlace ) + continue; + bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + { + iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); + assert( iGroupLast >= iGrpPlace ); + if ( iGroupLast > iGrpPlace ) + continue; + bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Cudd_Deref( bRes ); + return bRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManComputeInitState( Llb_Man_t * p, DdManager * dd ) +{ + Aig_Obj_t * pObj; + DdNode * bRes, * bVar, * bTemp; + int i, iVar; + bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); + Saig_ManForEachLo( p->pAig, pObj, i ) + { + iVar = (dd == p->ddG) ? i : Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)); + bVar = Cudd_bddIthVar( dd, iVar ); + bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bRes ); + return bRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManComputeImage( Llb_Man_t * p, DdNode * bInit ) +{ + int fCheckSupport = 0; + Llb_Grp_t * pGroup; + DdNode * bImage, * bGroup, * bCube, * bTemp; + int i; + bImage = bInit; Cudd_Ref( bImage ); + for ( i = 1; i < p->pMatrix->nCols-1; i++ ) + { + // compute group BDD + pGroup = p->pMatrix->pColGrps[i]; + bGroup = Llb_ManConstructGroupBdd( p, pGroup ); Cudd_Ref( bGroup ); + // quantify variables appearing only in this group + bCube = Llb_ManConstructQuantCubeIntern( p, pGroup, i ); Cudd_Ref( bCube ); + bGroup = Cudd_bddExistAbstract( p->dd, bTemp = bGroup, bCube ); Cudd_Ref( bGroup ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bCube ); + // perform partial product + bCube = Llb_ManConstructQuantCube( p, pGroup, i ); Cudd_Ref( bCube ); + bImage = Cudd_bddAndAbstract( p->dd, bTemp = bImage, bGroup, bCube ); Cudd_Ref( bImage ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bGroup ); + Cudd_RecursiveDeref( p->dd, bCube ); + // chech runtime + if ( p->pPars->TimeTarget && clock() >= p->pPars->TimeTarget ) + { + Cudd_RecursiveDeref( p->dd, bImage ); + return NULL; + } + } + + // make sure image depends on next state vars + if ( fCheckSupport ) + { + bCube = Cudd_Support( p->dd, bImage ); Cudd_Ref( bCube ); + for ( bTemp = bCube; bTemp != p->dd->one; bTemp = cuddT(bTemp) ) + { + int ObjId = Vec_IntEntry( p->vVar2Obj, bTemp->index ); + Aig_Obj_t * pObj = Aig_ManObj( p->pAig, ObjId ); + if ( !Saig_ObjIsLi(p->pAig, pObj) ) + printf( "Var %d assigned to obj %d that is not LI\n", bTemp->index, ObjId ); + } + Cudd_RecursiveDeref( p->dd, bCube ); + } + Cudd_Deref( bImage ); + return bImage; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManCreateConstraints( Llb_Man_t * p, Vec_Int_t * vHints, int fUseNsVars ) +{ + DdNode * bConstr, * bFunc, * bTemp; + Aig_Obj_t * pObj; + int i, Entry; + if ( vHints == NULL ) + return Cudd_ReadOne( p->dd ); + assert( Aig_ManPiNum(p->pAig) == Aig_ManPiNum(p->pAigGlo) ); + // assign const and PI nodes to the original AIG + Aig_ManCleanData( p->pAig ); + Aig_ManConst1( p->pAig )->pData = Cudd_ReadOne( p->dd ); + Saig_ManForEachPi( p->pAig, pObj, i ) + pObj->pData = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var,Aig_ObjId(pObj)) ); + Saig_ManForEachLo( p->pAig, pObj, i ) + { + if ( fUseNsVars ) + Entry = Vec_IntEntry( p->vObj2Var, Aig_ObjId(Saig_ObjLoToLi(p->pAig, pObj)) ); + else + Entry = Vec_IntEntry( p->vObj2Var, Aig_ObjId(pObj) ); + pObj->pData = Cudd_bddIthVar( p->dd, Entry ); + } + // transfer them to the global AIG + Aig_ManCleanData( p->pAigGlo ); + Aig_ManConst1( p->pAigGlo )->pData = Cudd_ReadOne( p->dd ); + Aig_ManForEachPi( p->pAigGlo, pObj, i ) + pObj->pData = Aig_ManPi(p->pAig, i)->pData; + // derive consraints + bConstr = Cudd_ReadOne( p->dd ); Cudd_Ref( bConstr ); + Vec_IntForEachEntry( vHints, Entry, i ) + { + if ( Entry != 0 && Entry != 1 ) + continue; + bFunc = Llb_ManConstructOutBdd( p->pAigGlo, Aig_ManObj(p->pAigGlo, i), p->dd ); Cudd_Ref( bFunc ); + bFunc = Cudd_NotCond( bFunc, Entry ); // restrict to not constraint + // make the product + bConstr = Cudd_bddAnd( p->dd, bTemp = bConstr, bFunc ); Cudd_Ref( bConstr ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bFunc ); + } + Cudd_Deref( bConstr ); + return bConstr; +} + +/**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 [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManReachability( Llb_Man_t * p, Vec_Int_t * vHints, DdManager ** pddGlo ) +{ + int fCheckOutputs = !p->pPars->fSkipOutCheck; + int * pNs2Glo = Vec_IntArray( p->vNs2Glo ); + int * pGlo2Cs = Vec_IntArray( p->vGlo2Cs ); + DdNode * bCurrent, * bReached, * bNext, * bTemp, * bCube; + DdNode * bConstrCs, * bConstrNs; + int clk2, clk = clock(), nIters, nBddSize = 0, iOutFail = -1; + int nThreshold = 10000; + + // compute time to stop + if ( p->pPars->TimeLimit ) + p->pPars->TimeTarget = clock() + p->pPars->TimeLimit * CLOCKS_PER_SEC; + else + p->pPars->TimeTarget = 0; + + // define variable limits + Llb_ManPrepareVarLimits( p ); + + // start the managers + assert( p->dd == NULL ); + assert( p->ddG == NULL ); + p->dd = Cudd_Init( Vec_IntSize(p->vVar2Obj), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + if ( pddGlo && *pddGlo ) + p->ddG = *pddGlo, *pddGlo = NULL; + else + p->ddG = Cudd_Init( Aig_ManRegNum(p->pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + + if ( p->pPars->fReorder ) + { + Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); + Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT ); + } + else + { + Cudd_AutodynDisable( p->dd ); + Cudd_AutodynDisable( p->ddG ); + } + + // derive constraints + bConstrCs = Llb_ManCreateConstraints( p, vHints, 0 ); Cudd_Ref( bConstrCs ); + bConstrNs = Llb_ManCreateConstraints( p, vHints, 1 ); Cudd_Ref( bConstrNs ); +//Extra_bddPrint( p->dd, bConstrCs ); printf( "\n" ); +//Extra_bddPrint( p->dd, bConstrNs ); printf( "\n" ); + + // perform reachability analysis + // compute the starting set of states + if ( p->ddG->bFunc ) + { + bReached = p->ddG->bFunc; p->ddG->bFunc = NULL; + bCurrent = Extra_TransferPermute( p->ddG, p->dd, bReached, pGlo2Cs ); Cudd_Ref( bCurrent ); + } + else + { + bReached = Llb_ManComputeInitState( p, p->ddG ); Cudd_Ref( bReached ); + bCurrent = Llb_ManComputeInitState( p, p->dd ); Cudd_Ref( bCurrent ); + } +//Extra_bddPrintSupport( p->ddG, bReached ); printf( "\n" ); +//Extra_bddPrintSupport( p->dd, bCurrent ); printf( "\n" ); + +//Extra_bddPrintSupport( p->dd, bCurrent ); printf( "\n" ); + for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ ) + { + clk2 = 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->dd, bConstrCs ); bConstrCs = NULL; + Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + + // check outputs + if ( fCheckOutputs ) + { + Aig_Obj_t * pObj; + int i; + Aig_ManConst1( p->pAigGlo )->pData = Cudd_ReadOne( p->dd ); + Aig_ManForEachPi( p->pAig, pObj, i ) + pObj->pData = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var,Aig_ObjId(pObj)) ); + Aig_ManForEachPi( p->pAigGlo, pObj, i ) + pObj->pData = Aig_ManPi(p->pAig, i)->pData; + +//Extra_bddPrintSupport( p->dd, bCurrent ); printf( "\n" ); + for ( iOutFail = 0; iOutFail < Saig_ManPoNum(p->pAig); iOutFail++ ) + { + DdNode * bFunc, * bInter; + bFunc = Llb_ManConstructOutBdd( p->pAigGlo, Aig_ManPo(p->pAigGlo, iOutFail), p->dd ); Cudd_Ref( bFunc ); +//Extra_bddPrint( p->dd, bFunc ); printf( "\n" ); + if ( Cudd_bddLeq( p->dd, bCurrent, Cudd_Not(bFunc) ) ) // no cex + { + Cudd_RecursiveDeref( p->dd, bFunc ); + continue; + } + bInter = Cudd_bddIntersect( p->dd, bCurrent, bFunc ); Cudd_Ref( bInter ); + assert( p->pAig->pSeqModel == NULL ); + p->pAig->pSeqModel = Llb_ManDeriveCex( p, bInter, iOutFail, nIters ); + Cudd_RecursiveDeref( p->dd, bInter ); + Cudd_RecursiveDeref( p->dd, bFunc ); + break; + } + if ( iOutFail < Saig_ManPoNum(p->pAig) ) + { + if ( !p->pPars->fSilent ) + printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump a witness). ", iOutFail, nIters ); + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + p->pPars->iFrame = nIters; + break; + } + } + + // restrict reachable states using constraints + if ( vHints ) + { + bCurrent = Cudd_bddAnd( p->dd, bTemp = bCurrent, bConstrCs ); Cudd_Ref( bCurrent ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + + // quantify variables appearing only in the init state + bCube = Llb_ManConstructQuantCubeIntern( p, (Llb_Grp_t *)Vec_PtrEntry(p->vGroups,0), 0 ); Cudd_Ref( bCube ); + bCurrent = Cudd_bddExistAbstract( p->dd, bTemp = bCurrent, bCube ); Cudd_Ref( bCurrent ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bCube ); + + // compute the next states + bNext = Llb_ManComputeImage( p, bCurrent ); + 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->dd, bConstrCs ); bConstrCs = NULL; + Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bNext ); + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + + // restrict reachable states using constraints + if ( vHints ) + { + bNext = Cudd_bddAnd( p->dd, bTemp = bNext, bConstrNs ); Cudd_Ref( bNext ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } +//Extra_bddPrintSupport( p->dd, bNext ); printf( "\n" ); + + // remap these states into the current state vars + bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pNs2Glo ); Cudd_Ref( bNext ); + Cudd_RecursiveDeref( p->dd, bTemp ); + + // check if there are any new states + if ( Cudd_bddLeq( p->ddG, bNext, bReached ) ) // implication = no new states + { + Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; + break; + } + + // check the BDD size + nBddSize = Cudd_DagSize(bNext); + if ( nBddSize > p->pPars->nBddMax ) + { + Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; + break; + } + + // get the new states + bCurrent = Cudd_bddAnd( p->ddG, bNext, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); + // minimize the new states with the reached states +// bCurrent = Cudd_bddConstrain( p->ddG, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); +// bCurrent = Cudd_bddRestrict( p->ddG, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); +// Cudd_RecursiveDeref( p->ddG, bTemp ); +//printf( "Initial BDD =%7d. Constrained BDD =%7d.\n", Cudd_DagSize(bTemp), Cudd_DagSize(bCurrent) ); + // remap these states into the current state vars + bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs ); Cudd_Ref( bCurrent ); + Cudd_RecursiveDeref( p->ddG, bTemp ); + + // 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->fVerbose ) + { + fprintf( stdout, "F =%5d : ", nIters ); + fprintf( stdout, "Im =%6d ", nBddSize ); + fprintf( stdout, "(%4d %3d) ", Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) ); + fprintf( stdout, "Rea =%6d ", Cudd_DagSize(bReached) ); + fprintf( stdout, "(%4d%4d) ", Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) ); + Abc_PrintTime( 1, "Time", clock() - clk2 ); + } +/* + if ( p->pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); +// Extra_bddPrint( p->ddG, bReached );printf( "\n" ); + fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); + fflush( stdout ); + } +*/ + } + Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; + Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; + if ( bReached == NULL ) + return 0; // reachable +// assert( bCurrent == NULL ); + if ( bCurrent ) + Cudd_RecursiveDeref( p->dd, bCurrent ); + // report the stats + if ( p->pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); + if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) + fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters ); + else + fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters ); + fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); + fflush( stdout ); + } + if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) + { + if ( !p->pPars->fSilent ) + printf( "Verified only for states reachable in %d frames. ", nIters ); + Cudd_RecursiveDeref( p->ddG, bReached ); + return -1; // undecided + } + if ( pddGlo ) + { + assert( p->ddG->bFunc == NULL ); + p->ddG->bFunc = bReached; bReached = NULL; + assert( *pddGlo == NULL ); + *pddGlo = p->ddG; p->ddG = NULL; + } + else + Cudd_RecursiveDeref( p->ddG, bReached ); + if ( !p->pPars->fSilent ) + printf( "The miter is proved unreachable after %d iterations. ", nIters ); + p->pPars->iFrame = nIters - 1; + return 1; // unreachable +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/aig/llb/llb1Sched.c b/src/aig/llb/llb1Sched.c new file mode 100644 index 00000000..6bdae42e --- /dev/null +++ b/src/aig/llb/llb1Sched.c @@ -0,0 +1,257 @@ +/**CFile**************************************************************** + + FileName [llb1Sched.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Partition scheduling algorithm.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Sched.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Swaps two rows.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrSwapColumns( Llb_Mtr_t * p, int iCol1, int iCol2 ) +{ + Llb_Grp_t * pGemp; + char * pTemp; + int iTemp; + assert( iCol1 >= 0 && iCol1 < p->nCols ); + assert( iCol2 >= 0 && iCol2 < p->nCols ); + if ( iCol1 == iCol2 ) + return; + assert( iCol1 != iCol2 ); + // swap col groups + pGemp = p->pColGrps[iCol1]; + p->pColGrps[iCol1] = p->pColGrps[iCol2]; + p->pColGrps[iCol2] = pGemp; + // swap col vectors + pTemp = p->pMatrix[iCol1]; + p->pMatrix[iCol1] = p->pMatrix[iCol2]; + p->pMatrix[iCol2] = pTemp; + // swap col sums + iTemp = p->pColSums[iCol1]; + p->pColSums[iCol1] = p->pColSums[iCol2]; + p->pColSums[iCol2] = iTemp; +} + +/**Function************************************************************* + + Synopsis [Find columns which brings as few vars as possible.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_MtrFindBestColumn( Llb_Mtr_t * p, int iGrpStart ) +{ + int Cost, Cost2, CostBest = ABC_INFINITY, Cost2Best = ABC_INFINITY; + int WeightCur, WeightBest = -ABC_INFINITY, iGrp, iGrpBest = -1; + int k, c, iVar, Counter; + // find partition that reduces partial product as much as possible + for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ ) + { + if ( p->pRowSums[iVar] < 2 ) + continue; + // look at present variables that can be quantified + if ( !(p->pProdVars[iVar] == 1 && p->pProdNums[iVar] == 1) ) + continue; + // check that it appears in one partition only + Counter = 0; + for ( c = iGrpStart; c < p->nCols-1; c++ ) + if ( p->pMatrix[c][iVar] == 1 ) + { + iGrp = c; + Counter++; + } + assert( Counter == 1 ); + if ( Counter != 1 ) + Abc_Print( -1, "Llb_MtrFindBestColumn() Internal error!\n" ); + // find weight of this column + WeightCur = 0; + for ( k = 0; k < p->nRows; k++ ) + { + // increase weight if variable k will be quantified from partial product + if ( p->pProdVars[k] == 1 && p->pMatrix[iGrp][k] == 1 && p->pProdNums[k] == 1 ) + WeightCur += 2; + // decrease weight if variable k will be added to partial product + if ( p->pProdVars[k] == 0 && p->pMatrix[iGrp][k] == 1 ) + WeightCur--; + } + if ( WeightCur > 0 && WeightBest < WeightCur ) + { + WeightBest = WeightCur; + iGrpBest = iGrp; + } + } + if ( iGrpBest >= 0 ) + return iGrpBest; + // could not find the group with any vars to quantify + // select the group that contains as few extra variables as possible + // if there is a tie, select variables that appear in less groups than others + for ( iGrp = iGrpStart; iGrp < p->nCols-1; iGrp++ ) + { + Cost = Cost2 = 0; + for ( k = 0; k < p->nRows; k++ ) + if ( p->pProdVars[k] == 0 && p->pMatrix[iGrp][k] == 1 ) + { + Cost++; + Cost2 += p->pProdNums[k]; + } + if ( CostBest > Cost || + (CostBest == Cost && Cost2 > Cost2Best) ) + { + CostBest = Cost; + Cost2Best = Cost2; + iGrpBest = iGrp; + } + } + return iGrpBest; +} + +/**Function************************************************************* + + Synopsis [Returns the number of variables that will be saved.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrUseSelectedColumn( Llb_Mtr_t * p, int iCol ) +{ + int iVar; + assert( iCol >= 1 && iCol < p->nCols - 1 ); + for ( iVar = 0; iVar < p->nRows; iVar++ ) + { + if ( p->pMatrix[iCol][iVar] == 0 ) + continue; + if ( p->pProdVars[iVar] == 1 && p->pProdNums[iVar] == 1 ) + { + p->pProdVars[iVar] = 0; + p->pProdNums[iVar] = 0; + continue; + } + if ( p->pProdVars[iVar] == 0 ) + { + p->pProdVars[iVar] = 1; + p->pProdNums[iVar] = p->pRowSums[iVar]; + } + p->pProdNums[iVar]--; + assert( p->pProdNums[iVar] >= 0 ); + if ( p->pProdNums[iVar] < 0 ) + Abc_Print( -1, "Llb_MtrUseSelectedColumn() Internal error!\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Verify columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrVerifyColumns( Llb_Mtr_t * p, int iGrpStart ) +{ + int iVar, iGrp, Counter; + for ( iVar = 0; iVar < p->nRows; iVar++ ) + { + if ( p->pProdVars[iVar] == 0 ) + continue; + Counter = 0; + for ( iGrp = iGrpStart; iGrp < p->nCols; iGrp++ ) + if ( p->pMatrix[iGrp][iVar] == 1 ) + Counter++; + assert( Counter == p->pProdNums[iVar] ); + if ( Counter != p->pProdNums[iVar] ) + Abc_Print( -1, "Llb_MtrVerifyColumns(): Internal error.\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Matrix reduce.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrSchedule( Llb_Mtr_t * p ) +{ + int iGrp, iGrpBest, i; + // start partial product + for ( i = 0; i < p->nRows; i++ ) + { + if ( i >= p->nPis && i < p->nPis + p->nFfs ) + { + p->pProdVars[i] = 1; + p->pProdNums[i] = p->pRowSums[i] - 1; + } + else + { + p->pProdVars[i] = 0; + p->pProdNums[i] = p->pRowSums[i]; + } + } + // order the partitions + Llb_MtrVerifyMatrix( p ); + for ( iGrp = 1; iGrp < p->nCols-1; iGrp++ ) + { + Llb_MtrVerifyColumns( p, iGrp ); + iGrpBest = Llb_MtrFindBestColumn( p, iGrp ); + Llb_MtrUseSelectedColumn( p, iGrpBest ); + Llb_MtrSwapColumns( p, iGrp, iGrpBest ); + } + Llb_MtrVerifyMatrix( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/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/llbCluster.c b/src/aig/llb/llbCluster.c deleted file mode 100644 index 1d0153ce..00000000 --- a/src/aig/llb/llbCluster.c +++ /dev/null @@ -1,357 +0,0 @@ -/**CFile**************************************************************** - - FileName [llbCluster.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Clustering algorithm.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llbCluster.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" -#include "extra.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManComputeCommonQuant( Llb_Mtr_t * p, int iCol1, int iCol2 ) -{ - int iVar, Weight = 0; - for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ ) - { - // count each removed variable as 2 - if ( p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 1 && p->pRowSums[iVar] == 2 ) - Weight += 2; - // count each added variale as -1 - else if ( (p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 0) || - (p->pMatrix[iCol1][iVar] == 0 && p->pMatrix[iCol2][iVar] == 1) ) - Weight--; - } - return Weight; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManComputeBestQuant( Llb_Mtr_t * p ) -{ - int i, k, WeightBest = -100000, WeightCur, RetValue = -1; - for ( i = 1; i < p->nCols-1; i++ ) - for ( k = i+1; k < p->nCols-1; k++ ) - { - if ( p->pColSums[i] == 0 || p->pColSums[i] > p->pMan->pPars->nClusterMax ) - continue; - if ( p->pColSums[k] == 0 || p->pColSums[k] > p->pMan->pPars->nClusterMax ) - continue; - - WeightCur = Llb_ManComputeCommonQuant( p, i, k ); - if ( WeightCur <= 0 ) - continue; - if ( WeightBest < WeightCur ) - { - WeightBest = WeightCur; - RetValue = (i << 16) | k; - } - } -// printf( "Choosing best quant Weight %4d\n", WeightCur ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float ** Llb_ManComputeQuant( Llb_Mtr_t * p ) -{ - float ** pCosts; - int i, k; - // alloc and clean - pCosts = (float **)Extra_ArrayAlloc( p->nCols, p->nCols, sizeof(float) ); - for ( i = 0; i < p->nCols; i++ ) - for ( k = 0; k < p->nCols; k++ ) - pCosts[i][i] = 0.0; - // fill up - for ( i = 1; i < p->nCols-1; i++ ) - for ( k = i+1; k < p->nCols-1; k++ ) - pCosts[i][k] = pCosts[k][i] = Llb_ManComputeCommonQuant( p, i, k ); - return pCosts; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Llb_ManComputeCommonAttr( Llb_Mtr_t * p, int iCol1, int iCol2 ) -{ - int iVar, CountComm = 0, CountDiff = 0; - for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ ) - { - if ( p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 1 ) - CountComm++; - else if ( p->pMatrix[iCol1][iVar] == 1 || p->pMatrix[iCol2][iVar] == 1 ) - CountDiff++; - } -/* - printf( "Attr cost for %4d and %4d: %4d %4d (%5.2f)\n", - iCol1, iCol2, - CountDiff, CountComm, - -1.0 * CountDiff / ( CountComm + CountDiff ) ); -*/ - return -1.0 * CountDiff / ( CountComm + CountDiff ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManComputeBestAttr( Llb_Mtr_t * p ) -{ - float WeightBest = -100000, WeightCur; - int i, k, RetValue = -1; - for ( i = 1; i < p->nCols-1; i++ ) - for ( k = i+1; k < p->nCols-1; k++ ) - { - if ( p->pColSums[i] == 0 || p->pColSums[i] > p->pMan->pPars->nClusterMax ) - continue; - if ( p->pColSums[k] == 0 || p->pColSums[k] > p->pMan->pPars->nClusterMax ) - continue; - WeightCur = Llb_ManComputeCommonAttr( p, i, k ); - if ( WeightBest < WeightCur ) - { - WeightBest = WeightCur; - RetValue = (i << 16) | k; - } - } - return RetValue; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float ** Llb_ManComputeAttr( Llb_Mtr_t * p ) -{ - float ** pCosts; - int i, k; - // alloc and clean - pCosts = (float **)Extra_ArrayAlloc( p->nCols, p->nCols, sizeof(float) ); - for ( i = 0; i < p->nCols; i++ ) - for ( k = 0; k < p->nCols; k++ ) - pCosts[i][i] = 0.0; - // fill up - for ( i = 1; i < p->nCols-1; i++ ) - for ( k = i+1; k < p->nCols-1; k++ ) - pCosts[i][k] = pCosts[k][i] = Llb_ManComputeCommonAttr( p, i, k ); - return pCosts; -} - - -/**Function************************************************************* - - Synopsis [Returns the number of variables that will be saved.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrCombineSelectedColumns( Llb_Mtr_t * p, int iGrp1, int iGrp2 ) -{ - int iVar; - assert( iGrp1 >= 1 && iGrp1 < p->nCols - 1 ); - assert( iGrp2 >= 1 && iGrp2 < p->nCols - 1 ); - assert( p->pColGrps[iGrp1] != NULL ); - assert( p->pColGrps[iGrp2] != NULL ); - for ( iVar = 0; iVar < p->nRows; iVar++ ) - { - if ( p->pMatrix[iGrp1][iVar] == 1 && p->pMatrix[iGrp2][iVar] == 1 ) - p->pRowSums[iVar]--; - if ( p->pMatrix[iGrp1][iVar] == 0 && p->pMatrix[iGrp2][iVar] == 1 ) - { - p->pMatrix[iGrp1][iVar] = 1; - p->pColSums[iGrp1]++; - } - if ( p->pMatrix[iGrp2][iVar] == 1 ) - p->pMatrix[iGrp2][iVar] = 0; - } - p->pColSums[iGrp2] = 0; -} - - -/**Function************************************************************* - - Synopsis [Combines one pair of columns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManClusterOne( Llb_Mtr_t * p, int iCol1, int iCol2 ) -{ - int fVerbose = 0; - Llb_Grp_t * pGrp; - int iVar; - - if ( fVerbose ) - { - printf( "Combining %d and %d\n", iCol1, iCol2 ); - for ( iVar = 0; iVar < p->nRows; iVar++ ) - { - if ( p->pMatrix[iCol1][iVar] == 0 && p->pMatrix[iCol2][iVar] == 0 ) - continue; - printf( "%3d : %c%c\n", iVar, - p->pMatrix[iCol1][iVar]? '*':' ', - p->pMatrix[iCol2][iVar]? '*':' ' ); - } - } - pGrp = Llb_ManGroupsCombine( p->pColGrps[iCol1], p->pColGrps[iCol2] ); - Llb_MtrCombineSelectedColumns( p, iCol1, iCol2 ); - p->pColGrps[iCol1] = pGrp; - p->pColGrps[iCol2] = NULL; -} - -/**Function************************************************************* - - Synopsis [Removes empty columns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManClusterCompress( Llb_Mtr_t * p ) -{ - int i, k = 0; - for ( i = 0; i < p->nCols; i++ ) - { - if ( p->pColGrps[i] == NULL ) - { - assert( p->pColSums[i] == 0 ); - assert( p->pMatrix[i] != NULL ); - ABC_FREE( p->pMatrix[i] ); - continue; - } - p->pMatrix[k] = p->pMatrix[i]; - p->pColGrps[k] = p->pColGrps[i]; - p->pColSums[k] = p->pColSums[i]; - k++; - } - p->nCols = k; -} - -/**Function************************************************************* - - Synopsis [Combines one pair of columns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManCluster( Llb_Mtr_t * p ) -{ - int RetValue; - do - { - do { - RetValue = Llb_ManComputeBestQuant( p ); - if ( RetValue > 0 ) - Llb_ManClusterOne( p, RetValue >> 16, RetValue & 0xffff ); - } - while ( RetValue > 0 ); - - RetValue = Llb_ManComputeBestAttr( p ); - if ( RetValue > 0 ) - Llb_ManClusterOne( p, RetValue >> 16, RetValue & 0xffff ); - - Llb_MtrVerifyMatrix( p ); - } - while ( RetValue > 0 ); - - Llb_ManClusterCompress( p ); - - Llb_MtrVerifyMatrix( p ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llbConstr.c b/src/aig/llb/llbConstr.c deleted file mode 100644 index eabae3bc..00000000 --- a/src/aig/llb/llbConstr.c +++ /dev/null @@ -1,313 +0,0 @@ -/**CFile**************************************************************** - - FileName [llbConstr.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Computing inductive constraints.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llbConstr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns the array of constraint candidates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManCountEntries( Vec_Int_t * vCands ) -{ - int i, Entry, Counter = 0; - Vec_IntForEachEntry( vCands, Entry, i ) - Counter += ((Entry == 0) || (Entry == 1)); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Returns the array of constraint candidates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManPrintEntries( Aig_Man_t * p, Vec_Int_t * vCands ) -{ - int i, Entry; - if ( vCands == NULL ) - { - printf( "There is no hints.\n" ); - return; - } - Entry = Llb_ManCountEntries(vCands); - printf( "\n*** Using %d hint%s:\n", Entry, (Entry != 1 ? "s":"") ); - Vec_IntForEachEntry( vCands, Entry, i ) - { - if ( Entry != 0 && Entry != 1 ) - continue; - printf( "%c", Entry ? '+' : '-' ); - printf( "%-6d : ", i ); - Aig_ObjPrint( p, Aig_ManObj(p, i) ); - printf( "\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Dereference BDD nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManDerefenceBdds( Aig_Man_t * p, DdManager * dd ) -{ - Aig_Obj_t * pObj; - int i; - Aig_ManForEachObj( p, pObj, i ) - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); -} - -/**Function************************************************************* - - Synopsis [Returns the array of constraint candidates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ManComputeIndCase_rec( Aig_Man_t * p, Aig_Obj_t * pObj, DdManager * dd, Vec_Ptr_t * vBdds ) -{ - DdNode * bBdd0, * bBdd1; - DdNode * bFunc = (DdNode *)Vec_PtrEntry( vBdds, Aig_ObjId(pObj) ); - if ( bFunc != NULL ) - return bFunc; - assert( Aig_ObjIsNode(pObj) ); - bBdd0 = Llb_ManComputeIndCase_rec( p, Aig_ObjFanin0(pObj), dd, vBdds ); - bBdd1 = Llb_ManComputeIndCase_rec( p, Aig_ObjFanin1(pObj), dd, vBdds ); - bBdd0 = Cudd_NotCond( bBdd0, Aig_ObjFaninC0(pObj) ); - bBdd1 = Cudd_NotCond( bBdd1, Aig_ObjFaninC1(pObj) ); - bFunc = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bFunc ); - Vec_PtrWriteEntry( vBdds, Aig_ObjId(pObj), bFunc ); - return bFunc; -} - -/**Function************************************************************* - - Synopsis [Returns the array of constraint candidates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManComputeIndCase( Aig_Man_t * p, DdManager * dd, Vec_Int_t * vNodes ) -{ - Vec_Ptr_t * vBdds; - Aig_Obj_t * pObj; - DdNode * bFunc; - int i, Entry; - vBdds = Vec_PtrStart( Aig_ManObjNumMax(p) ); - bFunc = Cudd_ReadOne(dd); Cudd_Ref( bFunc ); - Vec_PtrWriteEntry( vBdds, Aig_ObjId(Aig_ManConst1(p)), bFunc ); - Saig_ManForEachPi( p, pObj, i ) - { - bFunc = Cudd_bddIthVar( dd, Aig_ManPiNum(p) + i ); Cudd_Ref( bFunc ); - Vec_PtrWriteEntry( vBdds, Aig_ObjId(pObj), bFunc ); - } - Saig_ManForEachLi( p, pObj, i ) - { - bFunc = (DdNode *)pObj->pData; Cudd_Ref( bFunc ); - Vec_PtrWriteEntry( vBdds, Aig_ObjId(Saig_ObjLiToLo(p, pObj)), bFunc ); - } - Vec_IntForEachEntry( vNodes, Entry, i ) - { - if ( Entry != 0 && Entry != 1 ) - continue; - pObj = Aig_ManObj( p, i ); - bFunc = Llb_ManComputeIndCase_rec( p, pObj, dd, vBdds ); - if ( Entry == 0 ) - { -// Extra_bddPrint( dd, Cudd_Not(pObj->pData) ); printf( "\n" ); -// Extra_bddPrint( dd, Cudd_Not(bFunc) ); printf( "\n" ); - if ( !Cudd_bddLeq( dd, Cudd_Not(pObj->pData), Cudd_Not(bFunc) ) ) - Vec_IntWriteEntry( vNodes, i, -1 ); - } - else if ( Entry == 1 ) - { -// Extra_bddPrint( dd, pObj->pData ); printf( "\n" ); -// Extra_bddPrint( dd, bFunc ); printf( "\n" ); - if ( !Cudd_bddLeq( dd, (DdNode *)pObj->pData, bFunc ) ) - Vec_IntWriteEntry( vNodes, i, -1 ); - } - } - Vec_PtrForEachEntry( DdNode *, vBdds, bFunc, i ) - if ( bFunc ) - Cudd_RecursiveDeref( dd, bFunc ); - Vec_PtrFree( vBdds ); -} - -/**Function************************************************************* - - Synopsis [Returns the array of constraint candidates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_ManComputeBaseCase( Aig_Man_t * p, DdManager * dd ) -{ - Vec_Int_t * vNodes; - Aig_Obj_t * pObj, * pRoot; - int i; - pRoot = Aig_ManPo( p, 0 ); - vNodes = Vec_IntStartFull( Aig_ManObjNumMax(p) ); - Aig_ManForEachObj( p, pObj, i ) - { - if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) ) - continue; - if ( Cudd_bddLeq( dd, (DdNode *)pObj->pData, Cudd_Not(pRoot->pData) ) ) - Vec_IntWriteEntry( vNodes, i, 1 ); - else if ( Cudd_bddLeq( dd, Cudd_Not((DdNode *)pObj->pData), Cudd_Not(pRoot->pData) ) ) - Vec_IntWriteEntry( vNodes, i, 0 ); - } - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Constructs global BDDs for each object in the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdManager * Llb_ManConstructGlobalBdds( Aig_Man_t * p ) -{ - DdManager * dd; - DdNode * bBdd0, * bBdd1; - Aig_Obj_t * pObj; - int i; - dd = Cudd_Init( Aig_ManPiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - pObj = Aig_ManConst1(p); - pObj->pData = Cudd_ReadOne(dd); Cudd_Ref( (DdNode *)pObj->pData ); - Aig_ManForEachPi( p, pObj, i ) - { - pObj->pData = Cudd_bddIthVar(dd, i); Cudd_Ref( (DdNode *)pObj->pData ); - } - Aig_ManForEachNode( p, pObj, i ) - { - bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); - pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData ); - } - Aig_ManForEachPo( p, pObj, i ) - { - pObj->pData = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); Cudd_Ref( (DdNode *)pObj->pData ); - } - return dd; -} - -/**Function************************************************************* - - Synopsis [Derives inductive constraints.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_ManDeriveConstraints( Aig_Man_t * p ) -{ - DdManager * dd; - Vec_Int_t * vNodes; - if ( Saig_ManPoNum(p) != 1 ) - { - printf( "The AIG has %d property outputs.\n", Saig_ManPoNum(p) ); - return NULL; - } - assert( Saig_ManPoNum(p) == 1 ); - dd = Llb_ManConstructGlobalBdds( p ); - vNodes = Llb_ManComputeBaseCase( p, dd ); - if ( Llb_ManCountEntries(vNodes) > 0 ) - Llb_ManComputeIndCase( p, dd, vNodes ); - if ( Llb_ManCountEntries(vNodes) == 0 ) - Vec_IntFreeP( &vNodes ); - Llb_ManDerefenceBdds( p, dd ); - Extra_StopManager( dd ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Tests derived constraints.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManConstrTest( Aig_Man_t * p ) -{ - Vec_Int_t * vNodes; - vNodes = Llb_ManDeriveConstraints( p ); - Llb_ManPrintEntries( p, vNodes ); - Vec_IntFreeP( &vNodes ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llbCore.c b/src/aig/llb/llbCore.c deleted file mode 100644 index cbd527e2..00000000 --- a/src/aig/llb/llbCore.c +++ /dev/null @@ -1,219 +0,0 @@ -/**CFile**************************************************************** - - FileName [llbCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Top-level procedure.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llbCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" -#include "gia.h" -#include "giaAig.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManSetDefaultParams( Gia_ParLlb_t * p ) -{ - memset( p, 0, sizeof(Gia_ParLlb_t) ); - p->nBddMax = 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 [Prints statistics about MFFCs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManPrintAig( Llb_Man_t * p ) -{ - Abc_Print( 1, "pi =%3d ", Saig_ManPiNum(p->pAig) ); - Abc_Print( 1, "po =%3d ", Saig_ManPoNum(p->pAig) ); - Abc_Print( 1, "ff =%3d ", Saig_ManRegNum(p->pAig) ); - Abc_Print( 1, "int =%5d ", Vec_IntSize(p->vVar2Obj)-Aig_ManPiNum(p->pAig)-Saig_ManRegNum(p->pAig) ); - Abc_Print( 1, "var =%5d ", Vec_IntSize(p->vVar2Obj) ); - Abc_Print( 1, "part =%5d ", Vec_PtrSize(p->vGroups)-2 ); - Abc_Print( 1, "and =%5d ", Aig_ManNodeNum(p->pAig) ); - Abc_Print( 1, "lev =%4d ", Aig_ManLevelNum(p->pAig) ); -// Abc_Print( 1, "cut =%4d ", Llb_ManCrossCut(p->pAig) ); - Abc_Print( 1, "\n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManModelCheckAig( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars, Vec_Int_t * vHints, DdManager ** pddGlo ) -{ - Llb_Man_t * p = NULL; - Aig_Man_t * pAig; - int RetValue = -1; - int clk = clock(); - - if ( pPars->fIndConstr ) - { - assert( vHints == NULL ); - vHints = Llb_ManDeriveConstraints( pAigGlo ); - } - - // derive AIG for hints - if ( vHints == NULL ) - pAig = Aig_ManDupSimple( pAigGlo ); - else - { - if ( pPars->fVerbose ) - Llb_ManPrintEntries( pAigGlo, vHints ); - pAig = Aig_ManDupSimpleWithHints( pAigGlo, vHints ); - } - - - if ( pPars->fUseFlow ) - { -// p = Llb_ManStartFlow( pAigGlo, pAig, pPars ); - } - else - { - p = Llb_ManStart( pAigGlo, pAig, pPars ); - if ( pPars->fVerbose ) - { - Llb_ManPrintAig( p ); - printf( "Original matrix: " ); - Llb_MtrPrintMatrixStats( p->pMatrix ); - if ( pPars->fVeryVerbose ) - Llb_MtrPrint( p->pMatrix, 1 ); - } - if ( pPars->fCluster ) - { - Llb_ManCluster( p->pMatrix ); - if ( pPars->fVerbose ) - { - printf( "Matrix after clustering: " ); - Llb_MtrPrintMatrixStats( p->pMatrix ); - if ( pPars->fVeryVerbose ) - Llb_MtrPrint( p->pMatrix, 1 ); - } - } - if ( pPars->fSchedule ) - { - Llb_MtrSchedule( p->pMatrix ); - if ( pPars->fVerbose ) - { - printf( "Matrix after scheduling: " ); - Llb_MtrPrintMatrixStats( p->pMatrix ); - if ( pPars->fVeryVerbose ) - Llb_MtrPrint( p->pMatrix, 1 ); - } - } - } - - if ( !p->pPars->fSkipReach ) - RetValue = Llb_ManReachability( p, vHints, pddGlo ); - Llb_ManStop( p ); - - Abc_PrintTime( 1, "Time", clock() - clk ); - - if ( pPars->fIndConstr ) - Vec_IntFreeP( &vHints ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManModelCheckGia( Gia_Man_t * pGia, Gia_ParLlb_t * pPars ) -{ - Gia_Man_t * pGia2; - Aig_Man_t * pAig; - int RetValue = -1; - pGia2 = Gia_ManDupDfs( pGia ); - pAig = Gia_ManToAigSimple( pGia2 ); - Gia_ManStop( pGia2 ); -//Aig_ManShow( pAig, 0, NULL ); - - if ( pPars->nHintDepth == 0 ) - RetValue = Llb_ManModelCheckAig( pAig, pPars, NULL, NULL ); - else - RetValue = Llb_ManModelCheckAigWithHints( pAig, pPars ); - Aig_ManStop( pAig ); - return RetValue; -} - -//////////////////////////////////////////////////////////////////////// -/// 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/llbHint.c b/src/aig/llb/llbHint.c deleted file mode 100644 index acc674c8..00000000 --- a/src/aig/llb/llbHint.c +++ /dev/null @@ -1,226 +0,0 @@ -/**CFile**************************************************************** - - FileName [llbHint.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Cofactors the circuit w.r.t. the high-fanout variables.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llbHint.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns CI index with the largest number of fanouts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManMaxFanoutCi( Aig_Man_t * pAig ) -{ - Aig_Obj_t * pObj; - int i, WeightMax = -ABC_INFINITY, iInput = -1; - Aig_ManForEachPi( pAig, pObj, i ) - if ( WeightMax < Aig_ObjRefs(pObj) ) - { - WeightMax = Aig_ObjRefs(pObj); - iInput = i; - } - assert( iInput >= 0 ); - return iInput; -} - -/**Function************************************************************* - - Synopsis [Derives AIG whose PI is substituted by a constant.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Llb_ManPerformHints( Aig_Man_t * pAig, int nHintDepth ) -{ - Aig_Man_t * pNew, * pTemp; - int i, iInput; - pNew = Aig_ManDupDfs( pAig ); - for ( i = 0; i < nHintDepth; i++ ) - { - iInput = Llb_ManMaxFanoutCi( pNew ); - Abc_Print( 1, "%d %3d\n", i, iInput ); - pNew = Aig_ManDupCof( pTemp = pNew, iInput, 1 ); - Aig_ManStop( pTemp ); - } - return pNew; -} - -/**Function************************************************************* - - Synopsis [Returns CI index with the largest number of fanouts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_ManCollectHighFanoutObjects( Aig_Man_t * pAig, int nCandMax, int fCisOnly ) -{ - Vec_Int_t * vFanouts, * vResult; - Aig_Obj_t * pObj; - int i, fChanges, PivotValue; -// int Entry; - // collect fanout counts - vFanouts = Vec_IntAlloc( 100 ); - Aig_ManForEachObj( pAig, pObj, i ) - { -// if ( !Aig_ObjIsPi(pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) - if ( !Saig_ObjIsLo(pAig,pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) - continue; - Vec_IntPush( vFanouts, Aig_ObjRefs(pObj) ); - } - Vec_IntSort( vFanouts, 1 ); - // pick the separator - nCandMax = ABC_MIN( nCandMax, Vec_IntSize(vFanouts) - 1 ); - PivotValue = Vec_IntEntry( vFanouts, nCandMax ); - Vec_IntFree( vFanouts ); - // collect obj satisfying the constraints - vResult = Vec_IntAlloc( 100 ); - Aig_ManForEachObj( pAig, pObj, i ) - { -// if ( !Aig_ObjIsPi(pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) - if ( !Saig_ObjIsLo(pAig,pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) - continue; - if ( Aig_ObjRefs(pObj) < PivotValue ) - continue; - Vec_IntPush( vResult, Aig_ObjId(pObj) ); - } - assert( Vec_IntSize(vResult) >= nCandMax ); - // order in the decreasing order of fanouts - do - { - fChanges = 0; - for ( i = 0; i < Vec_IntSize(vResult) - 1; i++ ) - if ( Aig_ObjRefs(Aig_ManObj(pAig, Vec_IntEntry(vResult, i))) < - Aig_ObjRefs(Aig_ManObj(pAig, Vec_IntEntry(vResult, i+1))) ) - { - int Temp = Vec_IntEntry( vResult, i ); - Vec_IntWriteEntry( vResult, i, Vec_IntEntry(vResult, i+1) ); - Vec_IntWriteEntry( vResult, i+1, Temp ); - fChanges = 1; - } - } - while ( fChanges ); -/* - Vec_IntForEachEntry( vResult, Entry, i ) - printf( "%d ", Aig_ObjRefs(Aig_ManObj(pAig, Entry)) ); -printf( "\n" ); -*/ - return vResult; -} - -/**Function************************************************************* - - Synopsis [Derives AIG whose PI is substituted by a constant.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManModelCheckAigWithHints( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars ) -{ - DdManager * ddGlo = NULL; - Vec_Int_t * vHints; - Vec_Int_t * vHFCands; - int i, Entry, RetValue = -1; - int clk = clock(); - assert( pPars->nHintDepth > 0 ); -/* - // perform reachability without hints - RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, NULL, NULL ); - if ( RetValue >= 0 ) - return RetValue; -*/ - // create hints representation - vHFCands = Llb_ManCollectHighFanoutObjects( pAigGlo, pPars->nHintDepth+pPars->HintFirst, 1 ); - vHints = Vec_IntStartFull( Aig_ManObjNumMax(pAigGlo) ); - // add one hint at a time till the problem is solved - Vec_IntForEachEntryStart( vHFCands, Entry, i, pPars->HintFirst ) - { - Vec_IntWriteEntry( vHints, Entry, 1 ); // change to 1 to start from zero cof!!! - // solve under hints - RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, vHints, &ddGlo ); - if ( RetValue == 0 ) - goto Finish; - if ( RetValue == 1 ) - break; - } - if ( RetValue == -1 ) - goto Finish; - // undo the hints one at a time - for ( ; i >= pPars->HintFirst; i-- ) - { - Entry = Vec_IntEntry( vHFCands, i ); - Vec_IntWriteEntry( vHints, Entry, -1 ); - // solve under relaxed hints - RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, vHints, &ddGlo ); - if ( RetValue == 0 ) - goto Finish; - if ( RetValue == 1 ) - continue; - break; - } -Finish: - if ( ddGlo ) - { - if ( ddGlo->bReached ) - Cudd_RecursiveDeref( ddGlo, ddGlo->bReached ); - Extra_StopManager( ddGlo ); - } - Vec_IntFreeP( &vHFCands ); - Vec_IntFreeP( &vHints ); - if ( pPars->fVerbose ) - Abc_PrintTime( 1, "Total runtime", clock() - clk ); - return RetValue; -} - - -//////////////////////////////////////////////////////////////////////// -/// 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/llbMan.c b/src/aig/llb/llbMan.c deleted file mode 100644 index cd6fd3ff..00000000 --- a/src/aig/llb/llbMan.c +++ /dev/null @@ -1,189 +0,0 @@ -/**CFile**************************************************************** - - FileName [llbMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Reachability manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llbMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManPrepareVarMap( Llb_Man_t * p ) -{ - Aig_Obj_t * pObjLi, * pObjLo; - int i, iVarLi, iVarLo; - assert( p->vNs2Glo == NULL ); - assert( p->vGlo2Cs == NULL ); - p->vNs2Glo = Vec_IntStartFull( Vec_IntSize(p->vVar2Obj) ); - p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); - Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) - { - iVarLi = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLi)); - iVarLo = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLo)); - assert( iVarLi >= 0 && iVarLi < Vec_IntSize(p->vVar2Obj) ); - assert( iVarLo >= 0 && iVarLo < Vec_IntSize(p->vVar2Obj) ); - Vec_IntWriteEntry( p->vNs2Glo, iVarLi, i ); - Vec_IntWriteEntry( p->vGlo2Cs, i, iVarLo ); - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManPrepareVarLimits( Llb_Man_t * p ) -{ - Llb_Grp_t * pGroup; - Aig_Obj_t * pVar; - int i, k; - assert( p->vVarBegs == NULL ); - assert( p->vVarEnds == NULL ); - p->vVarEnds = Vec_IntStart( Aig_ManObjNumMax(p->pAig) ); - p->vVarBegs = Vec_IntStart( Aig_ManObjNumMax(p->pAig) ); - Vec_IntFill( p->vVarBegs, Aig_ManObjNumMax(p->pAig), p->pMatrix->nCols ); - - for ( i = 0; i < p->pMatrix->nCols; i++ ) - { - pGroup = p->pMatrix->pColGrps[i]; - - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) - if ( Vec_IntEntry(p->vVarBegs, pVar->Id) > i ) - Vec_IntWriteEntry( p->vVarBegs, pVar->Id, i ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) - if ( Vec_IntEntry(p->vVarBegs, pVar->Id) > i ) - Vec_IntWriteEntry( p->vVarBegs, pVar->Id, i ); - - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) - if ( Vec_IntEntry(p->vVarEnds, pVar->Id) < i ) - Vec_IntWriteEntry( p->vVarEnds, pVar->Id, i ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) - if ( Vec_IntEntry(p->vVarEnds, pVar->Id) < i ) - Vec_IntWriteEntry( p->vVarEnds, pVar->Id, i ); - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManStop( Llb_Man_t * p ) -{ - Llb_Grp_t * pGrp; - int i; - -// Vec_IntFreeP( &p->vMem ); -// Vec_PtrFreeP( &p->vTops ); -// Vec_PtrFreeP( &p->vBots ); -// Vec_VecFreeP( (Vec_Vec_t **)&p->vCuts ); - - if ( p->pMatrix ) - Llb_MtrFree( p->pMatrix ); - Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGrp, i ) - Llb_ManGroupStop( pGrp ); - Vec_PtrFreeP( &p->vGroups ); - Vec_IntFreeP( &p->vVar2Obj ); - Vec_IntFreeP( &p->vObj2Var ); - Vec_IntFreeP( &p->vVarBegs ); - Vec_IntFreeP( &p->vVarEnds ); - Vec_IntFreeP( &p->vNs2Glo ); - Vec_IntFreeP( &p->vGlo2Cs ); -// Vec_IntFreeP( &p->vHints ); - if ( p->dd ) - { - Extra_StopManager( p->dd ); - } - if ( p->ddG ) - { - if ( p->ddG->bReached ) - Cudd_RecursiveDeref( p->ddG, p->ddG->bReached ); - Extra_StopManager( p->ddG ); - } - Aig_ManStop( p->pAig ); - ABC_FREE( p ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Man_t * Llb_ManStart( Aig_Man_t * pAigGlo, Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) -{ - Llb_Man_t * p; - Aig_ManCleanMarkA( pAig ); - p = ABC_CALLOC( Llb_Man_t, 1 ); - p->pAigGlo = pAigGlo; - p->pPars = pPars; - p->pAig = pAig; - p->vVar2Obj = Llb_ManMarkPivotNodes( p->pAig, pPars->fUsePivots ); - p->vObj2Var = Vec_IntInvert( p->vVar2Obj, -1 ); - Llb_ManPrepareVarMap( p ); - Llb_ManPrepareGroups( p ); - Aig_ManCleanMarkA( pAig ); - p->pMatrix = Llb_MtrCreate( p ); - p->pMatrix->pMan = p; - return p; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llbMatrix.c b/src/aig/llb/llbMatrix.c deleted file mode 100644 index 484ee690..00000000 --- a/src/aig/llb/llbMatrix.c +++ /dev/null @@ -1,430 +0,0 @@ -/**CFile**************************************************************** - - FileName [llbMatrix.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Partition clustering as a matrix problem.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llbMatrix.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// 0123 nCols -// +---------------------> -// pi 0 | 111 row0 pRowSums[0] -// pi 1 | 1 11 row1 pRowSums[1] -// pi 2 | 1 11 row2 pRowSums[2] -// CS |1 1 -// CS |1 111 -// CS |111 111 -// int | 11111 -// int | 111 -// int | 111 -// int | 111 -// NS | 11 11 -// NS | 11 1 -// NS | 111 -// nRows | -// v -// cccc pColSums[0] -// oooo pColSums[1] -// llll pColSums[2] -// 0123 pColSums[3] - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Verify columns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrVerifyRowsAll( Llb_Mtr_t * p ) -{ - int iRow, iCol, Counter; - for ( iCol = 0; iCol < p->nCols; iCol++ ) - { - Counter = 0; - for ( iRow = 0; iRow < p->nRows; iRow++ ) - if ( p->pMatrix[iCol][iRow] == 1 ) - Counter++; - assert( Counter == p->pColSums[iCol] ); - } -} - -/**Function************************************************************* - - Synopsis [Verify columns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrVerifyColumnsAll( Llb_Mtr_t * p ) -{ - int iRow, iCol, Counter; - for ( iRow = 0; iRow < p->nRows; iRow++ ) - { - Counter = 0; - for ( iCol = 0; iCol < p->nCols; iCol++ ) - if ( p->pMatrix[iCol][iRow] == 1 ) - Counter++; - assert( Counter == p->pRowSums[iRow] ); - } -} - -/**Function************************************************************* - - Synopsis [Verify columns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrVerifyMatrix( Llb_Mtr_t * p ) -{ - Llb_MtrVerifyRowsAll( p ); - Llb_MtrVerifyColumnsAll( p ); -} - -/**Function************************************************************* - - Synopsis [Sort variables in the order of removal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int * Llb_MtrFindVarOrder( Llb_Mtr_t * p ) -{ - int * pOrder, * pLast; - int i, k, fChanges, Temp; - pOrder = ABC_CALLOC( int, p->nRows ); - pLast = ABC_CALLOC( int, p->nRows ); - for ( i = 0; i < p->nRows; i++ ) - { - pOrder[i] = i; - for ( k = p->nCols - 1; k >= 0; k-- ) - if ( p->pMatrix[k][i] ) - { - pLast[i] = k; - break; - } - } - do - { - fChanges = 0; - for ( i = 0; i < p->nRows - 1; i++ ) - if ( pLast[i] > pLast[i+1] ) - { - Temp = pOrder[i]; - pOrder[i] = pOrder[i+1]; - pOrder[i+1] = Temp; - - Temp = pLast[i]; - pLast[i] = pLast[i+1]; - pLast[i+1] = Temp; - - fChanges = 1; - } - } - while ( fChanges ); - ABC_FREE( pLast ); - return pOrder; -} - -/**Function************************************************************* - - Synopsis [Returns type of a variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Llb_MtrVarName( Llb_Mtr_t * p, int iVar ) -{ - static char Buffer[10]; - if ( iVar < p->nPis ) - strcpy( Buffer, "pi" ); - else if ( iVar < p->nPis + p->nFfs ) - strcpy( Buffer, "CS" ); - else if ( iVar >= p->nRows - p->nFfs ) - strcpy( Buffer, "NS" ); - else - strcpy( Buffer, "int" ); - return Buffer; -} - -/**Function************************************************************* - - Synopsis [Creates one column with vars in the array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrPrint( Llb_Mtr_t * p, int fOrder ) -{ - int * pOrder = NULL; - int i, iRow, iCol; - if ( fOrder ) - pOrder = Llb_MtrFindVarOrder( p ); - for ( i = 0; i < p->nRows; i++ ) - { - iRow = pOrder ? pOrder[i] : i; - printf( "%3d : ", iRow ); - printf( "%3d ", p->pRowSums[iRow] ); - printf( "%3s ", Llb_MtrVarName(p, iRow) ); - for ( iCol = 0; iCol < p->nCols; iCol++ ) - printf( "%c", p->pMatrix[iCol][iRow] ? '*' : ' ' ); - printf( "\n" ); - } - ABC_FREE( pOrder ); -} - -/**Function************************************************************* - - Synopsis [Verify columns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrPrintMatrixStats( Llb_Mtr_t * p ) -{ - int iVar, iGrp, iGrp1, iGrp2, Span = 0, nCutSize = 0, nCutSizeMax = 0; - int * pGrp1 = ABC_CALLOC( int, p->nRows ); - int * pGrp2 = ABC_CALLOC( int, p->nRows ); - for ( iVar = 0; iVar < p->nRows; iVar++ ) - { - if ( p->pRowSums[iVar] == 0 ) - continue; - for ( iGrp1 = 0; iGrp1 < p->nCols; iGrp1++ ) - if ( p->pMatrix[iGrp1][iVar] == 1 ) - break; - for ( iGrp2 = p->nCols - 1; iGrp2 >= 0; iGrp2-- ) - if ( p->pMatrix[iGrp2][iVar] == 1 ) - break; - assert( iGrp1 <= iGrp2 ); - pGrp1[iVar] = iGrp1; - pGrp2[iVar] = iGrp2; - Span += iGrp2 - iGrp1; - } - // compute span - for ( iGrp = 0; iGrp < p->nCols; iGrp++ ) - { - for ( iVar = 0; iVar < p->nRows; iVar++ ) - if ( pGrp1[iVar] == iGrp ) - nCutSize++; - if ( nCutSizeMax < nCutSize ) - nCutSizeMax = nCutSize; - for ( iVar = 0; iVar < p->nRows; iVar++ ) - if ( pGrp2[iVar] == iGrp ) - nCutSize--; - } - ABC_FREE( pGrp1 ); - ABC_FREE( pGrp2 ); - printf( "[%4d x %4d] Life-span =%6.2f Max-cut =%5d\n", - p->nCols, p->nRows, 1.0*Span/p->nRows, nCutSizeMax ); - if ( nCutSize ) - Abc_Print( -1, "Cut size is not zero (%d).\n", nCutSize ); -} - - - -/**Function************************************************************* - - Synopsis [Starts the matrix representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Mtr_t * Llb_MtrAlloc( int nPis, int nFfs, int nCols, int nRows ) -{ - Llb_Mtr_t * p; - int i; - p = ABC_CALLOC( Llb_Mtr_t, 1 ); - p->nPis = nPis; - p->nFfs = nFfs; - p->nRows = nRows; - p->nCols = nCols; - p->pRowSums = ABC_CALLOC( int, nRows ); - p->pColSums = ABC_CALLOC( int, nCols ); - p->pColGrps = ABC_CALLOC( Llb_Grp_t *, nCols ); - p->pMatrix = ABC_CALLOC( char *, nCols ); - for ( i = 0; i < nCols; i++ ) - p->pMatrix[i] = ABC_CALLOC( char, nRows ); - // partial product - p->pProdVars = ABC_CALLOC( char, nRows ); // variables in the partial product - p->pProdNums = ABC_CALLOC( int, nRows ); // var counts in the remaining partitions - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the matrix representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrFree( Llb_Mtr_t * p ) -{ - int i; - ABC_FREE( p->pProdVars ); - ABC_FREE( p->pProdNums ); - for ( i = 0; i < p->nCols; i++ ) - ABC_FREE( p->pMatrix[i] ); - ABC_FREE( p->pRowSums ); - ABC_FREE( p->pColSums ); - ABC_FREE( p->pMatrix ); - ABC_FREE( p->pColGrps ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Creates one column with vars in the array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrAddColumn( Llb_Mtr_t * p, Llb_Grp_t * pGrp ) -{ - Aig_Obj_t * pVar; - int i, iRow, iCol = pGrp->Id; - assert( iCol >= 0 && iCol < p->nCols ); - p->pColGrps[iCol] = pGrp; - Vec_PtrForEachEntry( Aig_Obj_t *, pGrp->vIns, pVar, i ) - { - iRow = Vec_IntEntry( pGrp->pMan->vObj2Var, Aig_ObjId(pVar) ); - assert( iRow >= 0 && iRow < p->nRows ); - p->pMatrix[iCol][iRow] = 1; - p->pColSums[iCol]++; - p->pRowSums[iRow]++; - } - Vec_PtrForEachEntry( Aig_Obj_t *, pGrp->vOuts, pVar, i ) - { - iRow = Vec_IntEntry( pGrp->pMan->vObj2Var, Aig_ObjId(pVar) ); - assert( iRow >= 0 && iRow < p->nRows ); - p->pMatrix[iCol][iRow] = 1; - p->pColSums[iCol]++; - p->pRowSums[iRow]++; - } -} - -/**Function************************************************************* - - Synopsis [Matrix reduce.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrRemoveSingletonRows( Llb_Mtr_t * p ) -{ - int i, k; - for ( i = 0; i < p->nRows; i++ ) - if ( p->pRowSums[i] < 2 ) - { - p->pRowSums[i] = 0; - for ( k = 0; k < p->nCols; k++ ) - { - if ( p->pMatrix[k][i] == 1 ) - { - p->pMatrix[k][i] = 0; - p->pColSums[k]--; - } - } - } -} - -/**Function************************************************************* - - Synopsis [Matrix reduce.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Mtr_t * Llb_MtrCreate( Llb_Man_t * p ) -{ - Llb_Mtr_t * pMatrix; - Llb_Grp_t * pGroup; - int i; - pMatrix = Llb_MtrAlloc( Saig_ManPiNum(p->pAig), Saig_ManRegNum(p->pAig), - Vec_PtrSize(p->vGroups), Vec_IntSize(p->vVar2Obj) ); - Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGroup, i ) - Llb_MtrAddColumn( pMatrix, pGroup ); -// Llb_MtrRemoveSingletonRows( pMatrix ); - return pMatrix; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llbPart.c b/src/aig/llb/llbPart.c deleted file mode 100644 index 41de27d8..00000000 --- a/src/aig/llb/llbPart.c +++ /dev/null @@ -1,474 +0,0 @@ -/**CFile**************************************************************** - - FileName [llbPart.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Initial partition computation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llbPart.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Grp_t * Llb_ManGroupAlloc( Llb_Man_t * pMan ) -{ - Llb_Grp_t * p; - p = ABC_CALLOC( Llb_Grp_t, 1 ); - p->pMan = pMan; - p->vIns = Vec_PtrAlloc( 8 ); - p->vOuts = Vec_PtrAlloc( 8 ); - p->Id = Vec_PtrSize( pMan->vGroups ); - Vec_PtrPush( pMan->vGroups, p ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManGroupStop( Llb_Grp_t * p ) -{ - if ( p == NULL ) - return; - Vec_PtrWriteEntry( p->pMan->vGroups, p->Id, NULL ); - Vec_PtrFreeP( &p->vIns ); - Vec_PtrFreeP( &p->vOuts ); - Vec_PtrFreeP( &p->vNodes ); - ABC_FREE( p ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManGroupCollect_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) -{ - if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) - return; - Aig_ObjSetTravIdCurrent(pAig, pObj); - if ( Aig_ObjIsConst1(pObj) ) - return; - if ( Aig_ObjIsPo(pObj) ) - { - Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin0(pObj), vNodes ); - return; - } - assert( Aig_ObjIsAnd(pObj) ); - Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin0(pObj), vNodes ); - Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin1(pObj), vNodes ); - Vec_PtrPush( vNodes, pObj ); -} - -/**Function************************************************************* - - Synopsis [Collects the support of MFFC.] - - Description [Returns the number of internal nodes in the MFFC.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManGroupCollect( Llb_Grp_t * pGroup ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i; - vNodes = Vec_PtrAlloc( 100 ); - Aig_ManIncrementTravId( pGroup->pMan->pAig ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) - Aig_ObjSetTravIdCurrent( pGroup->pMan->pAig, pObj ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) - Aig_ObjSetTravIdPrevious( pGroup->pMan->pAig, pObj ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) - Llb_ManGroupCollect_rec( pGroup->pMan->pAig, pObj, vNodes ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManGroupCreate_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vSupp ) -{ - if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) - return; - Aig_ObjSetTravIdCurrent(pAig, pObj); - if ( Aig_ObjIsConst1(pObj) ) - return; - if ( pObj->fMarkA ) - { - Vec_PtrPush( vSupp, pObj ); - return; - } - assert( Aig_ObjIsAnd(pObj) ); - Llb_ManGroupCreate_rec( pAig, Aig_ObjFanin0(pObj), vSupp ); - Llb_ManGroupCreate_rec( pAig, Aig_ObjFanin1(pObj), vSupp ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Grp_t * Llb_ManGroupCreate( Llb_Man_t * pMan, Aig_Obj_t * pObj ) -{ - Llb_Grp_t * p; - assert( pObj->fMarkA == 1 ); - // derive group - p = Llb_ManGroupAlloc( pMan ); - Vec_PtrPush( p->vOuts, pObj ); - Aig_ManIncrementTravId( pMan->pAig ); - if ( Aig_ObjIsPo(pObj) ) - Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin0(pObj), p->vIns ); - else - { - Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin0(pObj), p->vIns ); - Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin1(pObj), p->vIns ); - } - // derive internal objects - assert( p->vNodes == NULL ); - p->vNodes = Llb_ManGroupCollect( p ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Grp_t * Llb_ManGroupCreateFirst( Llb_Man_t * pMan ) -{ - Llb_Grp_t * p; - Aig_Obj_t * pObj; - int i; - p = Llb_ManGroupAlloc( pMan ); - Saig_ManForEachLo( pMan->pAig, pObj, i ) - Vec_PtrPush( p->vOuts, pObj ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Grp_t * Llb_ManGroupCreateLast( Llb_Man_t * pMan ) -{ - Llb_Grp_t * p; - Aig_Obj_t * pObj; - int i; - p = Llb_ManGroupAlloc( pMan ); - Saig_ManForEachLi( pMan->pAig, pObj, i ) - Vec_PtrPush( p->vIns, pObj ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Grp_t * Llb_ManGroupsCombine( Llb_Grp_t * p1, Llb_Grp_t * p2 ) -{ - Llb_Grp_t * p; - Aig_Obj_t * pObj; - int i; - p = Llb_ManGroupAlloc( p1->pMan ); - // create inputs - Vec_PtrForEachEntry( Aig_Obj_t *, p1->vIns, pObj, i ) - Vec_PtrPush( p->vIns, pObj ); - Vec_PtrForEachEntry( Aig_Obj_t *, p2->vIns, pObj, i ) - Vec_PtrPushUnique( p->vIns, pObj ); - // create outputs - Vec_PtrForEachEntry( Aig_Obj_t *, p1->vOuts, pObj, i ) - Vec_PtrPush( p->vOuts, pObj ); - Vec_PtrForEachEntry( Aig_Obj_t *, p2->vOuts, pObj, i ) - Vec_PtrPushUnique( p->vOuts, pObj ); - - // derive internal objects - assert( p->vNodes == NULL ); - p->vNodes = Llb_ManGroupCollect( p ); - return p; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManGroupMarkNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return; - if ( Aig_ObjIsTravIdPrevious(p, pObj) ) - { - Aig_ObjSetTravIdCurrent(p, pObj); - return; - } - Aig_ObjSetTravIdCurrent(p, pObj); - assert( Aig_ObjIsNode(pObj) ); - Llb_ManGroupMarkNodes_rec( p, Aig_ObjFanin0(pObj) ); - Llb_ManGroupMarkNodes_rec( p, Aig_ObjFanin1(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Creates group from two cuts derived by the flow computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Grp_t * Llb_ManGroupCreateFromCuts( Llb_Man_t * pMan, Vec_Int_t * vCut1, Vec_Int_t * vCut2 ) -{ - Llb_Grp_t * p; - Aig_Obj_t * pObj; - int i; - p = Llb_ManGroupAlloc( pMan ); - - // mark Cut1 - Aig_ManIncrementTravId( pMan->pAig ); - Aig_ManForEachNodeVec( pMan->pAig, vCut1, pObj, i ) - Aig_ObjSetTravIdCurrent( pMan->pAig, pObj ); - // collect unmarked Cut2 - Aig_ManForEachNodeVec( pMan->pAig, vCut2, pObj, i ) - if ( !Aig_ObjIsTravIdCurrent( pMan->pAig, pObj ) ) - Vec_PtrPush( p->vOuts, pObj ); - - // mark nodes reachable from Cut2 - Aig_ManIncrementTravId( pMan->pAig ); - Aig_ManForEachNodeVec( pMan->pAig, vCut2, pObj, i ) - Llb_ManGroupMarkNodes_rec( pMan->pAig, pObj ); - // collect marked Cut1 - Aig_ManForEachNodeVec( pMan->pAig, vCut1, pObj, i ) - if ( Aig_ObjIsTravIdCurrent( pMan->pAig, pObj ) ) - Vec_PtrPush( p->vIns, pObj ); - - // derive internal objects - assert( p->vNodes == NULL ); - p->vNodes = Llb_ManGroupCollect( p ); - return p; -} - - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManPrepareGroups( Llb_Man_t * pMan ) -{ - Aig_Obj_t * pObj; - int i; - assert( pMan->vGroups == NULL ); - pMan->vGroups = Vec_PtrAlloc( 1000 ); - Llb_ManGroupCreateFirst( pMan ); - Aig_ManForEachNode( pMan->pAig, pObj, i ) - { - if ( pObj->fMarkA ) - Llb_ManGroupCreate( pMan, pObj ); - } - Saig_ManForEachLi( pMan->pAig, pObj, i ) - { - if ( pObj->fMarkA ) - Llb_ManGroupCreate( pMan, pObj ); - } - Llb_ManGroupCreateLast( pMan ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManPrintSpan( Llb_Man_t * p ) -{ - Llb_Grp_t * pGroup; - Aig_Obj_t * pVar; - int i, k, Span = 0, SpanMax = 0; - Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGroup, i ) - { - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) - if ( Vec_IntEntry(p->vVarBegs, pVar->Id) == i ) - Span++; - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) - if ( Vec_IntEntry(p->vVarBegs, pVar->Id) == i ) - Span++; - - SpanMax = ABC_MAX( SpanMax, Span ); -printf( "%d ", Span ); - - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) - if ( Vec_IntEntry(p->vVarEnds, pVar->Id) == i ) - Span--; - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) - if ( Vec_IntEntry(p->vVarEnds, pVar->Id) == i ) - Span--; - } -printf( "\n" ); -printf( "Max = %d\n", SpanMax ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManGroupHasVar( Llb_Man_t * p, int iGroup, int iVar ) -{ - Llb_Grp_t * pGroup = (Llb_Grp_t *)Vec_PtrEntry( p->vGroups, iGroup ); - Aig_Obj_t * pObj; - int i; - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) - if ( pObj->Id == iVar ) - return 1; - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) - if ( pObj->Id == iVar ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManPrintHisto( Llb_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i, k; - Aig_ManForEachObj( p->pAig, pObj, i ) - { - if ( Vec_IntEntry(p->vObj2Var, i) < 0 ) - continue; - printf( "%3d :", i ); - for ( k = 0; k < Vec_IntEntry(p->vVarBegs, i); k++ ) - printf( " " ); - for ( ; k <= Vec_IntEntry(p->vVarEnds, i); k++ ) - printf( "%c", Llb_ManGroupHasVar(p, k, i)? '*':'-' ); - printf( "\n" ); - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llbPivot.c b/src/aig/llb/llbPivot.c deleted file mode 100644 index 6a6fb321..00000000 --- a/src/aig/llb/llbPivot.c +++ /dev/null @@ -1,254 +0,0 @@ -/**CFile**************************************************************** - - FileName [llbPivot.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Determining pivot variables.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llbPivot.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManTracePaths_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pPivot ) -{ - Aig_Obj_t * pFanout; - int k, iFan; - if ( Aig_ObjIsTravIdPrevious(p, pObj) ) - return 0; - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return 1; - if ( Saig_ObjIsLi(p, pObj) ) - return 0; - if ( Saig_ObjIsPo(p, pObj) ) - return 0; - if ( pObj == pPivot ) - return 1; - assert( Aig_ObjIsCand(pObj) ); - Aig_ObjForEachFanout( p, pObj, pFanout, iFan, k ) - if ( !Llb_ManTracePaths_rec( p, pFanout, pPivot ) ) - { - Aig_ObjSetTravIdPrevious(p, pObj); - return 0; - } - Aig_ObjSetTravIdCurrent(p, pObj); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManTracePaths( Aig_Man_t * p, Aig_Obj_t * pPivot ) -{ - Aig_Obj_t * pObj; - int i, Counter = 0; - Aig_ManIncrementTravId( p ); // prev = visited with path to LI (value 0) - Aig_ManIncrementTravId( p ); // cur = visited w/o path to LI (value 1) - Saig_ManForEachLo( p, pObj, i ) - Counter += Llb_ManTracePaths_rec( p, pObj, pPivot ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManTestCuts( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i, Count; - Aig_ManFanoutStart( p ); - Aig_ManForEachNode( p, pObj, i ) - { - if ( Aig_ObjRefs(pObj) <= 1 ) - continue; - Count = Llb_ManTracePaths( p, pObj ); - printf( "Obj =%5d. Lev =%3d. Fanout =%5d. Count = %3d.\n", - i, Aig_ObjLevel(pObj), Aig_ObjRefs(pObj), Count ); - } - Aig_ManFanoutStop( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManLabelLiCones_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - if ( pObj->fMarkB ) - return; - pObj->fMarkB = 1; - assert( Aig_ObjIsNode(pObj) ); - Llb_ManLabelLiCones_rec( p, Aig_ObjFanin0(pObj) ); - Llb_ManLabelLiCones_rec( p, Aig_ObjFanin1(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Determine starting cut-points.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManLabelLiCones( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - // mark const and PIs - Aig_ManConst1(p)->fMarkB = 1; - Aig_ManForEachPi( p, pObj, i ) - pObj->fMarkB = 1; - // mark cones - Saig_ManForEachLi( p, pObj, i ) - Llb_ManLabelLiCones_rec( p, Aig_ObjFanin0(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Determine starting cut-points.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManMarkInternalPivots( Aig_Man_t * p ) -{ - Vec_Ptr_t * vMuxes; - Aig_Obj_t * pObj; - int i, Counter = 0; - - // remove refs due to MUXes - vMuxes = Aig_ManMuxesCollect( p ); - Aig_ManMuxesDeref( p, vMuxes ); - - // mark nodes feeding into LIs - Aig_ManCleanMarkB( p ); - Llb_ManLabelLiCones( p ); - - // mark internal nodes - Aig_ManFanoutStart( p ); - Aig_ManForEachNode( p, pObj, i ) - if ( pObj->fMarkB && pObj->nRefs > 1 ) - { - if ( Llb_ManTracePaths(p, pObj) > 0 ) - pObj->fMarkA = 1; - Counter++; - } - Aig_ManFanoutStop( p ); -// printf( "TracePath tried = %d.\n", Counter ); - - // mark nodes feeding into LIs - Aig_ManCleanMarkB( p ); - - // add refs due to MUXes - Aig_ManMuxesRef( p, vMuxes ); - Vec_PtrFree( vMuxes ); -} - -/**Function************************************************************* - - Synopsis [Determine starting cut-points.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_ManMarkPivotNodes( Aig_Man_t * p, int fUseInternal ) -{ - Vec_Int_t * vVar2Obj; - Aig_Obj_t * pObj; - int i; - // mark inputs/outputs - Aig_ManForEachPi( p, pObj, i ) - pObj->fMarkA = 1; - Saig_ManForEachLi( p, pObj, i ) - pObj->fMarkA = 1; - - // mark internal pivot nodes - if ( fUseInternal ) - Llb_ManMarkInternalPivots( p ); - - // assign variable numbers - Aig_ManConst1(p)->fMarkA = 0; - vVar2Obj = Vec_IntAlloc( 100 ); - Aig_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; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llbReach.c b/src/aig/llb/llbReach.c deleted file mode 100644 index 76ee7147..00000000 --- a/src/aig/llb/llbReach.c +++ /dev/null @@ -1,620 +0,0 @@ -/**CFile**************************************************************** - - FileName [llbReach.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Reachability analysis.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llbReach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" -#include "extra.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Derives global BDD for the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ManConstructOutBdd( Aig_Man_t * pAig, Aig_Obj_t * pNode, DdManager * dd ) -{ - DdNode * bBdd0, * bBdd1, * bFunc; - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i; - if ( Aig_ObjFanin0(pNode) == Aig_ManConst1(pAig) ) - return Cudd_NotCond( Cudd_ReadOne(dd), Aig_ObjFaninC0(pNode) ); - vNodes = Aig_ManDfsNodes( pAig, &pNode, 1 ); - assert( Vec_PtrSize(vNodes) > 0 ); - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - { - if ( !Aig_ObjIsNode(pObj) ) - continue; - bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bBdd1 = Cudd_NotCond( Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); - pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData ); - } - bFunc = (DdNode *)pObj->pData; Cudd_Ref( bFunc ); - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - { - if ( !Aig_ObjIsNode(pObj) ) - continue; - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - } - Vec_PtrFree( vNodes ); - if ( Aig_ObjIsPo(pNode) ) - bFunc = Cudd_NotCond( bFunc, Aig_ObjFaninC0(pNode) ); - Cudd_Deref( bFunc ); - return bFunc; -} - -/**Function************************************************************* - - Synopsis [Derives BDD for the group.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ManConstructGroupBdd( Llb_Man_t * p, Llb_Grp_t * pGroup ) -{ - Aig_Obj_t * pObj; - DdNode * bBdd0, * bBdd1, * bRes, * bXor, * bTemp; - int i; - Aig_ManConst1(p->pAig)->pData = Cudd_ReadOne( p->dd ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) - pObj->pData = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vNodes, pObj, i ) - { - bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bBdd1 = Cudd_NotCond( Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); - pObj->pData = Cudd_bddAnd( p->dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData ); - } - bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) - { - if ( Aig_ObjIsPo(pObj) ) - bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - else - bBdd0 = (DdNode *)pObj->pData; - bBdd1 = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); - bXor = Cudd_bddXor( p->dd, bBdd0, bBdd1 ); Cudd_Ref( bXor ); - bRes = Cudd_bddAnd( p->dd, bTemp = bRes, Cudd_Not(bXor) ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bXor ); - } - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vNodes, pObj, i ) - Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData ); - Cudd_Deref( bRes ); - return bRes; -} - -/**Function************************************************************* - - Synopsis [Derives quantification cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ManConstructQuantCubeIntern( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace ) -{ - Aig_Obj_t * pObj; - DdNode * bRes, * bTemp, * bVar; - int i, iGroupFirst, iGroupLast; - bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) - { - iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); - iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); - assert( iGroupFirst <= iGroupLast ); - if ( iGroupFirst < iGroupLast ) - continue; - bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); - bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) - { - iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); - iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); - assert( iGroupFirst <= iGroupLast ); - if ( iGroupFirst < iGroupLast ) - continue; - bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); - bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - Cudd_Deref( bRes ); - return bRes; -} - -/**Function************************************************************* - - Synopsis [Derives quantification cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ManConstructQuantCube( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace ) -{ - Aig_Obj_t * pObj; - DdNode * bRes, * bTemp, * bVar; - int i, iGroupLast; - bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) - { - iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); - assert( iGroupLast >= iGrpPlace ); - if ( iGroupLast > iGrpPlace ) - continue; - bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); - bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) - { - iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); - assert( iGroupLast >= iGrpPlace ); - if ( iGroupLast > iGrpPlace ) - continue; - bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); - bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - Cudd_Deref( bRes ); - return bRes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ManComputeInitState( Llb_Man_t * p, DdManager * dd ) -{ - Aig_Obj_t * pObj; - DdNode * bRes, * bVar, * bTemp; - int i, iVar; - bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); - Saig_ManForEachLo( p->pAig, pObj, i ) - { - iVar = (dd == p->ddG) ? i : Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)); - bVar = Cudd_bddIthVar( dd, iVar ); - bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bRes ); - return bRes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ManComputeImage( Llb_Man_t * p, DdNode * bInit ) -{ - int fCheckSupport = 0; - Llb_Grp_t * pGroup; - DdNode * bImage, * bGroup, * bCube, * bTemp; - int i; - bImage = bInit; Cudd_Ref( bImage ); - for ( i = 1; i < p->pMatrix->nCols-1; i++ ) - { - // compute group BDD - pGroup = p->pMatrix->pColGrps[i]; - bGroup = Llb_ManConstructGroupBdd( p, pGroup ); Cudd_Ref( bGroup ); - // quantify variables appearing only in this group - bCube = Llb_ManConstructQuantCubeIntern( p, pGroup, i ); Cudd_Ref( bCube ); - bGroup = Cudd_bddExistAbstract( p->dd, bTemp = bGroup, bCube ); Cudd_Ref( bGroup ); - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bCube ); - // perform partial product - bCube = Llb_ManConstructQuantCube( p, pGroup, i ); Cudd_Ref( bCube ); - bImage = Cudd_bddAndAbstract( p->dd, bTemp = bImage, bGroup, bCube ); Cudd_Ref( bImage ); - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bGroup ); - Cudd_RecursiveDeref( p->dd, bCube ); - // chech runtime - if ( p->pPars->TimeTarget && clock() >= p->pPars->TimeTarget ) - { - Cudd_RecursiveDeref( p->dd, bImage ); - return NULL; - } - } - - // make sure image depends on next state vars - if ( fCheckSupport ) - { - bCube = Cudd_Support( p->dd, bImage ); Cudd_Ref( bCube ); - for ( bTemp = bCube; bTemp != p->dd->one; bTemp = cuddT(bTemp) ) - { - int ObjId = Vec_IntEntry( p->vVar2Obj, bTemp->index ); - Aig_Obj_t * pObj = Aig_ManObj( p->pAig, ObjId ); - if ( !Saig_ObjIsLi(p->pAig, pObj) ) - printf( "Var %d assigned to obj %d that is not LI\n", bTemp->index, ObjId ); - } - Cudd_RecursiveDeref( p->dd, bCube ); - } - Cudd_Deref( bImage ); - return bImage; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ManCreateConstraints( Llb_Man_t * p, Vec_Int_t * vHints, int fUseNsVars ) -{ - DdNode * bConstr, * bFunc, * bTemp; - Aig_Obj_t * pObj; - int i, Entry; - if ( vHints == NULL ) - return Cudd_ReadOne( p->dd ); - assert( Aig_ManPiNum(p->pAig) == Aig_ManPiNum(p->pAigGlo) ); - // assign const and PI nodes to the original AIG - Aig_ManCleanData( p->pAig ); - Aig_ManConst1( p->pAig )->pData = Cudd_ReadOne( p->dd ); - Saig_ManForEachPi( p->pAig, pObj, i ) - pObj->pData = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var,Aig_ObjId(pObj)) ); - Saig_ManForEachLo( p->pAig, pObj, i ) - { - if ( fUseNsVars ) - Entry = Vec_IntEntry( p->vObj2Var, Aig_ObjId(Saig_ObjLoToLi(p->pAig, pObj)) ); - else - Entry = Vec_IntEntry( p->vObj2Var, Aig_ObjId(pObj) ); - pObj->pData = Cudd_bddIthVar( p->dd, Entry ); - } - // transfer them to the global AIG - Aig_ManCleanData( p->pAigGlo ); - Aig_ManConst1( p->pAigGlo )->pData = Cudd_ReadOne( p->dd ); - Aig_ManForEachPi( p->pAigGlo, pObj, i ) - pObj->pData = Aig_ManPi(p->pAig, i)->pData; - // derive consraints - bConstr = Cudd_ReadOne( p->dd ); Cudd_Ref( bConstr ); - Vec_IntForEachEntry( vHints, Entry, i ) - { - if ( Entry != 0 && Entry != 1 ) - continue; - bFunc = Llb_ManConstructOutBdd( p->pAigGlo, Aig_ManObj(p->pAigGlo, i), p->dd ); Cudd_Ref( bFunc ); - bFunc = Cudd_NotCond( bFunc, Entry ); // restrict to not constraint - // make the product - bConstr = Cudd_bddAnd( p->dd, bTemp = bConstr, bFunc ); Cudd_Ref( bConstr ); - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bFunc ); - } - Cudd_Deref( bConstr ); - return bConstr; -} - -/**Function************************************************************* - - Synopsis [Perform reachability with hints and returns reached states in ppGlo.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManReachability( Llb_Man_t * p, Vec_Int_t * vHints, DdManager ** pddGlo ) -{ - int 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; - DdNode * bConstrCs, * bConstrNs; - int clk2, clk = clock(), nIters, nBddSize = 0, iOutFail = -1; - int nThreshold = 10000; - - // compute time to stop - if ( p->pPars->TimeLimit ) - p->pPars->TimeTarget = clock() + p->pPars->TimeLimit * CLOCKS_PER_SEC; - else - p->pPars->TimeTarget = 0; - - // define variable limits - Llb_ManPrepareVarLimits( p ); - - // start the managers - assert( p->dd == NULL ); - assert( p->ddG == NULL ); - p->dd = Cudd_Init( Vec_IntSize(p->vVar2Obj), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - if ( pddGlo && *pddGlo ) - p->ddG = *pddGlo, *pddGlo = NULL; - else - p->ddG = Cudd_Init( Aig_ManRegNum(p->pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - - if ( p->pPars->fReorder ) - { - Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); - Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT ); - } - else - { - Cudd_AutodynDisable( p->dd ); - Cudd_AutodynDisable( p->ddG ); - } - - // derive constraints - bConstrCs = Llb_ManCreateConstraints( p, vHints, 0 ); Cudd_Ref( bConstrCs ); - bConstrNs = Llb_ManCreateConstraints( p, vHints, 1 ); Cudd_Ref( bConstrNs ); -//Extra_bddPrint( p->dd, bConstrCs ); printf( "\n" ); -//Extra_bddPrint( p->dd, bConstrNs ); printf( "\n" ); - - // perform reachability analysis - // compute the starting set of states - if ( p->ddG->bReached ) - { - bReached = p->ddG->bReached; p->ddG->bReached = NULL; - bCurrent = Extra_TransferPermute( p->ddG, p->dd, bReached, pGlo2Cs ); Cudd_Ref( bCurrent ); - } - else - { - bReached = Llb_ManComputeInitState( p, p->ddG ); Cudd_Ref( bReached ); - bCurrent = Llb_ManComputeInitState( p, p->dd ); Cudd_Ref( bCurrent ); - } -//Extra_bddPrintSupport( p->ddG, bReached ); printf( "\n" ); -//Extra_bddPrintSupport( p->dd, bCurrent ); printf( "\n" ); - -//Extra_bddPrintSupport( p->dd, bCurrent ); printf( "\n" ); - for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ ) - { - clk2 = 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->dd, bConstrCs ); bConstrCs = NULL; - Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return -1; - } - - // check outputs - if ( fCheckOutputs ) - { - Aig_Obj_t * pObj; - int i; - Aig_ManConst1( p->pAigGlo )->pData = Cudd_ReadOne( p->dd ); - Aig_ManForEachPi( p->pAig, pObj, i ) - pObj->pData = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var,Aig_ObjId(pObj)) ); - Aig_ManForEachPi( p->pAigGlo, pObj, i ) - pObj->pData = Aig_ManPi(p->pAig, i)->pData; - -//Extra_bddPrintSupport( p->dd, bCurrent ); printf( "\n" ); - for ( iOutFail = 0; iOutFail < Saig_ManPoNum(p->pAig); iOutFail++ ) - { - DdNode * bFunc, * bInter; - bFunc = Llb_ManConstructOutBdd( p->pAigGlo, Aig_ManPo(p->pAigGlo, iOutFail), p->dd ); Cudd_Ref( bFunc ); -//Extra_bddPrint( p->dd, bFunc ); printf( "\n" ); - if ( Cudd_bddLeq( p->dd, bCurrent, Cudd_Not(bFunc) ) ) // no cex - { - Cudd_RecursiveDeref( p->dd, bFunc ); - continue; - } - bInter = Cudd_bddIntersect( p->dd, bCurrent, bFunc ); Cudd_Ref( bInter ); - assert( p->pAig->pSeqModel == NULL ); - p->pAig->pSeqModel = Llb_ManDeriveCex( p, bInter, iOutFail, nIters ); - Cudd_RecursiveDeref( p->dd, bInter ); - Cudd_RecursiveDeref( p->dd, bFunc ); - break; - } - if ( iOutFail < Saig_ManPoNum(p->pAig) ) - { - if ( !p->pPars->fSilent ) - printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump a witness). ", iOutFail, nIters ); - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; - p->pPars->iFrame = nIters; - break; - } - } - - // restrict reachable states using constraints - if ( vHints ) - { - bCurrent = Cudd_bddAnd( p->dd, bTemp = bCurrent, bConstrCs ); Cudd_Ref( bCurrent ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - - // quantify variables appearing only in the init state - bCube = Llb_ManConstructQuantCubeIntern( p, (Llb_Grp_t *)Vec_PtrEntry(p->vGroups,0), 0 ); Cudd_Ref( bCube ); - bCurrent = Cudd_bddExistAbstract( p->dd, bTemp = bCurrent, bCube ); Cudd_Ref( bCurrent ); - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bCube ); - - // compute the next states - bNext = Llb_ManComputeImage( p, bCurrent ); - 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->dd, bConstrCs ); bConstrCs = NULL; - Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return -1; - } - Cudd_Ref( bNext ); - Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; - - // restrict reachable states using constraints - if ( vHints ) - { - bNext = Cudd_bddAnd( p->dd, bTemp = bNext, bConstrNs ); Cudd_Ref( bNext ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } -//Extra_bddPrintSupport( p->dd, bNext ); printf( "\n" ); - - // remap these states into the current state vars - bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pNs2Glo ); Cudd_Ref( bNext ); - Cudd_RecursiveDeref( p->dd, bTemp ); - - // check if there are any new states - if ( Cudd_bddLeq( p->ddG, bNext, bReached ) ) // implication = no new states - { - Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; - break; - } - - // check the BDD size - nBddSize = Cudd_DagSize(bNext); - if ( nBddSize > p->pPars->nBddMax ) - { - Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; - break; - } - - // get the new states - bCurrent = Cudd_bddAnd( p->ddG, bNext, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); - // minimize the new states with the reached states -// bCurrent = Cudd_bddConstrain( p->ddG, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); -// bCurrent = Cudd_bddRestrict( p->ddG, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); -// Cudd_RecursiveDeref( p->ddG, bTemp ); -//printf( "Initial BDD =%7d. Constrained BDD =%7d.\n", Cudd_DagSize(bTemp), Cudd_DagSize(bCurrent) ); - // remap these states into the current state vars - bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs ); Cudd_Ref( bCurrent ); - Cudd_RecursiveDeref( p->ddG, bTemp ); - - // 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->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) ); - } - if ( fInternalReorder && p->pPars->fReorder && nBddSize > nThreshold ) - { - 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; - } - 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; - if ( bReached == NULL ) - return 0; // reachable -// assert( bCurrent == NULL ); - if ( bCurrent ) - Cudd_RecursiveDeref( p->dd, bCurrent ); - // report the stats - if ( p->pPars->fVerbose ) - { - double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); - if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) - fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters ); - else - fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters ); - fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); - fflush( stdout ); - } - if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) - { - if ( !p->pPars->fSilent ) - printf( "Verified only for states reachable in %d frames. ", nIters ); - Cudd_RecursiveDeref( p->ddG, bReached ); - return -1; // undecided - } - if ( pddGlo ) - { - assert( p->ddG->bReached == NULL ); - p->ddG->bReached = bReached; bReached = NULL; - assert( *pddGlo == NULL ); - *pddGlo = p->ddG; p->ddG = NULL; - } - else - Cudd_RecursiveDeref( p->ddG, bReached ); - if ( !p->pPars->fSilent ) - printf( "The miter is proved unreachable after %d iterations. ", nIters ); - p->pPars->iFrame = nIters - 1; - return 1; // unreachable -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/aig/llb/llbSched.c b/src/aig/llb/llbSched.c deleted file mode 100644 index 0f7b9fab..00000000 --- a/src/aig/llb/llbSched.c +++ /dev/null @@ -1,257 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Swaps two rows.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrSwapColumns( Llb_Mtr_t * p, int iCol1, int iCol2 ) -{ - Llb_Grp_t * pGemp; - char * pTemp; - int iTemp; - assert( iCol1 >= 0 && iCol1 < p->nCols ); - assert( iCol2 >= 0 && iCol2 < p->nCols ); - if ( iCol1 == iCol2 ) - return; - assert( iCol1 != iCol2 ); - // swap col groups - pGemp = p->pColGrps[iCol1]; - p->pColGrps[iCol1] = p->pColGrps[iCol2]; - p->pColGrps[iCol2] = pGemp; - // swap col vectors - pTemp = p->pMatrix[iCol1]; - p->pMatrix[iCol1] = p->pMatrix[iCol2]; - p->pMatrix[iCol2] = pTemp; - // swap col sums - iTemp = p->pColSums[iCol1]; - p->pColSums[iCol1] = p->pColSums[iCol2]; - p->pColSums[iCol2] = iTemp; -} - -/**Function************************************************************* - - Synopsis [Find columns which brings as few vars as possible.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_MtrFindBestColumn( Llb_Mtr_t * p, int iGrpStart ) -{ - int Cost, Cost2, CostBest = ABC_INFINITY, Cost2Best = ABC_INFINITY; - int WeightCur, WeightBest = -ABC_INFINITY, iGrp, iGrpBest = -1; - int k, c, iVar, Counter; - // find partition that reduces partial product as much as possible - for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ ) - { - if ( p->pRowSums[iVar] < 2 ) - continue; - // look at present variables that can be quantified - if ( !(p->pProdVars[iVar] == 1 && p->pProdNums[iVar] == 1) ) - continue; - // check that it appears in one partition only - Counter = 0; - for ( c = iGrpStart; c < p->nCols-1; c++ ) - if ( p->pMatrix[c][iVar] == 1 ) - { - iGrp = c; - Counter++; - } - assert( Counter == 1 ); - if ( Counter != 1 ) - Abc_Print( -1, "Llb_MtrFindBestColumn() Internal error!\n" ); - // find weight of this column - WeightCur = 0; - for ( k = 0; k < p->nRows; k++ ) - { - // increase weight if variable k will be quantified from partial product - if ( p->pProdVars[k] == 1 && p->pMatrix[iGrp][k] == 1 && p->pProdNums[k] == 1 ) - WeightCur += 2; - // decrease weight if variable k will be added to partial product - if ( p->pProdVars[k] == 0 && p->pMatrix[iGrp][k] == 1 ) - WeightCur--; - } - if ( WeightCur > 0 && WeightBest < WeightCur ) - { - WeightBest = WeightCur; - iGrpBest = iGrp; - } - } - if ( iGrpBest >= 0 ) - return iGrpBest; - // could not find the group with any vars to quantify - // select the group that contains as few extra variables as possible - // if there is a tie, select variables that appear in less groups than others - for ( iGrp = iGrpStart; iGrp < p->nCols-1; iGrp++ ) - { - Cost = Cost2 = 0; - for ( k = 0; k < p->nRows; k++ ) - if ( p->pProdVars[k] == 0 && p->pMatrix[iGrp][k] == 1 ) - { - Cost++; - Cost2 += p->pProdNums[k]; - } - if ( CostBest > Cost || - (CostBest == Cost && Cost2 > Cost2Best) ) - { - CostBest = Cost; - Cost2Best = Cost2; - iGrpBest = iGrp; - } - } - return iGrpBest; -} - -/**Function************************************************************* - - Synopsis [Returns the number of variables that will be saved.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrUseSelectedColumn( Llb_Mtr_t * p, int iCol ) -{ - int iVar; - assert( iCol >= 1 && iCol < p->nCols - 1 ); - for ( iVar = 0; iVar < p->nRows; iVar++ ) - { - if ( p->pMatrix[iCol][iVar] == 0 ) - continue; - if ( p->pProdVars[iVar] == 1 && p->pProdNums[iVar] == 1 ) - { - p->pProdVars[iVar] = 0; - p->pProdNums[iVar] = 0; - continue; - } - if ( p->pProdVars[iVar] == 0 ) - { - p->pProdVars[iVar] = 1; - p->pProdNums[iVar] = p->pRowSums[iVar]; - } - p->pProdNums[iVar]--; - assert( p->pProdNums[iVar] >= 0 ); - if ( p->pProdNums[iVar] < 0 ) - Abc_Print( -1, "Llb_MtrUseSelectedColumn() Internal error!\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Verify columns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrVerifyColumns( Llb_Mtr_t * p, int iGrpStart ) -{ - int iVar, iGrp, Counter; - for ( iVar = 0; iVar < p->nRows; iVar++ ) - { - if ( p->pProdVars[iVar] == 0 ) - continue; - Counter = 0; - for ( iGrp = iGrpStart; iGrp < p->nCols; iGrp++ ) - if ( p->pMatrix[iGrp][iVar] == 1 ) - Counter++; - assert( Counter == p->pProdNums[iVar] ); - if ( Counter != p->pProdNums[iVar] ) - Abc_Print( -1, "Llb_MtrVerifyColumns(): Internal error.\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Matrix reduce.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrSchedule( Llb_Mtr_t * p ) -{ - int iGrp, iGrpBest, i; - // start partial product - for ( i = 0; i < p->nRows; i++ ) - { - if ( i >= p->nPis && i < p->nPis + p->nFfs ) - { - p->pProdVars[i] = 1; - p->pProdNums[i] = p->pRowSums[i] - 1; - } - else - { - p->pProdVars[i] = 0; - p->pProdNums[i] = p->pRowSums[i]; - } - } - // order the partitions - Llb_MtrVerifyMatrix( p ); - for ( iGrp = 1; iGrp < p->nCols-1; iGrp++ ) - { - Llb_MtrVerifyColumns( p, iGrp ); - iGrpBest = Llb_MtrFindBestColumn( p, iGrp ); - Llb_MtrUseSelectedColumn( p, iGrpBest ); - Llb_MtrSwapColumns( p, iGrp, iGrpBest ); - } - Llb_MtrVerifyMatrix( p ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/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 @@ -145,6 +145,32 @@ Aig_Man_t * Saig_ManTemporDecompose( Aig_Man_t * pAig, int nFrames ) return pAigNew; } +/**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 [] @@ -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 ] [-bvwh]\n" ); + Abc_Print( -2, "usage: tempor [-FTC ] [-bsvwh]\n" ); Abc_Print( -2, "\t performs temporal decomposition\n" ); Abc_Print( -2, "\t-F : init logic timeframe count (0 = use leading length) [default = %d]\n", nFrames ); Abc_Print( -2, "\t-T : runtime limit in seconds for BMC (0=unused) [default = %d]\n", TimeOut ); Abc_Print( -2, "\t-C : 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 ); @@ -27613,6 +27620,276 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + 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 [] 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 + limit, 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/hashGen.h b/src/misc/hash/hashGen.h new file mode 100644 index 00000000..e88fa497 --- /dev/null +++ b/src/misc/hash/hashGen.h @@ -0,0 +1,360 @@ +/**CFile**************************************************************** + + FileName [vecGen.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Hash maps.] + + Synopsis [Hash maps.] + + Author [Aaron P. Hurst, Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Jan 26, 2011.] + + Revision [$Id: vecGen.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $] + +***********************************************************************/ + +#ifndef __HASH_GEN_H__ +#define __HASH_GEN_H__ + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include "extra.h" + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Hash_Gen_t_ Hash_Gen_t; +typedef struct Hash_Gen_Entry_t_ Hash_Gen_Entry_t; + +struct Hash_Gen_Entry_t_ +{ + char * key; + void * data; + struct Hash_Gen_Entry_t_ * pNext; +}; + +struct Hash_Gen_t_ +{ + int nSize; + int nBins; + int (* fHash)(void * key, int nBins); + int (* fComp)(void * key, void * key); + Hash_Gen_Entry_t ** pArray; +}; + + + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define Hash_GenForEachEntry( pHash, pEntry, bin ) \ + for(bin=-1, pEntry=NULL; bin < pHash->nBins; (!pEntry)?(pEntry=pHash->pArray[++bin]):(pEntry=pEntry->pNext)) \ + if (pEntry) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Default hash function for strings.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Hash_DefaultHashFuncStr( void * key, int nBins ) +{ + int i, Value = 0; + if ( key[0] == 0 ) + return 0; + for ( i = strlen(key)-1; i >= 0; i-- ) + Value = 5 * Value + key[i]; + return Value % nBins; +} + +/**Function************************************************************* + + Synopsis [Allocates a hash map with the given number of bins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Hash_Gen_t * Hash_GenAlloc( + int nBins, + int (*Hash_FuncHash)(void *, int), + int (*Hash_FuncComp)(void *, void *) ) +{ + Hash_Gen_t * p; + int i; + assert(nBins > 0); + p = ABC_CALLOC( Hash_Gen_t, 1 ); + p->nBins = nBins; + p->fHash = Hash_FuncHash? Hash_FuncHash : (int (*)(void *, int))Hash_DefaultHashFuncStr; + p->fComp = Hash_FuncComp? Hash_FuncComp : (int (*)(void *, void *))strcmp; + p->nSize = 0; + p->pArray = ABC_CALLOC( Hash_Gen_Entry_t *, nBins ); + return p; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if a key already exists.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Hash_GenExists( Hash_Gen_t *p, void * key ) +{ + int bin; + Hash_Gen_Entry_t *pEntry; + + // find the bin where this key would live + bin = (*(p->fHash))(key, p->nBins); + + // search for key + pEntry = p->pArray[bin]; + while(pEntry) { + if ( !p->fComp(pEntry->key,key) ) { + return 1; + } + pEntry = pEntry->pNext; + } + + return 0; +} + +/**Function************************************************************* + + Synopsis [Finds or creates an entry with a key and writes value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Hash_GenWriteEntry( Hash_Gen_t *p, void * key, void * data ) +{ + int bin; + Hash_Gen_Entry_t *pEntry, **pLast; + + // 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 ( !p->fComp(pEntry->key,key) ) { + pEntry->data = data; + return; + } + pLast = &(pEntry->pNext); + pEntry = pEntry->pNext; + } + + // this key does not currently exist + // create a new entry and add to bin + p->nSize++; + (*pLast) = pEntry = ABC_ALLOC( Hash_Gen_Entry_t, 1 ); + pEntry->pNext = NULL; + pEntry->key = key; + pEntry->data = data; + + return; +} + + +/**Function************************************************************* + + Synopsis [Finds or creates an entry with a key.] + + Description [fCreate specifies whether a new entry should be created.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void * Hash_GenEntry( Hash_Gen_t *p, void * key, int fCreate ) +{ + int bin; + Hash_Gen_Entry_t *pEntry, **pLast; + + // 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 ( !p->fComp(pEntry->key,key) ) + return pEntry->data; + pLast = &(pEntry->pNext); + pEntry = pEntry->pNext; + } + + // this key does not currently exist + if (fCreate) { + // create a new entry and add to bin + p->nSize++; + (*pLast) = pEntry = ABC_ALLOC( Hash_Gen_Entry_t, 1 ); + pEntry->pNext = NULL; + pEntry->key = key; + pEntry->data = NULL; + return pEntry->data; + } + + return NULL; +} + + +/**Function************************************************************* + + Synopsis [Finds or creates an entry with a key and returns the pointer to it.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void** Hash_GenEntryPtr( Hash_Gen_t *p, void * key ) +{ + int bin; + Hash_Gen_Entry_t *pEntry, **pLast; + + // 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 ( !p->fComp(pEntry->key,key) ) + return &(pEntry->data); + pLast = &(pEntry->pNext); + pEntry = pEntry->pNext; + } + + // this key does not currently exist + // create a new entry and add to bin + p->nSize++; + (*pLast) = pEntry = ABC_ALLOC( Hash_Gen_Entry_t, 1 ); + pEntry->pNext = NULL; + pEntry->key = key; + pEntry->data = NULL; + + return &(pEntry->data); +} + +/**Function************************************************************* + + Synopsis [Deletes an entry.] + + Description [Returns data, if there was any.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void* Hash_GenRemove( Hash_Gen_t *p, void * key ) +{ + int bin; + void * data; + Hash_Gen_Entry_t *pEntry, **pLast; + + // 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 ( !p->fComp(pEntry->key,key) ) { + p->nSize--; + data = pEntry->data; + *pLast = pEntry->pNext; + return data; + } + pLast = &(pEntry->pNext); + pEntry = pEntry->pNext; + } + + // could not find key + return NULL; +} + +/**Function************************************************************* + + Synopsis [Frees the hash.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Hash_GenFree( Hash_Gen_t *p ) +{ + int bin; + Hash_Gen_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( pTemp ); + } + } + + // free hash + ABC_FREE( p->pArray ); + ABC_FREE( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_END + +#endif 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 ); } } -- cgit v1.2.3