diff options
Diffstat (limited to 'src/bdd/llb')
28 files changed, 12634 insertions, 0 deletions
diff --git a/src/bdd/llb/llb.c b/src/bdd/llb/llb.c new file mode 100644 index 00000000..348c0622 --- /dev/null +++ b/src/bdd/llb/llb.c @@ -0,0 +1,52 @@ +/**CFile**************************************************************** + + FileName [llb.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb.h b/src/bdd/llb/llb.h new file mode 100644 index 00000000..f465359d --- /dev/null +++ b/src/bdd/llb/llb.h @@ -0,0 +1,96 @@ +/**CFile**************************************************************** + + FileName [llb.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD-based reachability.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 8, 2010.] + + Revision [$Id: llb.h,v 1.00 2010/05/08 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__llb__llb_h +#define ABC__aig__llb__llb_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Gia_ParLlb_t_ Gia_ParLlb_t; +struct Gia_ParLlb_t_ +{ + int nBddMax; // maximum BDD size + int nIterMax; // maximum iteration count + int nClusterMax; // maximum cluster size + int nHintDepth; // the number of times to cofactor + int HintFirst; // the number of first hint to use + int fUseFlow; // use flow computation + int nVolumeMax; // the largest volume + int nVolumeMin; // the smallest volume + int nPartValue; // partitioning value + int fBackward; // enable backward reachability + int fReorder; // enable dynamic variable reordering + int fIndConstr; // extract inductive constraints + int fUsePivots; // use internal pivot variables + int fCluster; // use partition clustering + int fSchedule; // use cluster scheduling + int fDumpReached; // dump reached states into a file + int fVerbose; // print verbose information + int fVeryVerbose; // print dependency matrices + int fSilent; // do not print any infomation + int fSkipReach; // skip reachability (preparation phase only) + int fSkipOutCheck; // does not check the property output + int TimeLimit; // time limit for one reachability run + int TimeLimitGlo; // time limit for all reachability runs + // internal parameters + abctime TimeTarget; // the time to stop + int iFrame; // explored up to this frame +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== llbCore.c ==========================================================*/ +extern void Llb_ManSetDefaultParams( Gia_ParLlb_t * pPars ); +/*=== llb4Nonlin.c ==========================================================*/ +extern int Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/bdd/llb/llb1Cluster.c b/src/bdd/llb/llb1Cluster.c new file mode 100644 index 00000000..1356e484 --- /dev/null +++ b/src/bdd/llb/llb1Cluster.c @@ -0,0 +1,356 @@ +/**CFile**************************************************************** + + FileName [llb1Cluster.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Clustering algorithm.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Cluster.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManComputeCommonQuant( Llb_Mtr_t * p, int iCol1, int iCol2 ) +{ + int iVar, Weight = 0; + for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ ) + { + // count each removed variable as 2 + if ( p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 1 && p->pRowSums[iVar] == 2 ) + Weight += 2; + // count each added variale as -1 + else if ( (p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 0) || + (p->pMatrix[iCol1][iVar] == 0 && p->pMatrix[iCol2][iVar] == 1) ) + Weight--; + } + return Weight; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManComputeBestQuant( Llb_Mtr_t * p ) +{ + int i, k, WeightBest = -100000, WeightCur, RetValue = -1; + for ( i = 1; i < p->nCols-1; i++ ) + for ( k = i+1; k < p->nCols-1; k++ ) + { + if ( p->pColSums[i] == 0 || p->pColSums[i] > p->pMan->pPars->nClusterMax ) + continue; + if ( p->pColSums[k] == 0 || p->pColSums[k] > p->pMan->pPars->nClusterMax ) + continue; + + WeightCur = Llb_ManComputeCommonQuant( p, i, k ); + if ( WeightCur <= 0 ) + continue; + if ( WeightBest < WeightCur ) + { + WeightBest = WeightCur; + RetValue = (i << 16) | k; + } + } +// printf( "Choosing best quant Weight %4d\n", WeightCur ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float ** Llb_ManComputeQuant( Llb_Mtr_t * p ) +{ + float ** pCosts; + int i, k; + // alloc and clean + pCosts = (float **)Extra_ArrayAlloc( p->nCols, p->nCols, sizeof(float) ); + for ( i = 0; i < p->nCols; i++ ) + for ( k = 0; k < p->nCols; k++ ) + pCosts[i][i] = 0.0; + // fill up + for ( i = 1; i < p->nCols-1; i++ ) + for ( k = i+1; k < p->nCols-1; k++ ) + pCosts[i][k] = pCosts[k][i] = Llb_ManComputeCommonQuant( p, i, k ); + return pCosts; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Llb_ManComputeCommonAttr( Llb_Mtr_t * p, int iCol1, int iCol2 ) +{ + int iVar, CountComm = 0, CountDiff = 0; + for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ ) + { + if ( p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 1 ) + CountComm++; + else if ( p->pMatrix[iCol1][iVar] == 1 || p->pMatrix[iCol2][iVar] == 1 ) + CountDiff++; + } +/* + printf( "Attr cost for %4d and %4d: %4d %4d (%5.2f)\n", + iCol1, iCol2, + CountDiff, CountComm, + -1.0 * CountDiff / ( CountComm + CountDiff ) ); +*/ + return -1.0 * CountDiff / ( CountComm + CountDiff ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManComputeBestAttr( Llb_Mtr_t * p ) +{ + float WeightBest = -100000, WeightCur; + int i, k, RetValue = -1; + for ( i = 1; i < p->nCols-1; i++ ) + for ( k = i+1; k < p->nCols-1; k++ ) + { + if ( p->pColSums[i] == 0 || p->pColSums[i] > p->pMan->pPars->nClusterMax ) + continue; + if ( p->pColSums[k] == 0 || p->pColSums[k] > p->pMan->pPars->nClusterMax ) + continue; + WeightCur = Llb_ManComputeCommonAttr( p, i, k ); + if ( WeightBest < WeightCur ) + { + WeightBest = WeightCur; + RetValue = (i << 16) | k; + } + } + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float ** Llb_ManComputeAttr( Llb_Mtr_t * p ) +{ + float ** pCosts; + int i, k; + // alloc and clean + pCosts = (float **)Extra_ArrayAlloc( p->nCols, p->nCols, sizeof(float) ); + for ( i = 0; i < p->nCols; i++ ) + for ( k = 0; k < p->nCols; k++ ) + pCosts[i][i] = 0.0; + // fill up + for ( i = 1; i < p->nCols-1; i++ ) + for ( k = i+1; k < p->nCols-1; k++ ) + pCosts[i][k] = pCosts[k][i] = Llb_ManComputeCommonAttr( p, i, k ); + return pCosts; +} + + +/**Function************************************************************* + + Synopsis [Returns the number of variables that will be saved.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrCombineSelectedColumns( Llb_Mtr_t * p, int iGrp1, int iGrp2 ) +{ + int iVar; + assert( iGrp1 >= 1 && iGrp1 < p->nCols - 1 ); + assert( iGrp2 >= 1 && iGrp2 < p->nCols - 1 ); + assert( p->pColGrps[iGrp1] != NULL ); + assert( p->pColGrps[iGrp2] != NULL ); + for ( iVar = 0; iVar < p->nRows; iVar++ ) + { + if ( p->pMatrix[iGrp1][iVar] == 1 && p->pMatrix[iGrp2][iVar] == 1 ) + p->pRowSums[iVar]--; + if ( p->pMatrix[iGrp1][iVar] == 0 && p->pMatrix[iGrp2][iVar] == 1 ) + { + p->pMatrix[iGrp1][iVar] = 1; + p->pColSums[iGrp1]++; + } + if ( p->pMatrix[iGrp2][iVar] == 1 ) + p->pMatrix[iGrp2][iVar] = 0; + } + p->pColSums[iGrp2] = 0; +} + + +/**Function************************************************************* + + Synopsis [Combines one pair of columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManClusterOne( Llb_Mtr_t * p, int iCol1, int iCol2 ) +{ + int fVerbose = 0; + Llb_Grp_t * pGrp; + int iVar; + + if ( fVerbose ) + { + printf( "Combining %d and %d\n", iCol1, iCol2 ); + for ( iVar = 0; iVar < p->nRows; iVar++ ) + { + if ( p->pMatrix[iCol1][iVar] == 0 && p->pMatrix[iCol2][iVar] == 0 ) + continue; + printf( "%3d : %c%c\n", iVar, + p->pMatrix[iCol1][iVar]? '*':' ', + p->pMatrix[iCol2][iVar]? '*':' ' ); + } + } + pGrp = Llb_ManGroupsCombine( p->pColGrps[iCol1], p->pColGrps[iCol2] ); + Llb_MtrCombineSelectedColumns( p, iCol1, iCol2 ); + p->pColGrps[iCol1] = pGrp; + p->pColGrps[iCol2] = NULL; +} + +/**Function************************************************************* + + Synopsis [Removes empty columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManClusterCompress( Llb_Mtr_t * p ) +{ + int i, k = 0; + for ( i = 0; i < p->nCols; i++ ) + { + if ( p->pColGrps[i] == NULL ) + { + assert( p->pColSums[i] == 0 ); + assert( p->pMatrix[i] != NULL ); + ABC_FREE( p->pMatrix[i] ); + continue; + } + p->pMatrix[k] = p->pMatrix[i]; + p->pColGrps[k] = p->pColGrps[i]; + p->pColSums[k] = p->pColSums[i]; + k++; + } + p->nCols = k; +} + +/**Function************************************************************* + + Synopsis [Combines one pair of columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManCluster( Llb_Mtr_t * p ) +{ + int RetValue; + do + { + do { + RetValue = Llb_ManComputeBestQuant( p ); + if ( RetValue > 0 ) + Llb_ManClusterOne( p, RetValue >> 16, RetValue & 0xffff ); + } + while ( RetValue > 0 ); + + RetValue = Llb_ManComputeBestAttr( p ); + if ( RetValue > 0 ) + Llb_ManClusterOne( p, RetValue >> 16, RetValue & 0xffff ); + + Llb_MtrVerifyMatrix( p ); + } + while ( RetValue > 0 ); + + Llb_ManClusterCompress( p ); + + Llb_MtrVerifyMatrix( p ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb1Constr.c b/src/bdd/llb/llb1Constr.c new file mode 100644 index 00000000..1ef4ce14 --- /dev/null +++ b/src/bdd/llb/llb1Constr.c @@ -0,0 +1,313 @@ +/**CFile**************************************************************** + + FileName [llb1Constr.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Computing inductive constraints.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Constr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the array of constraint candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManCountEntries( Vec_Int_t * vCands ) +{ + int i, Entry, Counter = 0; + Vec_IntForEachEntry( vCands, Entry, i ) + Counter += ((Entry == 0) || (Entry == 1)); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns the array of constraint candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrintEntries( Aig_Man_t * p, Vec_Int_t * vCands ) +{ + int i, Entry; + if ( vCands == NULL ) + { + printf( "There is no hints.\n" ); + return; + } + Entry = Llb_ManCountEntries(vCands); + printf( "\n*** Using %d hint%s:\n", Entry, (Entry != 1 ? "s":"") ); + Vec_IntForEachEntry( vCands, Entry, i ) + { + if ( Entry != 0 && Entry != 1 ) + continue; + printf( "%c", Entry ? '+' : '-' ); + printf( "%-6d : ", i ); + Aig_ObjPrint( p, Aig_ManObj(p, i) ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Dereference BDD nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManDerefenceBdds( Aig_Man_t * p, DdManager * dd ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachObj( p, pObj, i ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); +} + +/**Function************************************************************* + + Synopsis [Returns the array of constraint candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManComputeIndCase_rec( Aig_Man_t * p, Aig_Obj_t * pObj, DdManager * dd, Vec_Ptr_t * vBdds ) +{ + DdNode * bBdd0, * bBdd1; + DdNode * bFunc = (DdNode *)Vec_PtrEntry( vBdds, Aig_ObjId(pObj) ); + if ( bFunc != NULL ) + return bFunc; + assert( Aig_ObjIsNode(pObj) ); + bBdd0 = Llb_ManComputeIndCase_rec( p, Aig_ObjFanin0(pObj), dd, vBdds ); + bBdd1 = Llb_ManComputeIndCase_rec( p, Aig_ObjFanin1(pObj), dd, vBdds ); + bBdd0 = Cudd_NotCond( bBdd0, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( bBdd1, Aig_ObjFaninC1(pObj) ); + bFunc = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bFunc ); + Vec_PtrWriteEntry( vBdds, Aig_ObjId(pObj), bFunc ); + return bFunc; +} + +/**Function************************************************************* + + Synopsis [Returns the array of constraint candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManComputeIndCase( Aig_Man_t * p, DdManager * dd, Vec_Int_t * vNodes ) +{ + Vec_Ptr_t * vBdds; + Aig_Obj_t * pObj; + DdNode * bFunc; + int i, Entry; + vBdds = Vec_PtrStart( Aig_ManObjNumMax(p) ); + bFunc = Cudd_ReadOne(dd); Cudd_Ref( bFunc ); + Vec_PtrWriteEntry( vBdds, Aig_ObjId(Aig_ManConst1(p)), bFunc ); + Saig_ManForEachPi( p, pObj, i ) + { + bFunc = Cudd_bddIthVar( dd, Aig_ManCiNum(p) + i ); Cudd_Ref( bFunc ); + Vec_PtrWriteEntry( vBdds, Aig_ObjId(pObj), bFunc ); + } + Saig_ManForEachLi( p, pObj, i ) + { + bFunc = (DdNode *)pObj->pData; Cudd_Ref( bFunc ); + Vec_PtrWriteEntry( vBdds, Aig_ObjId(Saig_ObjLiToLo(p, pObj)), bFunc ); + } + Vec_IntForEachEntry( vNodes, Entry, i ) + { + if ( Entry != 0 && Entry != 1 ) + continue; + pObj = Aig_ManObj( p, i ); + bFunc = Llb_ManComputeIndCase_rec( p, pObj, dd, vBdds ); + if ( Entry == 0 ) + { +// Extra_bddPrint( dd, Cudd_Not(pObj->pData) ); printf( "\n" ); +// Extra_bddPrint( dd, Cudd_Not(bFunc) ); printf( "\n" ); + if ( !Cudd_bddLeq( dd, Cudd_Not(pObj->pData), Cudd_Not(bFunc) ) ) + Vec_IntWriteEntry( vNodes, i, -1 ); + } + else if ( Entry == 1 ) + { +// Extra_bddPrint( dd, pObj->pData ); printf( "\n" ); +// Extra_bddPrint( dd, bFunc ); printf( "\n" ); + if ( !Cudd_bddLeq( dd, (DdNode *)pObj->pData, bFunc ) ) + Vec_IntWriteEntry( vNodes, i, -1 ); + } + } + Vec_PtrForEachEntry( DdNode *, vBdds, bFunc, i ) + if ( bFunc ) + Cudd_RecursiveDeref( dd, bFunc ); + Vec_PtrFree( vBdds ); +} + +/**Function************************************************************* + + Synopsis [Returns the array of constraint candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_ManComputeBaseCase( Aig_Man_t * p, DdManager * dd ) +{ + Vec_Int_t * vNodes; + Aig_Obj_t * pObj, * pRoot; + int i; + pRoot = Aig_ManCo( p, 0 ); + vNodes = Vec_IntStartFull( Aig_ManObjNumMax(p) ); + Aig_ManForEachObj( p, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) ) + continue; + if ( Cudd_bddLeq( dd, (DdNode *)pObj->pData, Cudd_Not(pRoot->pData) ) ) + Vec_IntWriteEntry( vNodes, i, 1 ); + else if ( Cudd_bddLeq( dd, Cudd_Not((DdNode *)pObj->pData), Cudd_Not(pRoot->pData) ) ) + Vec_IntWriteEntry( vNodes, i, 0 ); + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Constructs global BDDs for each object in the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdManager * Llb_ManConstructGlobalBdds( Aig_Man_t * p ) +{ + DdManager * dd; + DdNode * bBdd0, * bBdd1; + Aig_Obj_t * pObj; + int i; + dd = Cudd_Init( Aig_ManCiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + pObj = Aig_ManConst1(p); + pObj->pData = Cudd_ReadOne(dd); Cudd_Ref( (DdNode *)pObj->pData ); + Aig_ManForEachCi( p, pObj, i ) + { + pObj->pData = Cudd_bddIthVar(dd, i); Cudd_Ref( (DdNode *)pObj->pData ); + } + Aig_ManForEachNode( p, pObj, i ) + { + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); + pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData ); + } + Aig_ManForEachCo( p, pObj, i ) + { + pObj->pData = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); Cudd_Ref( (DdNode *)pObj->pData ); + } + return dd; +} + +/**Function************************************************************* + + Synopsis [Derives inductive constraints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_ManDeriveConstraints( Aig_Man_t * p ) +{ + DdManager * dd; + Vec_Int_t * vNodes; + if ( Saig_ManPoNum(p) != 1 ) + { + printf( "The AIG has %d property outputs.\n", Saig_ManPoNum(p) ); + return NULL; + } + assert( Saig_ManPoNum(p) == 1 ); + dd = Llb_ManConstructGlobalBdds( p ); + vNodes = Llb_ManComputeBaseCase( p, dd ); + if ( Llb_ManCountEntries(vNodes) > 0 ) + Llb_ManComputeIndCase( p, dd, vNodes ); + if ( Llb_ManCountEntries(vNodes) == 0 ) + Vec_IntFreeP( &vNodes ); + Llb_ManDerefenceBdds( p, dd ); + Extra_StopManager( dd ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Tests derived constraints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManConstrTest( Aig_Man_t * p ) +{ + Vec_Int_t * vNodes; + vNodes = Llb_ManDeriveConstraints( p ); + Llb_ManPrintEntries( p, vNodes ); + Vec_IntFreeP( &vNodes ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb1Core.c b/src/bdd/llb/llb1Core.c new file mode 100644 index 00000000..213f2cd9 --- /dev/null +++ b/src/bdd/llb/llb1Core.c @@ -0,0 +1,222 @@ +/**CFile**************************************************************** + + FileName [llb1Core.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Top-level procedure.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Core.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" +#include "aig/gia/gia.h" +#include "aig/gia/giaAig.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManSetDefaultParams( Gia_ParLlb_t * p ) +{ + memset( p, 0, sizeof(Gia_ParLlb_t) ); + p->nBddMax = 10000000; + p->nIterMax = 10000000; + p->nClusterMax = 20; + p->nHintDepth = 0; + p->HintFirst = 0; + p->fUseFlow = 0; // use flow + p->nVolumeMax = 100; // max volume + p->nVolumeMin = 30; // min volume + p->nPartValue = 5; // partitioning value + p->fBackward = 0; // forward by default + p->fReorder = 1; + p->fIndConstr = 0; + p->fUsePivots = 0; + p->fCluster = 0; + p->fSchedule = 0; + p->fDumpReached = 0; + p->fVerbose = 0; + p->fVeryVerbose = 0; + p->fSilent = 0; + p->TimeLimit = 0; +// p->TimeLimit = 0; + p->TimeLimitGlo = 0; + p->TimeTarget = 0; + p->iFrame = -1; +} + + +/**Function************************************************************* + + Synopsis [Prints statistics about MFFCs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrintAig( Llb_Man_t * p ) +{ + Abc_Print( 1, "pi =%3d ", Saig_ManPiNum(p->pAig) ); + Abc_Print( 1, "po =%3d ", Saig_ManPoNum(p->pAig) ); + Abc_Print( 1, "ff =%3d ", Saig_ManRegNum(p->pAig) ); + Abc_Print( 1, "int =%5d ", Vec_IntSize(p->vVar2Obj)-Aig_ManCiNum(p->pAig)-Saig_ManRegNum(p->pAig) ); + Abc_Print( 1, "var =%5d ", Vec_IntSize(p->vVar2Obj) ); + Abc_Print( 1, "part =%5d ", Vec_PtrSize(p->vGroups)-2 ); + Abc_Print( 1, "and =%5d ", Aig_ManNodeNum(p->pAig) ); + Abc_Print( 1, "lev =%4d ", Aig_ManLevelNum(p->pAig) ); +// Abc_Print( 1, "cut =%4d ", Llb_ManCrossCut(p->pAig) ); + Abc_Print( 1, "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManModelCheckAig( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars, Vec_Int_t * vHints, DdManager ** pddGlo ) +{ + Llb_Man_t * p = NULL; + Aig_Man_t * pAig; + int RetValue = -1; + abctime clk = Abc_Clock(); + + if ( pPars->fIndConstr ) + { + assert( vHints == NULL ); + vHints = Llb_ManDeriveConstraints( pAigGlo ); + } + + // derive AIG for hints + if ( vHints == NULL ) + pAig = Aig_ManDupSimple( pAigGlo ); + else + { + if ( pPars->fVerbose ) + Llb_ManPrintEntries( pAigGlo, vHints ); + pAig = Aig_ManDupSimpleWithHints( pAigGlo, vHints ); + } + + + if ( pPars->fUseFlow ) + { +// p = Llb_ManStartFlow( pAigGlo, pAig, pPars ); + } + else + { + p = Llb_ManStart( pAigGlo, pAig, pPars ); + if ( pPars->fVerbose ) + { + Llb_ManPrintAig( p ); + printf( "Original matrix: " ); + Llb_MtrPrintMatrixStats( p->pMatrix ); + if ( pPars->fVeryVerbose ) + Llb_MtrPrint( p->pMatrix, 1 ); + } + if ( pPars->fCluster ) + { + Llb_ManCluster( p->pMatrix ); + if ( pPars->fVerbose ) + { + printf( "Matrix after clustering: " ); + Llb_MtrPrintMatrixStats( p->pMatrix ); + if ( pPars->fVeryVerbose ) + Llb_MtrPrint( p->pMatrix, 1 ); + } + } + if ( pPars->fSchedule ) + { + Llb_MtrSchedule( p->pMatrix ); + if ( pPars->fVerbose ) + { + printf( "Matrix after scheduling: " ); + Llb_MtrPrintMatrixStats( p->pMatrix ); + if ( pPars->fVeryVerbose ) + Llb_MtrPrint( p->pMatrix, 1 ); + } + } + } + + if ( !p->pPars->fSkipReach ) + RetValue = Llb_ManReachability( p, vHints, pddGlo ); + Llb_ManStop( p ); + + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + + if ( pPars->fIndConstr ) + Vec_IntFreeP( &vHints ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManModelCheckGia( Gia_Man_t * pGia, Gia_ParLlb_t * pPars ) +{ + Gia_Man_t * pGia2; + Aig_Man_t * pAig; + int RetValue = -1; + pGia2 = Gia_ManDupDfs( pGia ); + pAig = Gia_ManToAigSimple( pGia2 ); + Gia_ManStop( pGia2 ); +//Aig_ManShow( pAig, 0, NULL ); + + if ( pPars->nHintDepth == 0 ) + RetValue = Llb_ManModelCheckAig( pAig, pPars, NULL, NULL ); + else + RetValue = Llb_ManModelCheckAigWithHints( pAig, pPars ); + pGia->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL; + Aig_ManStop( pAig ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb1Group.c b/src/bdd/llb/llb1Group.c new file mode 100644 index 00000000..1099b2cd --- /dev/null +++ b/src/bdd/llb/llb1Group.c @@ -0,0 +1,474 @@ +/**CFile**************************************************************** + + FileName [llb1Group.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Initial partition computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Group.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Grp_t * Llb_ManGroupAlloc( Llb_Man_t * pMan ) +{ + Llb_Grp_t * p; + p = ABC_CALLOC( Llb_Grp_t, 1 ); + p->pMan = pMan; + p->vIns = Vec_PtrAlloc( 8 ); + p->vOuts = Vec_PtrAlloc( 8 ); + p->Id = Vec_PtrSize( pMan->vGroups ); + Vec_PtrPush( pMan->vGroups, p ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManGroupStop( Llb_Grp_t * p ) +{ + if ( p == NULL ) + return; + Vec_PtrWriteEntry( p->pMan->vGroups, p->Id, NULL ); + Vec_PtrFreeP( &p->vIns ); + Vec_PtrFreeP( &p->vOuts ); + Vec_PtrFreeP( &p->vNodes ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManGroupCollect_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return; + Aig_ObjSetTravIdCurrent(pAig, pObj); + if ( Aig_ObjIsConst1(pObj) ) + return; + if ( Aig_ObjIsCo(pObj) ) + { + Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin0(pObj), vNodes ); + return; + } + assert( Aig_ObjIsAnd(pObj) ); + Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin0(pObj), vNodes ); + Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin1(pObj), vNodes ); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Collects the support of MFFC.] + + Description [Returns the number of internal nodes in the MFFC.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManGroupCollect( Llb_Grp_t * pGroup ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + vNodes = Vec_PtrAlloc( 100 ); + Aig_ManIncrementTravId( pGroup->pMan->pAig ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) + Aig_ObjSetTravIdCurrent( pGroup->pMan->pAig, pObj ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + Aig_ObjSetTravIdPrevious( pGroup->pMan->pAig, pObj ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + Llb_ManGroupCollect_rec( pGroup->pMan->pAig, pObj, vNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManGroupCreate_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vSupp ) +{ + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return; + Aig_ObjSetTravIdCurrent(pAig, pObj); + if ( Aig_ObjIsConst1(pObj) ) + return; + if ( pObj->fMarkA ) + { + Vec_PtrPush( vSupp, pObj ); + return; + } + assert( Aig_ObjIsAnd(pObj) ); + Llb_ManGroupCreate_rec( pAig, Aig_ObjFanin0(pObj), vSupp ); + Llb_ManGroupCreate_rec( pAig, Aig_ObjFanin1(pObj), vSupp ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Grp_t * Llb_ManGroupCreate( Llb_Man_t * pMan, Aig_Obj_t * pObj ) +{ + Llb_Grp_t * p; + assert( pObj->fMarkA == 1 ); + // derive group + p = Llb_ManGroupAlloc( pMan ); + Vec_PtrPush( p->vOuts, pObj ); + Aig_ManIncrementTravId( pMan->pAig ); + if ( Aig_ObjIsCo(pObj) ) + Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin0(pObj), p->vIns ); + else + { + Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin0(pObj), p->vIns ); + Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin1(pObj), p->vIns ); + } + // derive internal objects + assert( p->vNodes == NULL ); + p->vNodes = Llb_ManGroupCollect( p ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Grp_t * Llb_ManGroupCreateFirst( Llb_Man_t * pMan ) +{ + Llb_Grp_t * p; + Aig_Obj_t * pObj; + int i; + p = Llb_ManGroupAlloc( pMan ); + Saig_ManForEachLo( pMan->pAig, pObj, i ) + Vec_PtrPush( p->vOuts, pObj ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Grp_t * Llb_ManGroupCreateLast( Llb_Man_t * pMan ) +{ + Llb_Grp_t * p; + Aig_Obj_t * pObj; + int i; + p = Llb_ManGroupAlloc( pMan ); + Saig_ManForEachLi( pMan->pAig, pObj, i ) + Vec_PtrPush( p->vIns, pObj ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Grp_t * Llb_ManGroupsCombine( Llb_Grp_t * p1, Llb_Grp_t * p2 ) +{ + Llb_Grp_t * p; + Aig_Obj_t * pObj; + int i; + p = Llb_ManGroupAlloc( p1->pMan ); + // create inputs + Vec_PtrForEachEntry( Aig_Obj_t *, p1->vIns, pObj, i ) + Vec_PtrPush( p->vIns, pObj ); + Vec_PtrForEachEntry( Aig_Obj_t *, p2->vIns, pObj, i ) + Vec_PtrPushUnique( p->vIns, pObj ); + // create outputs + Vec_PtrForEachEntry( Aig_Obj_t *, p1->vOuts, pObj, i ) + Vec_PtrPush( p->vOuts, pObj ); + Vec_PtrForEachEntry( Aig_Obj_t *, p2->vOuts, pObj, i ) + Vec_PtrPushUnique( p->vOuts, pObj ); + + // derive internal objects + assert( p->vNodes == NULL ); + p->vNodes = Llb_ManGroupCollect( p ); + return p; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManGroupMarkNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + if ( Aig_ObjIsTravIdPrevious(p, pObj) ) + { + Aig_ObjSetTravIdCurrent(p, pObj); + return; + } + Aig_ObjSetTravIdCurrent(p, pObj); + assert( Aig_ObjIsNode(pObj) ); + Llb_ManGroupMarkNodes_rec( p, Aig_ObjFanin0(pObj) ); + Llb_ManGroupMarkNodes_rec( p, Aig_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Creates group from two cuts derived by the flow computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Grp_t * Llb_ManGroupCreateFromCuts( Llb_Man_t * pMan, Vec_Int_t * vCut1, Vec_Int_t * vCut2 ) +{ + Llb_Grp_t * p; + Aig_Obj_t * pObj; + int i; + p = Llb_ManGroupAlloc( pMan ); + + // mark Cut1 + Aig_ManIncrementTravId( pMan->pAig ); + Aig_ManForEachObjVec( vCut1, pMan->pAig, pObj, i ) + Aig_ObjSetTravIdCurrent( pMan->pAig, pObj ); + // collect unmarked Cut2 + Aig_ManForEachObjVec( vCut2, pMan->pAig, pObj, i ) + if ( !Aig_ObjIsTravIdCurrent( pMan->pAig, pObj ) ) + Vec_PtrPush( p->vOuts, pObj ); + + // mark nodes reachable from Cut2 + Aig_ManIncrementTravId( pMan->pAig ); + Aig_ManForEachObjVec( vCut2, pMan->pAig, pObj, i ) + Llb_ManGroupMarkNodes_rec( pMan->pAig, pObj ); + // collect marked Cut1 + Aig_ManForEachObjVec( vCut1, pMan->pAig, pObj, i ) + if ( Aig_ObjIsTravIdCurrent( pMan->pAig, pObj ) ) + Vec_PtrPush( p->vIns, pObj ); + + // derive internal objects + assert( p->vNodes == NULL ); + p->vNodes = Llb_ManGroupCollect( p ); + return p; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrepareGroups( Llb_Man_t * pMan ) +{ + Aig_Obj_t * pObj; + int i; + assert( pMan->vGroups == NULL ); + pMan->vGroups = Vec_PtrAlloc( 1000 ); + Llb_ManGroupCreateFirst( pMan ); + Aig_ManForEachNode( pMan->pAig, pObj, i ) + { + if ( pObj->fMarkA ) + Llb_ManGroupCreate( pMan, pObj ); + } + Saig_ManForEachLi( pMan->pAig, pObj, i ) + { + if ( pObj->fMarkA ) + Llb_ManGroupCreate( pMan, pObj ); + } + Llb_ManGroupCreateLast( pMan ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrintSpan( Llb_Man_t * p ) +{ + Llb_Grp_t * pGroup; + Aig_Obj_t * pVar; + int i, k, Span = 0, SpanMax = 0; + Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGroup, i ) + { + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) + if ( Vec_IntEntry(p->vVarBegs, pVar->Id) == i ) + Span++; + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) + if ( Vec_IntEntry(p->vVarBegs, pVar->Id) == i ) + Span++; + + SpanMax = Abc_MaxInt( SpanMax, Span ); +printf( "%d ", Span ); + + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) + if ( Vec_IntEntry(p->vVarEnds, pVar->Id) == i ) + Span--; + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) + if ( Vec_IntEntry(p->vVarEnds, pVar->Id) == i ) + Span--; + } +printf( "\n" ); +printf( "Max = %d\n", SpanMax ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManGroupHasVar( Llb_Man_t * p, int iGroup, int iVar ) +{ + Llb_Grp_t * pGroup = (Llb_Grp_t *)Vec_PtrEntry( p->vGroups, iGroup ); + Aig_Obj_t * pObj; + int i; + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) + if ( pObj->Id == iVar ) + return 1; + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + if ( pObj->Id == iVar ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrintHisto( Llb_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, k; + Aig_ManForEachObj( p->pAig, pObj, i ) + { + if ( Vec_IntEntry(p->vObj2Var, i) < 0 ) + continue; + printf( "%3d :", i ); + for ( k = 0; k < Vec_IntEntry(p->vVarBegs, i); k++ ) + printf( " " ); + for ( ; k <= Vec_IntEntry(p->vVarEnds, i); k++ ) + printf( "%c", Llb_ManGroupHasVar(p, k, i)? '*':'-' ); + printf( "\n" ); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb1Hint.c b/src/bdd/llb/llb1Hint.c new file mode 100644 index 00000000..353b4c69 --- /dev/null +++ b/src/bdd/llb/llb1Hint.c @@ -0,0 +1,226 @@ +/**CFile**************************************************************** + + FileName [llb1Hint.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Cofactors the circuit w.r.t. the high-fanout variables.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Hint.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns CI index with the largest number of fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManMaxFanoutCi( Aig_Man_t * pAig ) +{ + Aig_Obj_t * pObj; + int i, WeightMax = -ABC_INFINITY, iInput = -1; + Aig_ManForEachCi( pAig, pObj, i ) + if ( WeightMax < Aig_ObjRefs(pObj) ) + { + WeightMax = Aig_ObjRefs(pObj); + iInput = i; + } + assert( iInput >= 0 ); + return iInput; +} + +/**Function************************************************************* + + Synopsis [Derives AIG whose PI is substituted by a constant.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Llb_ManPerformHints( Aig_Man_t * pAig, int nHintDepth ) +{ + Aig_Man_t * pNew, * pTemp; + int i, iInput; + pNew = Aig_ManDupDfs( pAig ); + for ( i = 0; i < nHintDepth; i++ ) + { + iInput = Llb_ManMaxFanoutCi( pNew ); + Abc_Print( 1, "%d %3d\n", i, iInput ); + pNew = Aig_ManDupCof( pTemp = pNew, iInput, 1 ); + Aig_ManStop( pTemp ); + } + return pNew; +} + +/**Function************************************************************* + + Synopsis [Returns CI index with the largest number of fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_ManCollectHighFanoutObjects( Aig_Man_t * pAig, int nCandMax, int fCisOnly ) +{ + Vec_Int_t * vFanouts, * vResult; + Aig_Obj_t * pObj; + int i, fChanges, PivotValue; +// int Entry; + // collect fanout counts + vFanouts = Vec_IntAlloc( 100 ); + Aig_ManForEachObj( pAig, pObj, i ) + { +// if ( !Aig_ObjIsCi(pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) + if ( !Saig_ObjIsLo(pAig,pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) + continue; + Vec_IntPush( vFanouts, Aig_ObjRefs(pObj) ); + } + Vec_IntSort( vFanouts, 1 ); + // pick the separator + nCandMax = Abc_MinInt( nCandMax, Vec_IntSize(vFanouts) - 1 ); + PivotValue = Vec_IntEntry( vFanouts, nCandMax ); + Vec_IntFree( vFanouts ); + // collect obj satisfying the constraints + vResult = Vec_IntAlloc( 100 ); + Aig_ManForEachObj( pAig, pObj, i ) + { +// if ( !Aig_ObjIsCi(pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) + if ( !Saig_ObjIsLo(pAig,pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) + continue; + if ( Aig_ObjRefs(pObj) < PivotValue ) + continue; + Vec_IntPush( vResult, Aig_ObjId(pObj) ); + } + assert( Vec_IntSize(vResult) >= nCandMax ); + // order in the decreasing order of fanouts + do + { + fChanges = 0; + for ( i = 0; i < Vec_IntSize(vResult) - 1; i++ ) + if ( Aig_ObjRefs(Aig_ManObj(pAig, Vec_IntEntry(vResult, i))) < + Aig_ObjRefs(Aig_ManObj(pAig, Vec_IntEntry(vResult, i+1))) ) + { + int Temp = Vec_IntEntry( vResult, i ); + Vec_IntWriteEntry( vResult, i, Vec_IntEntry(vResult, i+1) ); + Vec_IntWriteEntry( vResult, i+1, Temp ); + fChanges = 1; + } + } + while ( fChanges ); +/* + Vec_IntForEachEntry( vResult, Entry, i ) + printf( "%d ", Aig_ObjRefs(Aig_ManObj(pAig, Entry)) ); +printf( "\n" ); +*/ + return vResult; +} + +/**Function************************************************************* + + Synopsis [Derives AIG whose PI is substituted by a constant.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManModelCheckAigWithHints( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars ) +{ + DdManager * ddGlo = NULL; + Vec_Int_t * vHints; + Vec_Int_t * vHFCands; + int i, Entry, RetValue = -1; + abctime clk = Abc_Clock(); + assert( pPars->nHintDepth > 0 ); +/* + // perform reachability without hints + RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, NULL, NULL ); + if ( RetValue >= 0 ) + return RetValue; +*/ + // create hints representation + vHFCands = Llb_ManCollectHighFanoutObjects( pAigGlo, pPars->nHintDepth+pPars->HintFirst, 1 ); + vHints = Vec_IntStartFull( Aig_ManObjNumMax(pAigGlo) ); + // add one hint at a time till the problem is solved + Vec_IntForEachEntryStart( vHFCands, Entry, i, pPars->HintFirst ) + { + Vec_IntWriteEntry( vHints, Entry, 1 ); // change to 1 to start from zero cof!!! + // solve under hints + RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, vHints, &ddGlo ); + if ( RetValue == 0 ) + goto Finish; + if ( RetValue == 1 ) + break; + } + if ( RetValue == -1 ) + goto Finish; + // undo the hints one at a time + for ( ; i >= pPars->HintFirst; i-- ) + { + Entry = Vec_IntEntry( vHFCands, i ); + Vec_IntWriteEntry( vHints, Entry, -1 ); + // solve under relaxed hints + RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, vHints, &ddGlo ); + if ( RetValue == 0 ) + goto Finish; + if ( RetValue == 1 ) + continue; + break; + } +Finish: + if ( ddGlo ) + { + if ( ddGlo->bFunc ) + Cudd_RecursiveDeref( ddGlo, ddGlo->bFunc ); + Extra_StopManager( ddGlo ); + } + Vec_IntFreeP( &vHFCands ); + Vec_IntFreeP( &vHints ); + if ( pPars->fVerbose ) + Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clk ); + return RetValue; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb1Man.c b/src/bdd/llb/llb1Man.c new file mode 100644 index 00000000..f5de25e0 --- /dev/null +++ b/src/bdd/llb/llb1Man.c @@ -0,0 +1,218 @@ +/**CFile**************************************************************** + + FileName [llb1Man.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Reachability manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Man.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrepareVarMap( Llb_Man_t * p ) +{ + Aig_Obj_t * pObjLi, * pObjLo; + int i, iVarLi, iVarLo; + assert( p->vNs2Glo == NULL ); + assert( p->vCs2Glo == NULL ); + assert( p->vGlo2Cs == NULL ); + assert( p->vGlo2Ns == NULL ); + p->vNs2Glo = Vec_IntStartFull( Vec_IntSize(p->vVar2Obj) ); + p->vCs2Glo = Vec_IntStartFull( Vec_IntSize(p->vVar2Obj) ); + p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); + p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); + Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) + { + iVarLi = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLi)); + iVarLo = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLo)); + assert( iVarLi >= 0 && iVarLi < Vec_IntSize(p->vVar2Obj) ); + assert( iVarLo >= 0 && iVarLo < Vec_IntSize(p->vVar2Obj) ); + Vec_IntWriteEntry( p->vNs2Glo, iVarLi, i ); + Vec_IntWriteEntry( p->vCs2Glo, iVarLo, i ); + Vec_IntWriteEntry( p->vGlo2Cs, i, iVarLo ); + Vec_IntWriteEntry( p->vGlo2Ns, i, iVarLi ); + } + // add mapping of the PIs + Saig_ManForEachPi( p->pAig, pObjLo, i ) + { + iVarLo = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLo)); + Vec_IntWriteEntry( p->vCs2Glo, iVarLo, Aig_ManRegNum(p->pAig)+i ); + Vec_IntWriteEntry( p->vNs2Glo, iVarLo, Aig_ManRegNum(p->pAig)+i ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrepareVarLimits( Llb_Man_t * p ) +{ + Llb_Grp_t * pGroup; + Aig_Obj_t * pVar; + int i, k; + assert( p->vVarBegs == NULL ); + assert( p->vVarEnds == NULL ); + p->vVarEnds = Vec_IntStart( Aig_ManObjNumMax(p->pAig) ); + p->vVarBegs = Vec_IntStart( Aig_ManObjNumMax(p->pAig) ); + Vec_IntFill( p->vVarBegs, Aig_ManObjNumMax(p->pAig), p->pMatrix->nCols ); + + for ( i = 0; i < p->pMatrix->nCols; i++ ) + { + pGroup = p->pMatrix->pColGrps[i]; + + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) + if ( Vec_IntEntry(p->vVarBegs, pVar->Id) > i ) + Vec_IntWriteEntry( p->vVarBegs, pVar->Id, i ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) + if ( Vec_IntEntry(p->vVarBegs, pVar->Id) > i ) + Vec_IntWriteEntry( p->vVarBegs, pVar->Id, i ); + + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) + if ( Vec_IntEntry(p->vVarEnds, pVar->Id) < i ) + Vec_IntWriteEntry( p->vVarEnds, pVar->Id, i ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) + if ( Vec_IntEntry(p->vVarEnds, pVar->Id) < i ) + Vec_IntWriteEntry( p->vVarEnds, pVar->Id, i ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManStop( Llb_Man_t * p ) +{ + Llb_Grp_t * pGrp; + DdNode * bTemp; + int i; + +// Vec_IntFreeP( &p->vMem ); +// Vec_PtrFreeP( &p->vTops ); +// Vec_PtrFreeP( &p->vBots ); +// Vec_VecFreeP( (Vec_Vec_t **)&p->vCuts ); + + if ( p->pMatrix ) + Llb_MtrFree( p->pMatrix ); + Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGrp, i ) + Llb_ManGroupStop( pGrp ); + if ( p->dd ) + { +// printf( "Manager dd\n" ); + Extra_StopManager( p->dd ); + } + if ( p->ddG ) + { +// printf( "Manager ddG\n" ); + if ( p->ddG->bFunc ) + Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc ); + Extra_StopManager( p->ddG ); + } + if ( p->ddR ) + { +// printf( "Manager ddR\n" ); + if ( p->ddR->bFunc ) + Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc ); + Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i ) + Cudd_RecursiveDeref( p->ddR, bTemp ); + Extra_StopManager( p->ddR ); + } + Aig_ManStop( p->pAig ); + Vec_PtrFreeP( &p->vGroups ); + Vec_IntFreeP( &p->vVar2Obj ); + Vec_IntFreeP( &p->vObj2Var ); + Vec_IntFreeP( &p->vVarBegs ); + Vec_IntFreeP( &p->vVarEnds ); + Vec_PtrFreeP( &p->vRings ); + Vec_IntFreeP( &p->vNs2Glo ); + Vec_IntFreeP( &p->vCs2Glo ); + Vec_IntFreeP( &p->vGlo2Cs ); + Vec_IntFreeP( &p->vGlo2Ns ); +// Vec_IntFreeP( &p->vHints ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Man_t * Llb_ManStart( Aig_Man_t * pAigGlo, Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) +{ + Llb_Man_t * p; + Aig_ManCleanMarkA( pAig ); + p = ABC_CALLOC( Llb_Man_t, 1 ); + p->pAigGlo = pAigGlo; + p->pPars = pPars; + p->pAig = pAig; + p->vVar2Obj = Llb_ManMarkPivotNodes( p->pAig, pPars->fUsePivots ); + p->vObj2Var = Vec_IntInvert( p->vVar2Obj, -1 ); + p->vRings = Vec_PtrAlloc( 100 ); + Llb_ManPrepareVarMap( p ); + Llb_ManPrepareGroups( p ); + Aig_ManCleanMarkA( pAig ); + p->pMatrix = Llb_MtrCreate( p ); + p->pMatrix->pMan = p; + return p; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb1Matrix.c b/src/bdd/llb/llb1Matrix.c new file mode 100644 index 00000000..7aa9c744 --- /dev/null +++ b/src/bdd/llb/llb1Matrix.c @@ -0,0 +1,430 @@ +/**CFile**************************************************************** + + FileName [llb1Matrix.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Partition clustering as a matrix problem.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Matrix.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// 0123 nCols +// +---------------------> +// pi 0 | 111 row0 pRowSums[0] +// pi 1 | 1 11 row1 pRowSums[1] +// pi 2 | 1 11 row2 pRowSums[2] +// CS |1 1 +// CS |1 111 +// CS |111 111 +// int | 11111 +// int | 111 +// int | 111 +// int | 111 +// NS | 11 11 +// NS | 11 1 +// NS | 111 +// nRows | +// v +// cccc pColSums[0] +// oooo pColSums[1] +// llll pColSums[2] +// 0123 pColSums[3] + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Verify columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrVerifyRowsAll( Llb_Mtr_t * p ) +{ + int iRow, iCol, Counter; + for ( iCol = 0; iCol < p->nCols; iCol++ ) + { + Counter = 0; + for ( iRow = 0; iRow < p->nRows; iRow++ ) + if ( p->pMatrix[iCol][iRow] == 1 ) + Counter++; + assert( Counter == p->pColSums[iCol] ); + } +} + +/**Function************************************************************* + + Synopsis [Verify columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrVerifyColumnsAll( Llb_Mtr_t * p ) +{ + int iRow, iCol, Counter; + for ( iRow = 0; iRow < p->nRows; iRow++ ) + { + Counter = 0; + for ( iCol = 0; iCol < p->nCols; iCol++ ) + if ( p->pMatrix[iCol][iRow] == 1 ) + Counter++; + assert( Counter == p->pRowSums[iRow] ); + } +} + +/**Function************************************************************* + + Synopsis [Verify columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrVerifyMatrix( Llb_Mtr_t * p ) +{ + Llb_MtrVerifyRowsAll( p ); + Llb_MtrVerifyColumnsAll( p ); +} + +/**Function************************************************************* + + Synopsis [Sort variables in the order of removal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Llb_MtrFindVarOrder( Llb_Mtr_t * p ) +{ + int * pOrder, * pLast; + int i, k, fChanges, Temp; + pOrder = ABC_CALLOC( int, p->nRows ); + pLast = ABC_CALLOC( int, p->nRows ); + for ( i = 0; i < p->nRows; i++ ) + { + pOrder[i] = i; + for ( k = p->nCols - 1; k >= 0; k-- ) + if ( p->pMatrix[k][i] ) + { + pLast[i] = k; + break; + } + } + do + { + fChanges = 0; + for ( i = 0; i < p->nRows - 1; i++ ) + if ( pLast[i] > pLast[i+1] ) + { + Temp = pOrder[i]; + pOrder[i] = pOrder[i+1]; + pOrder[i+1] = Temp; + + Temp = pLast[i]; + pLast[i] = pLast[i+1]; + pLast[i+1] = Temp; + + fChanges = 1; + } + } + while ( fChanges ); + ABC_FREE( pLast ); + return pOrder; +} + +/**Function************************************************************* + + Synopsis [Returns type of a variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Llb_MtrVarName( Llb_Mtr_t * p, int iVar ) +{ + static char Buffer[10]; + if ( iVar < p->nPis ) + strcpy( Buffer, "pi" ); + else if ( iVar < p->nPis + p->nFfs ) + strcpy( Buffer, "CS" ); + else if ( iVar >= p->nRows - p->nFfs ) + strcpy( Buffer, "NS" ); + else + strcpy( Buffer, "int" ); + return Buffer; +} + +/**Function************************************************************* + + Synopsis [Creates one column with vars in the array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrPrint( Llb_Mtr_t * p, int fOrder ) +{ + int * pOrder = NULL; + int i, iRow, iCol; + if ( fOrder ) + pOrder = Llb_MtrFindVarOrder( p ); + for ( i = 0; i < p->nRows; i++ ) + { + iRow = pOrder ? pOrder[i] : i; + printf( "%3d : ", iRow ); + printf( "%3d ", p->pRowSums[iRow] ); + printf( "%3s ", Llb_MtrVarName(p, iRow) ); + for ( iCol = 0; iCol < p->nCols; iCol++ ) + printf( "%c", p->pMatrix[iCol][iRow] ? '*' : ' ' ); + printf( "\n" ); + } + ABC_FREE( pOrder ); +} + +/**Function************************************************************* + + Synopsis [Verify columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrPrintMatrixStats( Llb_Mtr_t * p ) +{ + int iVar, iGrp, iGrp1, iGrp2, Span = 0, nCutSize = 0, nCutSizeMax = 0; + int * pGrp1 = ABC_CALLOC( int, p->nRows ); + int * pGrp2 = ABC_CALLOC( int, p->nRows ); + for ( iVar = 0; iVar < p->nRows; iVar++ ) + { + if ( p->pRowSums[iVar] == 0 ) + continue; + for ( iGrp1 = 0; iGrp1 < p->nCols; iGrp1++ ) + if ( p->pMatrix[iGrp1][iVar] == 1 ) + break; + for ( iGrp2 = p->nCols - 1; iGrp2 >= 0; iGrp2-- ) + if ( p->pMatrix[iGrp2][iVar] == 1 ) + break; + assert( iGrp1 <= iGrp2 ); + pGrp1[iVar] = iGrp1; + pGrp2[iVar] = iGrp2; + Span += iGrp2 - iGrp1; + } + // compute span + for ( iGrp = 0; iGrp < p->nCols; iGrp++ ) + { + for ( iVar = 0; iVar < p->nRows; iVar++ ) + if ( pGrp1[iVar] == iGrp ) + nCutSize++; + if ( nCutSizeMax < nCutSize ) + nCutSizeMax = nCutSize; + for ( iVar = 0; iVar < p->nRows; iVar++ ) + if ( pGrp2[iVar] == iGrp ) + nCutSize--; + } + ABC_FREE( pGrp1 ); + ABC_FREE( pGrp2 ); + printf( "[%4d x %4d] Life-span =%6.2f Max-cut =%5d\n", + p->nCols, p->nRows, 1.0*Span/p->nRows, nCutSizeMax ); + if ( nCutSize ) + Abc_Print( -1, "Cut size is not zero (%d).\n", nCutSize ); +} + + + +/**Function************************************************************* + + Synopsis [Starts the matrix representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Mtr_t * Llb_MtrAlloc( int nPis, int nFfs, int nCols, int nRows ) +{ + Llb_Mtr_t * p; + int i; + p = ABC_CALLOC( Llb_Mtr_t, 1 ); + p->nPis = nPis; + p->nFfs = nFfs; + p->nRows = nRows; + p->nCols = nCols; + p->pRowSums = ABC_CALLOC( int, nRows ); + p->pColSums = ABC_CALLOC( int, nCols ); + p->pColGrps = ABC_CALLOC( Llb_Grp_t *, nCols ); + p->pMatrix = ABC_CALLOC( char *, nCols ); + for ( i = 0; i < nCols; i++ ) + p->pMatrix[i] = ABC_CALLOC( char, nRows ); + // partial product + p->pProdVars = ABC_CALLOC( char, nRows ); // variables in the partial product + p->pProdNums = ABC_CALLOC( int, nRows ); // var counts in the remaining partitions + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the matrix representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrFree( Llb_Mtr_t * p ) +{ + int i; + ABC_FREE( p->pProdVars ); + ABC_FREE( p->pProdNums ); + for ( i = 0; i < p->nCols; i++ ) + ABC_FREE( p->pMatrix[i] ); + ABC_FREE( p->pRowSums ); + ABC_FREE( p->pColSums ); + ABC_FREE( p->pMatrix ); + ABC_FREE( p->pColGrps ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Creates one column with vars in the array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrAddColumn( Llb_Mtr_t * p, Llb_Grp_t * pGrp ) +{ + Aig_Obj_t * pVar; + int i, iRow, iCol = pGrp->Id; + assert( iCol >= 0 && iCol < p->nCols ); + p->pColGrps[iCol] = pGrp; + Vec_PtrForEachEntry( Aig_Obj_t *, pGrp->vIns, pVar, i ) + { + iRow = Vec_IntEntry( pGrp->pMan->vObj2Var, Aig_ObjId(pVar) ); + assert( iRow >= 0 && iRow < p->nRows ); + p->pMatrix[iCol][iRow] = 1; + p->pColSums[iCol]++; + p->pRowSums[iRow]++; + } + Vec_PtrForEachEntry( Aig_Obj_t *, pGrp->vOuts, pVar, i ) + { + iRow = Vec_IntEntry( pGrp->pMan->vObj2Var, Aig_ObjId(pVar) ); + assert( iRow >= 0 && iRow < p->nRows ); + p->pMatrix[iCol][iRow] = 1; + p->pColSums[iCol]++; + p->pRowSums[iRow]++; + } +} + +/**Function************************************************************* + + Synopsis [Matrix reduce.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrRemoveSingletonRows( Llb_Mtr_t * p ) +{ + int i, k; + for ( i = 0; i < p->nRows; i++ ) + if ( p->pRowSums[i] < 2 ) + { + p->pRowSums[i] = 0; + for ( k = 0; k < p->nCols; k++ ) + { + if ( p->pMatrix[k][i] == 1 ) + { + p->pMatrix[k][i] = 0; + p->pColSums[k]--; + } + } + } +} + +/**Function************************************************************* + + Synopsis [Matrix reduce.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Mtr_t * Llb_MtrCreate( Llb_Man_t * p ) +{ + Llb_Mtr_t * pMatrix; + Llb_Grp_t * pGroup; + int i; + pMatrix = Llb_MtrAlloc( Saig_ManPiNum(p->pAig), Saig_ManRegNum(p->pAig), + Vec_PtrSize(p->vGroups), Vec_IntSize(p->vVar2Obj) ); + Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGroup, i ) + Llb_MtrAddColumn( pMatrix, pGroup ); +// Llb_MtrRemoveSingletonRows( pMatrix ); + return pMatrix; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb1Pivot.c b/src/bdd/llb/llb1Pivot.c new file mode 100644 index 00000000..7a5bb66f --- /dev/null +++ b/src/bdd/llb/llb1Pivot.c @@ -0,0 +1,254 @@ +/**CFile**************************************************************** + + FileName [llb1Pivot.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Determining pivot variables.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Pivot.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManTracePaths_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pPivot ) +{ + Aig_Obj_t * pFanout; + int k, iFan = -1; + if ( Aig_ObjIsTravIdPrevious(p, pObj) ) + return 0; + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return 1; + if ( Saig_ObjIsLi(p, pObj) ) + return 0; + if ( Saig_ObjIsPo(p, pObj) ) + return 0; + if ( pObj == pPivot ) + return 1; + assert( Aig_ObjIsCand(pObj) ); + Aig_ObjForEachFanout( p, pObj, pFanout, iFan, k ) + if ( !Llb_ManTracePaths_rec( p, pFanout, pPivot ) ) + { + Aig_ObjSetTravIdPrevious(p, pObj); + return 0; + } + Aig_ObjSetTravIdCurrent(p, pObj); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManTracePaths( Aig_Man_t * p, Aig_Obj_t * pPivot ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + Aig_ManIncrementTravId( p ); // prev = visited with path to LI (value 0) + Aig_ManIncrementTravId( p ); // cur = visited w/o path to LI (value 1) + Saig_ManForEachLo( p, pObj, i ) + Counter += Llb_ManTracePaths_rec( p, pObj, pPivot ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManTestCuts( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, Count; + Aig_ManFanoutStart( p ); + Aig_ManForEachNode( p, pObj, i ) + { + if ( Aig_ObjRefs(pObj) <= 1 ) + continue; + Count = Llb_ManTracePaths( p, pObj ); + printf( "Obj =%5d. Lev =%3d. Fanout =%5d. Count = %3d.\n", + i, Aig_ObjLevel(pObj), Aig_ObjRefs(pObj), Count ); + } + Aig_ManFanoutStop( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManLabelLiCones_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + if ( pObj->fMarkB ) + return; + pObj->fMarkB = 1; + assert( Aig_ObjIsNode(pObj) ); + Llb_ManLabelLiCones_rec( p, Aig_ObjFanin0(pObj) ); + Llb_ManLabelLiCones_rec( p, Aig_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Determine starting cut-points.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManLabelLiCones( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + // mark const and PIs + Aig_ManConst1(p)->fMarkB = 1; + Aig_ManForEachCi( p, pObj, i ) + pObj->fMarkB = 1; + // mark cones + Saig_ManForEachLi( p, pObj, i ) + Llb_ManLabelLiCones_rec( p, Aig_ObjFanin0(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Determine starting cut-points.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManMarkInternalPivots( Aig_Man_t * p ) +{ + Vec_Ptr_t * vMuxes; + Aig_Obj_t * pObj; + int i, Counter = 0; + + // remove refs due to MUXes + vMuxes = Aig_ManMuxesCollect( p ); + Aig_ManMuxesDeref( p, vMuxes ); + + // mark nodes feeding into LIs + Aig_ManCleanMarkB( p ); + Llb_ManLabelLiCones( p ); + + // mark internal nodes + Aig_ManFanoutStart( p ); + Aig_ManForEachNode( p, pObj, i ) + if ( pObj->fMarkB && pObj->nRefs > 1 ) + { + if ( Llb_ManTracePaths(p, pObj) > 0 ) + pObj->fMarkA = 1; + Counter++; + } + Aig_ManFanoutStop( p ); +// printf( "TracePath tried = %d.\n", Counter ); + + // mark nodes feeding into LIs + Aig_ManCleanMarkB( p ); + + // add refs due to MUXes + Aig_ManMuxesRef( p, vMuxes ); + Vec_PtrFree( vMuxes ); +} + +/**Function************************************************************* + + Synopsis [Determine starting cut-points.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_ManMarkPivotNodes( Aig_Man_t * p, int fUseInternal ) +{ + Vec_Int_t * vVar2Obj; + Aig_Obj_t * pObj; + int i; + // mark inputs/outputs + Aig_ManForEachCi( p, pObj, i ) + pObj->fMarkA = 1; + Saig_ManForEachLi( p, pObj, i ) + pObj->fMarkA = 1; + + // mark internal pivot nodes + if ( fUseInternal ) + Llb_ManMarkInternalPivots( p ); + + // assign variable numbers + Aig_ManConst1(p)->fMarkA = 0; + vVar2Obj = Vec_IntAlloc( 100 ); + Aig_ManForEachCi( p, pObj, i ) + Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) ); + Aig_ManForEachNode( p, pObj, i ) + if ( pObj->fMarkA ) + Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) ); + Saig_ManForEachLi( p, pObj, i ) + Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) ); + return vVar2Obj; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb1Reach.c b/src/bdd/llb/llb1Reach.c new file mode 100644 index 00000000..fae7bee2 --- /dev/null +++ b/src/bdd/llb/llb1Reach.c @@ -0,0 +1,904 @@ +/**CFile**************************************************************** + + FileName [llb1Reach.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Reachability analysis.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Reach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Derives global BDD for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManConstructOutBdd( Aig_Man_t * pAig, Aig_Obj_t * pNode, DdManager * dd ) +{ + DdNode * bBdd0, * bBdd1, * bFunc; + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj = NULL; + int i; + abctime TimeStop; + if ( Aig_ObjFanin0(pNode) == Aig_ManConst1(pAig) ) + return Cudd_NotCond( Cudd_ReadOne(dd), Aig_ObjFaninC0(pNode) ); + TimeStop = dd->TimeStop; dd->TimeStop = 0; + vNodes = Aig_ManDfsNodes( pAig, &pNode, 1 ); + assert( Vec_PtrSize(vNodes) > 0 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) ) + continue; + bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); + pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData ); + } + bFunc = (DdNode *)pObj->pData; Cudd_Ref( bFunc ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) ) + continue; + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + } + Vec_PtrFree( vNodes ); + if ( Aig_ObjIsCo(pNode) ) + bFunc = Cudd_NotCond( bFunc, Aig_ObjFaninC0(pNode) ); + Cudd_Deref( bFunc ); + dd->TimeStop = TimeStop; + return bFunc; +} + +/**Function************************************************************* + + Synopsis [Derives BDD for the group.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManConstructGroupBdd( Llb_Man_t * p, Llb_Grp_t * pGroup ) +{ + Aig_Obj_t * pObj; + DdNode * bBdd0, * bBdd1, * bRes, * bXor, * bTemp; + int i, k; + Aig_ManConst1(p->pAig)->pData = Cudd_ReadOne( p->dd ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) + pObj->pData = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vNodes, pObj, i ) + { + bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); +// pObj->pData = Extra_bddAndTime( p->dd, bBdd0, bBdd1, p->pPars->TimeTarget ); + pObj->pData = Cudd_bddAnd( p->dd, bBdd0, bBdd1 ); + if ( pObj->pData == NULL ) + { + Vec_PtrForEachEntryStop( Aig_Obj_t *, pGroup->vNodes, pObj, k, i ) + if ( pObj->pData ) + Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData ); + return NULL; + } + Cudd_Ref( (DdNode *)pObj->pData ); + } + bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + { + if ( Aig_ObjIsCo(pObj) ) + bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + else + bBdd0 = (DdNode *)pObj->pData; + bBdd1 = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + bXor = Cudd_bddXor( p->dd, bBdd0, bBdd1 ); Cudd_Ref( bXor ); +// bRes = Extra_bddAndTime( p->dd, bTemp = bRes, Cudd_Not(bXor), p->pPars->TimeTarget ); + bRes = Cudd_bddAnd( p->dd, bTemp = bRes, Cudd_Not(bXor) ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bXor ); + Vec_PtrForEachEntryStop( Aig_Obj_t *, pGroup->vNodes, pObj, k, i ) + if ( pObj->pData ) + Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData ); + return NULL; + } + Cudd_Ref( bRes ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bXor ); + } + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vNodes, pObj, i ) + Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData ); + Cudd_Deref( bRes ); + return bRes; +} + +/**Function************************************************************* + + Synopsis [Derives quantification cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManConstructQuantCubeIntern( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace, int fBackward ) +{ + Aig_Obj_t * pObj; + DdNode * bRes, * bTemp, * bVar; + int i, iGroupFirst, iGroupLast; + abctime TimeStop; + TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; + bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) + { + if ( fBackward && Saig_ObjIsPi(p->pAig, pObj) ) + continue; + iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); + iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); + assert( iGroupFirst <= iGroupLast ); + if ( iGroupFirst < iGroupLast ) + continue; + bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + { + if ( fBackward && Saig_ObjIsPi(p->pAig, pObj) ) + continue; + iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); + iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); + assert( iGroupFirst <= iGroupLast ); + if ( iGroupFirst < iGroupLast ) + continue; + bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Cudd_Deref( bRes ); + p->dd->TimeStop = TimeStop; + return bRes; +} + +/**Function************************************************************* + + Synopsis [Derives quantification cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManConstructQuantCubeFwd( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace ) +{ + Aig_Obj_t * pObj; + DdNode * bRes, * bTemp, * bVar; + int i, iGroupLast; + abctime TimeStop; + TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; + bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) + { + iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); + assert( iGroupLast >= iGrpPlace ); + if ( iGroupLast > iGrpPlace ) + continue; + bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + { + iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); + assert( iGroupLast >= iGrpPlace ); + if ( iGroupLast > iGrpPlace ) + continue; + bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Cudd_Deref( bRes ); + p->dd->TimeStop = TimeStop; + return bRes; +} + +/**Function************************************************************* + + Synopsis [Derives quantification cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManConstructQuantCubeBwd( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace ) +{ + Aig_Obj_t * pObj; + DdNode * bRes, * bTemp, * bVar; + int i, iGroupFirst; + abctime TimeStop; + TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; + bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) + { + if ( Saig_ObjIsPi(p->pAig, pObj) ) + continue; + iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); + assert( iGroupFirst <= iGrpPlace ); + if ( iGroupFirst < iGrpPlace ) + continue; + bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + { + if ( Saig_ObjIsPi(p->pAig, pObj) ) + continue; + iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); + assert( iGroupFirst <= iGrpPlace ); + if ( iGroupFirst < iGrpPlace ) + continue; + bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Cudd_Deref( bRes ); + p->dd->TimeStop = TimeStop; + return bRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManComputeInitState( Llb_Man_t * p, DdManager * dd ) +{ + Aig_Obj_t * pObj; + DdNode * bRes, * bVar, * bTemp; + int i, iVar; + abctime TimeStop; + TimeStop = dd->TimeStop; dd->TimeStop = 0; + bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); + Saig_ManForEachLo( p->pAig, pObj, i ) + { + iVar = (dd == p->ddG) ? i : Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)); + bVar = Cudd_bddIthVar( dd, iVar ); + bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bRes ); + dd->TimeStop = TimeStop; + return bRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManComputeImage( Llb_Man_t * p, DdNode * bInit, int fBackward ) +{ + int fCheckSupport = 0; + Llb_Grp_t * pGroup; + DdNode * bImage, * bGroup, * bCube, * bTemp; + int k, Index; + bImage = bInit; Cudd_Ref( bImage ); + for ( k = 1; k < p->pMatrix->nCols-1; k++ ) + { + if ( fBackward ) + Index = p->pMatrix->nCols - 1 - k; + else + Index = k; + + // compute group BDD + pGroup = p->pMatrix->pColGrps[Index]; + bGroup = Llb_ManConstructGroupBdd( p, pGroup ); + if ( bGroup == NULL ) + { + Cudd_RecursiveDeref( p->dd, bImage ); + return NULL; + } + Cudd_Ref( bGroup ); + // quantify variables appearing only in this group + bCube = Llb_ManConstructQuantCubeIntern( p, pGroup, Index, fBackward ); Cudd_Ref( bCube ); + bGroup = Cudd_bddExistAbstract( p->dd, bTemp = bGroup, bCube ); + if ( bGroup == NULL ) + { + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bCube ); + return NULL; + } + Cudd_Ref( bGroup ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bCube ); + // perform partial product + if ( fBackward ) + bCube = Llb_ManConstructQuantCubeBwd( p, pGroup, Index ); + else + bCube = Llb_ManConstructQuantCubeFwd( p, pGroup, Index ); + Cudd_Ref( bCube ); +// bImage = Extra_bddAndAbstractTime( p->dd, bTemp = bImage, bGroup, bCube, p->pPars->TimeTarget ); + bImage = Cudd_bddAndAbstract( p->dd, bTemp = bImage, bGroup, bCube ); + if ( bImage == NULL ) + { + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bGroup ); + Cudd_RecursiveDeref( p->dd, bCube ); + return NULL; + } + Cudd_Ref( bImage ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bGroup ); + Cudd_RecursiveDeref( p->dd, bCube ); + } + + // make sure image depends on next state vars + if ( fCheckSupport ) + { + bCube = Cudd_Support( p->dd, bImage ); Cudd_Ref( bCube ); + for ( bTemp = bCube; bTemp != p->dd->one; bTemp = cuddT(bTemp) ) + { + int ObjId = Vec_IntEntry( p->vVar2Obj, bTemp->index ); + Aig_Obj_t * pObj = Aig_ManObj( p->pAig, ObjId ); + if ( !Saig_ObjIsLi(p->pAig, pObj) ) + printf( "Var %d assigned to obj %d that is not LI\n", bTemp->index, ObjId ); + } + Cudd_RecursiveDeref( p->dd, bCube ); + } + Cudd_Deref( bImage ); + return bImage; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManCreateConstraints( Llb_Man_t * p, Vec_Int_t * vHints, int fUseNsVars ) +{ + DdNode * bConstr, * bFunc, * bTemp; + Aig_Obj_t * pObj; + int i, Entry; + abctime TimeStop; + if ( vHints == NULL ) + return Cudd_ReadOne( p->dd ); + TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; + assert( Aig_ManCiNum(p->pAig) == Aig_ManCiNum(p->pAigGlo) ); + // assign const and PI nodes to the original AIG + Aig_ManCleanData( p->pAig ); + Aig_ManConst1( p->pAig )->pData = Cudd_ReadOne( p->dd ); + Saig_ManForEachPi( p->pAig, pObj, i ) + pObj->pData = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var,Aig_ObjId(pObj)) ); + Saig_ManForEachLo( p->pAig, pObj, i ) + { + if ( fUseNsVars ) + Entry = Vec_IntEntry( p->vObj2Var, Aig_ObjId(Saig_ObjLoToLi(p->pAig, pObj)) ); + else + Entry = Vec_IntEntry( p->vObj2Var, Aig_ObjId(pObj) ); + pObj->pData = Cudd_bddIthVar( p->dd, Entry ); + } + // transfer them to the global AIG + Aig_ManCleanData( p->pAigGlo ); + Aig_ManConst1( p->pAigGlo )->pData = Cudd_ReadOne( p->dd ); + Aig_ManForEachCi( p->pAigGlo, pObj, i ) + pObj->pData = Aig_ManCi(p->pAig, i)->pData; + // derive consraints + bConstr = Cudd_ReadOne( p->dd ); Cudd_Ref( bConstr ); + Vec_IntForEachEntry( vHints, Entry, i ) + { + if ( Entry != 0 && Entry != 1 ) + continue; + bFunc = Llb_ManConstructOutBdd( p->pAigGlo, Aig_ManObj(p->pAigGlo, i), p->dd ); Cudd_Ref( bFunc ); + bFunc = Cudd_NotCond( bFunc, Entry ); // restrict to not constraint + // make the product + bConstr = Cudd_bddAnd( p->dd, bTemp = bConstr, bFunc ); Cudd_Ref( bConstr ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bFunc ); + } + Cudd_Deref( bConstr ); + p->dd->TimeStop = TimeStop; + return bConstr; +} + +/**Function************************************************************* + + Synopsis [Perform reachability with hints and returns reached states in ppGlo.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Llb_ManReachDeriveCex( Llb_Man_t * p ) +{ + Abc_Cex_t * pCex; + Aig_Obj_t * pObj; + DdNode * bState = NULL, * bImage, * bOneCube, * bTemp, * bRing; + int i, v, RetValue, nPiOffset; + char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) ); + assert( Vec_PtrSize(p->vRings) > 0 ); + + p->dd->TimeStop = 0; + p->ddR->TimeStop = 0; + +/* + Saig_ManForEachLo( p->pAig, pObj, i ) + printf( "%d ", pObj->Id ); + printf( "\n" ); + Saig_ManForEachLi( p->pAig, pObj, i ) + printf( "%d(%d) ", pObj->Id, Aig_ObjFaninId0(pObj) ); + printf( "\n" ); +*/ + // allocate room for the counter-example + pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) ); + pCex->iFrame = Vec_PtrSize(p->vRings) - 1; + pCex->iPo = -1; + + // get the last cube + bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc ); Cudd_Ref( bOneCube ); + RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); + Cudd_RecursiveDeref( p->ddR, bOneCube ); + assert( RetValue ); + + // write PIs of counter-example + nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1); + Saig_ManForEachPi( p->pAig, pObj, i ) + if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) + Abc_InfoSetBit( pCex->pData, nPiOffset + i ); + + // write state in terms of NS variables + if ( Vec_PtrSize(p->vRings) > 1 ) + { + bState = Llb_CoreComputeCube( p->dd, p->vGlo2Ns, 1, pValues ); Cudd_Ref( bState ); + } + // perform backward analysis + Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v ) + { + if ( v == Vec_PtrSize(p->vRings) - 1 ) + continue; +//Extra_bddPrintSupport( p->dd, bState ); printf( "\n" ); +//Extra_bddPrintSupport( p->dd, bRing ); printf( "\n" ); + // compute the next states + bImage = Llb_ManComputeImage( p, bState, 1 ); + assert( bImage != NULL ); + Cudd_Ref( bImage ); + Cudd_RecursiveDeref( p->dd, bState ); +//Extra_bddPrintSupport( p->dd, bImage ); printf( "\n" ); + + // move reached states into ring manager + bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) ); Cudd_Ref( bImage ); + Cudd_RecursiveDeref( p->dd, bTemp ); +//Extra_bddPrintSupport( p->ddR, bImage ); printf( "\n" ); + + // intersect with the previous set + bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing ); Cudd_Ref( bOneCube ); + Cudd_RecursiveDeref( p->ddR, bImage ); + + // find any assignment of the BDD + RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); + Cudd_RecursiveDeref( p->ddR, bOneCube ); + assert( RetValue ); +/* + for ( i = 0; i < p->ddR->size; i++ ) + printf( "%d ", pValues[i] ); + printf( "\n" ); +*/ + // write PIs of counter-example + nPiOffset -= Saig_ManPiNum(p->pAig); + Saig_ManForEachPi( p->pAig, pObj, i ) + if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) + Abc_InfoSetBit( pCex->pData, nPiOffset + i ); + + // check that we get the init state + if ( v == 0 ) + { + Saig_ManForEachLo( p->pAig, pObj, i ) + assert( pValues[i] == 0 ); + break; + } + + // write state in terms of NS variables + bState = Llb_CoreComputeCube( p->dd, p->vGlo2Ns, 1, pValues ); Cudd_Ref( bState ); + } + assert( nPiOffset == Saig_ManRegNum(p->pAig) ); + // update the output number +//Abc_CexPrint( pCex ); + RetValue = Saig_ManFindFailedPoCex( p->pAigGlo, pCex ); + assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pAigGlo) ); // invalid CEX!!! + pCex->iPo = RetValue; + // cleanup + ABC_FREE( pValues ); + return pCex; +} + +/**Function************************************************************* + + Synopsis [Perform reachability with hints and returns reached states in ppGlo.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManReachability( Llb_Man_t * p, Vec_Int_t * vHints, DdManager ** pddGlo ) +{ + int * pNs2Glo = Vec_IntArray( p->vNs2Glo ); + int * pCs2Glo = Vec_IntArray( p->vCs2Glo ); + int * pGlo2Cs = Vec_IntArray( p->vGlo2Cs ); + DdNode * bCurrent, * bReached, * bNext, * bTemp, * bCube; + DdNode * bConstrCs, * bConstrNs; + abctime clk2, clk = Abc_Clock(); + int nIters, nBddSize = 0; +// int nThreshold = 10000; + + // compute time to stop + p->pPars->TimeTarget = p->pPars->TimeLimit ? p->pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0; + + // define variable limits + Llb_ManPrepareVarLimits( p ); + + // start the managers + assert( p->dd == NULL ); + assert( p->ddG == NULL ); + assert( p->ddR == NULL ); + p->dd = Cudd_Init( Vec_IntSize(p->vVar2Obj), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + p->ddR = Cudd_Init( Aig_ManCiNum(p->pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + if ( pddGlo && *pddGlo ) + p->ddG = *pddGlo, *pddGlo = NULL; + else + p->ddG = Cudd_Init( Aig_ManRegNum(p->pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + + if ( p->pPars->fReorder ) + { + Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); + Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT ); + Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT ); + } + else + { + Cudd_AutodynDisable( p->dd ); + Cudd_AutodynDisable( p->ddG ); + Cudd_AutodynDisable( p->ddR ); + } + + // set the stop time parameter + p->dd->TimeStop = p->pPars->TimeTarget; + p->ddG->TimeStop = p->pPars->TimeTarget; + p->ddR->TimeStop = p->pPars->TimeTarget; + + // create bad state in the ring manager + p->ddR->bFunc = Llb_BddComputeBad( p->pAigGlo, p->ddR, p->pPars->TimeTarget ); + if ( p->ddR->bFunc == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + Cudd_Ref( p->ddR->bFunc ); + + // derive constraints + bConstrCs = Llb_ManCreateConstraints( p, vHints, 0 ); Cudd_Ref( bConstrCs ); + bConstrNs = Llb_ManCreateConstraints( p, vHints, 1 ); Cudd_Ref( bConstrNs ); +//Extra_bddPrint( p->dd, bConstrCs ); printf( "\n" ); +//Extra_bddPrint( p->dd, bConstrNs ); printf( "\n" ); + + // perform reachability analysis + // compute the starting set of states + if ( p->ddG->bFunc ) + { + bReached = p->ddG->bFunc; p->ddG->bFunc = NULL; + bCurrent = Extra_TransferPermute( p->ddG, p->dd, bReached, pGlo2Cs ); Cudd_Ref( bCurrent ); + } + else + { + bReached = Llb_ManComputeInitState( p, p->ddG ); Cudd_Ref( bReached ); + bCurrent = Llb_ManComputeInitState( p, p->dd ); Cudd_Ref( bCurrent ); + } +//Extra_bddPrintSupport( p->ddG, bReached ); printf( "\n" ); +//Extra_bddPrintSupport( p->dd, bCurrent ); printf( "\n" ); + +//Extra_bddPrintSupport( p->dd, bCurrent ); printf( "\n" ); + for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ ) + { + clk2 = Abc_Clock(); + // check the runtime limit + if ( p->pPars->TimeLimit && Abc_Clock() > p->pPars->TimeTarget ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout during image computation (%d seconds).\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; + Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + + // save the onion ring + bTemp = Extra_TransferPermute( p->dd, p->ddR, bCurrent, pCs2Glo ); + if ( bTemp == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during ring transfer.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; + Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bTemp ); + Vec_PtrPush( p->vRings, bTemp ); + + // check it for bad states + if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) ) + { + assert( p->pAigGlo->pSeqModel == NULL ); + if ( !p->pPars->fBackward ) + p->pAigGlo->pSeqModel = Llb_ManReachDeriveCex( p ); + if ( !p->pPars->fSilent ) + { + if ( !p->pPars->fBackward ) + Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", p->pAigGlo->pSeqModel->iPo, p->pAigGlo->pName, p->pAigGlo->pName, nIters ); + else + Abc_Print( 1, "Output ??? of miter \"%s\" was asserted in frame %d (counter-example is not produced). ", p->pAigGlo->pName, nIters ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; + Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return 0; + } + + // restrict reachable states using constraints + if ( vHints ) + { + bCurrent = Cudd_bddAnd( p->dd, bTemp = bCurrent, bConstrCs ); Cudd_Ref( bCurrent ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + + // quantify variables appearing only in the init state + bCube = Llb_ManConstructQuantCubeIntern( p, (Llb_Grp_t *)Vec_PtrEntry(p->vGroups,0), 0, 0 ); Cudd_Ref( bCube ); + bCurrent = Cudd_bddExistAbstract( p->dd, bTemp = bCurrent, bCube ); Cudd_Ref( bCurrent ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bCube ); + + // compute the next states + bNext = Llb_ManComputeImage( p, bCurrent, 0 ); + if ( bNext == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; + Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bNext ); + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + + // restrict reachable states using constraints + if ( vHints ) + { + bNext = Cudd_bddAnd( p->dd, bTemp = bNext, bConstrNs ); Cudd_Ref( bNext ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } +//Extra_bddPrintSupport( p->dd, bNext ); printf( "\n" ); + + // remap these states into the current state vars +// bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pNs2Glo ); Cudd_Ref( bNext ); +// Cudd_RecursiveDeref( p->dd, bTemp ); +// bNext = Extra_TransferPermuteTime( p->dd, p->ddG, bTemp = bNext, pNs2Glo, p->pPars->TimeTarget ); + bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pNs2Glo ); + if ( bNext == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; + Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bNext ); + Cudd_RecursiveDeref( p->dd, bTemp ); + + + // check if there are any new states + if ( Cudd_bddLeq( p->ddG, bNext, bReached ) ) // implication = no new states + { + Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; + break; + } + + // check the BDD size + nBddSize = Cudd_DagSize(bNext); + if ( nBddSize > p->pPars->nBddMax ) + { + Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; + break; + } + + // get the new states + bCurrent = Cudd_bddAnd( p->ddG, bNext, Cudd_Not(bReached) ); + if ( bCurrent == NULL ) + { + Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + break; + } + Cudd_Ref( bCurrent ); + // minimize the new states with the reached states +// bCurrent = Cudd_bddConstrain( p->ddG, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); +// bCurrent = Cudd_bddRestrict( p->ddG, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); +// Cudd_RecursiveDeref( p->ddG, bTemp ); +//printf( "Initial BDD =%7d. Constrained BDD =%7d.\n", Cudd_DagSize(bTemp), Cudd_DagSize(bCurrent) ); + + // remap these states into the current state vars +// bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs ); Cudd_Ref( bCurrent ); +// Cudd_RecursiveDeref( p->ddG, bTemp ); +// bCurrent = Extra_TransferPermuteTime( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs, p->pPars->TimeTarget ); + bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs ); + if ( bCurrent == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->ddG, bTemp ); + Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; + Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bCurrent ); + Cudd_RecursiveDeref( p->ddG, bTemp ); + + + // add to the reached states + bReached = Cudd_bddOr( p->ddG, bTemp = bReached, bNext ); + if ( bReached == NULL ) + { + Cudd_RecursiveDeref( p->ddG, bTemp ); bTemp = NULL; + Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; + break; + } + Cudd_Ref( bReached ); + Cudd_RecursiveDeref( p->ddG, bTemp ); + Cudd_RecursiveDeref( p->ddG, bNext ); + bNext = NULL; + + if ( p->pPars->fVerbose ) + { + fprintf( stdout, "F =%5d : ", nIters ); + fprintf( stdout, "Im =%6d ", nBddSize ); + fprintf( stdout, "(%4d %3d) ", Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) ); + fprintf( stdout, "Rea =%6d ", Cudd_DagSize(bReached) ); + fprintf( stdout, "(%4d%4d) ", Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk2 ); + } +/* + if ( p->pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); +// Extra_bddPrint( p->ddG, bReached );printf( "\n" ); + fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); + fflush( stdout ); + } +*/ + } + Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; + Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; + if ( bReached == NULL ) + { + p->pPars->iFrame = nIters - 1; + return 0; // reachable + } +// assert( bCurrent == NULL ); + if ( bCurrent ) + Cudd_RecursiveDeref( p->dd, bCurrent ); + // report the stats + if ( p->pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); + if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) + fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters ); + else + fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters ); + fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); + fflush( stdout ); + } + if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) + { + if ( !p->pPars->fSilent ) + printf( "Verified only for states reachable in %d frames. ", nIters ); + p->pPars->iFrame = p->pPars->nIterMax; + Cudd_RecursiveDeref( p->ddG, bReached ); + return -1; // undecided + } + if ( pddGlo ) + { + assert( p->ddG->bFunc == NULL ); + p->ddG->bFunc = bReached; bReached = NULL; + assert( *pddGlo == NULL ); + *pddGlo = p->ddG; p->ddG = NULL; + } + else + Cudd_RecursiveDeref( p->ddG, bReached ); + if ( !p->pPars->fSilent ) + printf( "The miter is proved unreachable after %d iterations. ", nIters ); + p->pPars->iFrame = nIters - 1; + return 1; // unreachable +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb1Sched.c b/src/bdd/llb/llb1Sched.c new file mode 100644 index 00000000..51de973a --- /dev/null +++ b/src/bdd/llb/llb1Sched.c @@ -0,0 +1,257 @@ +/**CFile**************************************************************** + + FileName [llb1Sched.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Partition scheduling algorithm.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Sched.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Swaps two rows.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrSwapColumns( Llb_Mtr_t * p, int iCol1, int iCol2 ) +{ + Llb_Grp_t * pGemp; + char * pTemp; + int iTemp; + assert( iCol1 >= 0 && iCol1 < p->nCols ); + assert( iCol2 >= 0 && iCol2 < p->nCols ); + if ( iCol1 == iCol2 ) + return; + assert( iCol1 != iCol2 ); + // swap col groups + pGemp = p->pColGrps[iCol1]; + p->pColGrps[iCol1] = p->pColGrps[iCol2]; + p->pColGrps[iCol2] = pGemp; + // swap col vectors + pTemp = p->pMatrix[iCol1]; + p->pMatrix[iCol1] = p->pMatrix[iCol2]; + p->pMatrix[iCol2] = pTemp; + // swap col sums + iTemp = p->pColSums[iCol1]; + p->pColSums[iCol1] = p->pColSums[iCol2]; + p->pColSums[iCol2] = iTemp; +} + +/**Function************************************************************* + + Synopsis [Find columns which brings as few vars as possible.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_MtrFindBestColumn( Llb_Mtr_t * p, int iGrpStart ) +{ + int Cost, Cost2, CostBest = ABC_INFINITY, Cost2Best = ABC_INFINITY; + int WeightCur, WeightBest = -ABC_INFINITY, iGrp = -1, iGrpBest = -1; + int k, c, iVar, Counter; + // find partition that reduces partial product as much as possible + for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ ) + { + if ( p->pRowSums[iVar] < 2 ) + continue; + // look at present variables that can be quantified + if ( !(p->pProdVars[iVar] == 1 && p->pProdNums[iVar] == 1) ) + continue; + // check that it appears in one partition only + Counter = 0; + for ( c = iGrpStart; c < p->nCols-1; c++ ) + if ( p->pMatrix[c][iVar] == 1 ) + { + iGrp = c; + Counter++; + } + assert( Counter == 1 ); + if ( Counter != 1 ) + Abc_Print( -1, "Llb_MtrFindBestColumn() Internal error!\n" ); + // find weight of this column + WeightCur = 0; + for ( k = 0; k < p->nRows; k++ ) + { + // increase weight if variable k will be quantified from partial product + if ( p->pProdVars[k] == 1 && p->pMatrix[iGrp][k] == 1 && p->pProdNums[k] == 1 ) + WeightCur += 2; + // decrease weight if variable k will be added to partial product + if ( p->pProdVars[k] == 0 && p->pMatrix[iGrp][k] == 1 ) + WeightCur--; + } + if ( WeightCur > 0 && WeightBest < WeightCur ) + { + WeightBest = WeightCur; + iGrpBest = iGrp; + } + } + if ( iGrpBest >= 0 ) + return iGrpBest; + // could not find the group with any vars to quantify + // select the group that contains as few extra variables as possible + // if there is a tie, select variables that appear in less groups than others + for ( iGrp = iGrpStart; iGrp < p->nCols-1; iGrp++ ) + { + Cost = Cost2 = 0; + for ( k = 0; k < p->nRows; k++ ) + if ( p->pProdVars[k] == 0 && p->pMatrix[iGrp][k] == 1 ) + { + Cost++; + Cost2 += p->pProdNums[k]; + } + if ( CostBest > Cost || + (CostBest == Cost && Cost2 > Cost2Best) ) + { + CostBest = Cost; + Cost2Best = Cost2; + iGrpBest = iGrp; + } + } + return iGrpBest; +} + +/**Function************************************************************* + + Synopsis [Returns the number of variables that will be saved.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrUseSelectedColumn( Llb_Mtr_t * p, int iCol ) +{ + int iVar; + assert( iCol >= 1 && iCol < p->nCols - 1 ); + for ( iVar = 0; iVar < p->nRows; iVar++ ) + { + if ( p->pMatrix[iCol][iVar] == 0 ) + continue; + if ( p->pProdVars[iVar] == 1 && p->pProdNums[iVar] == 1 ) + { + p->pProdVars[iVar] = 0; + p->pProdNums[iVar] = 0; + continue; + } + if ( p->pProdVars[iVar] == 0 ) + { + p->pProdVars[iVar] = 1; + p->pProdNums[iVar] = p->pRowSums[iVar]; + } + p->pProdNums[iVar]--; + assert( p->pProdNums[iVar] >= 0 ); + if ( p->pProdNums[iVar] < 0 ) + Abc_Print( -1, "Llb_MtrUseSelectedColumn() Internal error!\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Verify columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrVerifyColumns( Llb_Mtr_t * p, int iGrpStart ) +{ + int iVar, iGrp, Counter; + for ( iVar = 0; iVar < p->nRows; iVar++ ) + { + if ( p->pProdVars[iVar] == 0 ) + continue; + Counter = 0; + for ( iGrp = iGrpStart; iGrp < p->nCols; iGrp++ ) + if ( p->pMatrix[iGrp][iVar] == 1 ) + Counter++; + assert( Counter == p->pProdNums[iVar] ); + if ( Counter != p->pProdNums[iVar] ) + Abc_Print( -1, "Llb_MtrVerifyColumns(): Internal error.\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Matrix reduce.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrSchedule( Llb_Mtr_t * p ) +{ + int iGrp, iGrpBest, i; + // start partial product + for ( i = 0; i < p->nRows; i++ ) + { + if ( i >= p->nPis && i < p->nPis + p->nFfs ) + { + p->pProdVars[i] = 1; + p->pProdNums[i] = p->pRowSums[i] - 1; + } + else + { + p->pProdVars[i] = 0; + p->pProdNums[i] = p->pRowSums[i]; + } + } + // order the partitions + Llb_MtrVerifyMatrix( p ); + for ( iGrp = 1; iGrp < p->nCols-1; iGrp++ ) + { + Llb_MtrVerifyColumns( p, iGrp ); + iGrpBest = Llb_MtrFindBestColumn( p, iGrp ); + Llb_MtrUseSelectedColumn( p, iGrpBest ); + Llb_MtrSwapColumns( p, iGrp, iGrpBest ); + } + Llb_MtrVerifyMatrix( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb2Bad.c b/src/bdd/llb/llb2Bad.c new file mode 100644 index 00000000..ac04b563 --- /dev/null +++ b/src/bdd/llb/llb2Bad.c @@ -0,0 +1,138 @@ +/**CFile**************************************************************** + + FileName [llb2Bad.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Computing bad states.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Bad.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes bad in working manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_BddComputeBad( Aig_Man_t * pInit, DdManager * dd, abctime TimeOut ) +{ + Vec_Ptr_t * vNodes; + DdNode * bBdd0, * bBdd1, * bTemp, * bResult; + Aig_Obj_t * pObj; + int i, k; + assert( Cudd_ReadSize(dd) == Aig_ManCiNum(pInit) ); + // initialize elementary variables + Aig_ManConst1(pInit)->pData = Cudd_ReadOne( dd ); + Saig_ManForEachLo( pInit, pObj, i ) + pObj->pData = Cudd_bddIthVar( dd, i ); + Saig_ManForEachPi( pInit, pObj, i ) + pObj->pData = Cudd_bddIthVar( dd, Aig_ManRegNum(pInit) + i ); + // compute internal nodes + vNodes = Aig_ManDfsNodes( pInit, (Aig_Obj_t **)Vec_PtrArray(pInit->vCos), Saig_ManPoNum(pInit) ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) ) + continue; + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); +// pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeOut ); + pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); + if ( pObj->pData == NULL ) + { + Vec_PtrForEachEntryStop( Aig_Obj_t *, vNodes, pObj, k, i ) + if ( pObj->pData ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + Vec_PtrFree( vNodes ); + return NULL; + } + Cudd_Ref( (DdNode *)pObj->pData ); + } + // quantify PIs of each PO + bResult = Cudd_ReadLogicZero( dd ); Cudd_Ref( bResult ); + Saig_ManForEachPo( pInit, pObj, i ) + { + bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bResult = Cudd_bddOr( dd, bTemp = bResult, bBdd0 ); Cudd_Ref( bResult ); + Cudd_RecursiveDeref( dd, bTemp ); + } + // deref + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) ) + continue; + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + } + Vec_PtrFree( vNodes ); + Cudd_Deref( bResult ); + return bResult; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_BddQuantifyPis( Aig_Man_t * pInit, DdManager * dd, DdNode * bFunc ) +{ + DdNode * bVar, * bCube, * bTemp; + Aig_Obj_t * pObj; + int i; + abctime TimeStop; + assert( Cudd_ReadSize(dd) == Aig_ManCiNum(pInit) ); + TimeStop = dd->TimeStop; dd->TimeStop = 0; + // create PI cube + bCube = Cudd_ReadOne( dd ); Cudd_Ref( bCube ); + Saig_ManForEachPi( pInit, pObj, i ) { + bVar = Cudd_bddIthVar( dd, Aig_ManRegNum(pInit) + i ); + bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + } + // quantify PI cube + bFunc = Cudd_bddExistAbstract( dd, bFunc, bCube ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( dd, bCube ); + Cudd_Deref( bFunc ); + dd->TimeStop = TimeStop; + return bFunc; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb2Core.c b/src/bdd/llb/llb2Core.c new file mode 100644 index 00000000..3d62b322 --- /dev/null +++ b/src/bdd/llb/llb2Core.c @@ -0,0 +1,777 @@ +/**CFile**************************************************************** + + FileName [llb2Core.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Core procedure.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Core.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Llb_Img_t_ Llb_Img_t; +struct Llb_Img_t_ +{ + Aig_Man_t * pInit; // AIG manager + Aig_Man_t * pAig; // AIG manager + Gia_ParLlb_t * pPars; // parameters + + DdManager * dd; // BDD manager + DdManager * ddG; // BDD manager + DdManager * ddR; // BDD manager + Vec_Ptr_t * vDdMans; // BDD managers for each partition + Vec_Ptr_t * vRings; // onion rings in ddR + + Vec_Int_t * vDriRefs; // driver references + Vec_Int_t * vVarsCs; // cur state variables + Vec_Int_t * vVarsNs; // next state variables + + Vec_Int_t * vCs2Glo; // cur state variables into global variables + Vec_Int_t * vNs2Glo; // next state variables into global variables + Vec_Int_t * vGlo2Cs; // global variables into cur state variables + Vec_Int_t * vGlo2Ns; // global variables into next state variables +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes cube composed of given variables with given values.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_CoreComputeCube( DdManager * dd, Vec_Int_t * vVars, int fUseVarIndex, char * pValues ) +{ + DdNode * bRes, * bVar, * bTemp; + int i, iVar, Index; + abctime TimeStop; + TimeStop = dd->TimeStop; dd->TimeStop = 0; + bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); + Vec_IntForEachEntry( vVars, Index, i ) + { + iVar = fUseVarIndex ? Index : i; + bVar = Cudd_NotCond( Cudd_bddIthVar(dd, iVar), (int)(pValues == NULL || pValues[i] != 1) ); + bRes = Cudd_bddAnd( dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bRes ); + dd->TimeStop = TimeStop; + return bRes; +} + +/**Function************************************************************* + + Synopsis [Derives counter-example by backward reachability.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Llb_CoreDeriveCex( Llb_Img_t * p ) +{ + Abc_Cex_t * pCex; + Aig_Obj_t * pObj; + Vec_Ptr_t * vSupps, * vQuant0, * vQuant1; + DdNode * bState = NULL, * bImage, * bOneCube, * bTemp, * bRing; + int i, v, RetValue, nPiOffset; + char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) ); + assert( Vec_PtrSize(p->vRings) > 0 ); + + p->dd->TimeStop = 0; + p->ddR->TimeStop = 0; + + // get supports and quantified variables + Vec_PtrReverseOrder( p->vDdMans ); + vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsNs, p->vVarsCs, 1, 0 ); + Llb_ImgSchedule( vSupps, &vQuant0, &vQuant1, 0 ); + Vec_VecFree( (Vec_Vec_t *)vSupps ); + Llb_ImgQuantifyReset( p->vDdMans ); +// Llb_ImgQuantifyFirst( p->pAig, p->vDdMans, vQuant0 ); + + // allocate room for the counter-example + pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) ); + pCex->iFrame = Vec_PtrSize(p->vRings) - 1; + pCex->iPo = -1; + + // get the last cube + bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc ); Cudd_Ref( bOneCube ); + RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); + Cudd_RecursiveDeref( p->ddR, bOneCube ); + assert( RetValue ); + + // write PIs of counter-example + nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1); + Saig_ManForEachPi( p->pAig, pObj, i ) + if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) + Abc_InfoSetBit( pCex->pData, nPiOffset + i ); + + // write state in terms of NS variables + if ( Vec_PtrSize(p->vRings) > 1 ) + { + bState = Llb_CoreComputeCube( p->dd, p->vVarsNs, 1, pValues ); Cudd_Ref( bState ); + } + // perform backward analysis + Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v ) + { + if ( v == Vec_PtrSize(p->vRings) - 1 ) + continue; + // compute the next states + bImage = Llb_ImgComputeImage( p->pAig, p->vDdMans, p->dd, bState, + vQuant0, vQuant1, p->vDriRefs, p->pPars->TimeTarget, 1, 0, 0 ); + assert( bImage != NULL ); + Cudd_Ref( bImage ); + Cudd_RecursiveDeref( p->dd, bState ); +//Extra_bddPrintSupport( p->dd, bImage ); printf( "\n" ); + + // move reached states into ring manager + bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) ); Cudd_Ref( bImage ); + Cudd_RecursiveDeref( p->dd, bTemp ); + + // intersect with the previous set + bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing ); Cudd_Ref( bOneCube ); + Cudd_RecursiveDeref( p->ddR, bImage ); + + // find any assignment of the BDD + RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); + Cudd_RecursiveDeref( p->ddR, bOneCube ); + assert( RetValue ); + + // write PIs of counter-example + nPiOffset -= Saig_ManPiNum(p->pAig); + Saig_ManForEachPi( p->pAig, pObj, i ) + if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) + Abc_InfoSetBit( pCex->pData, nPiOffset + i ); + + // check that we get the init state + if ( v == 0 ) + { + Saig_ManForEachLo( p->pAig, pObj, i ) + assert( pValues[i] == 0 ); + break; + } + + // write state in terms of NS variables + bState = Llb_CoreComputeCube( p->dd, p->vVarsNs, 1, pValues ); Cudd_Ref( bState ); + } + assert( nPiOffset == Saig_ManRegNum(p->pAig) ); + // update the output number + RetValue = Saig_ManFindFailedPoCex( p->pInit, pCex ); + assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pInit) ); // invalid CEX!!! + pCex->iPo = RetValue; + // cleanup + ABC_FREE( pValues ); + Vec_VecFree( (Vec_Vec_t *)vQuant0 ); + Vec_VecFree( (Vec_Vec_t *)vQuant1 ); + return pCex; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_CoreReachability_int( Llb_Img_t * p, Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1 ) +{ + int * pLoc2Glo = p->pPars->fBackward? Vec_IntArray( p->vCs2Glo ) : Vec_IntArray( p->vNs2Glo ); + int * pLoc2GloR = p->pPars->fBackward? Vec_IntArray( p->vNs2Glo ) : Vec_IntArray( p->vCs2Glo ); + int * pGlo2Loc = p->pPars->fBackward? Vec_IntArray( p->vGlo2Ns ) : Vec_IntArray( p->vGlo2Cs ); + DdNode * bCurrent, * bReached, * bNext, * bTemp; + abctime clk2, clk = Abc_Clock(); + int nIters, nBddSize;//, iOutFail = -1; +/* + // compute time to stop + if ( p->pPars->TimeLimit ) + p->pPars->TimeTarget = Abc_Clock() + p->pPars->TimeLimit * CLOCKS_PER_SEC; + else + p->pPars->TimeTarget = 0; +*/ + + if ( Abc_Clock() > p->pPars->TimeTarget ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) before image computation.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + + // set the stop time parameter + p->dd->TimeStop = p->pPars->TimeTarget; + p->ddG->TimeStop = p->pPars->TimeTarget; + p->ddR->TimeStop = p->pPars->TimeTarget; + + // compute initial states + if ( p->pPars->fBackward ) + { + // create init state in the global manager + bTemp = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget ); + if ( bTemp == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) while computing bad states.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + Cudd_Ref( bTemp ); + // create bad state in the ring manager + p->ddR->bFunc = Llb_CoreComputeCube( p->ddR, p->vVarsCs, 0, NULL ); Cudd_Ref( p->ddR->bFunc ); + bCurrent = Llb_BddQuantifyPis( p->pInit, p->ddR, bTemp ); Cudd_Ref( bCurrent ); + Cudd_RecursiveDeref( p->ddR, bTemp ); + bReached = Cudd_bddTransfer( p->ddR, p->ddG, bCurrent ); Cudd_Ref( bReached ); + Cudd_RecursiveDeref( p->ddR, bCurrent ); + // move init state to the working manager + bCurrent = Extra_TransferPermute( p->ddG, p->dd, bReached, pGlo2Loc ); + if ( bCurrent == NULL ) + { + Cudd_RecursiveDeref( p->ddG, bReached ); + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during transfer 0.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + Cudd_Ref( bCurrent ); + } + else + { + // create bad state in the ring manager + p->ddR->bFunc = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget ); + if ( p->ddR->bFunc == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) while computing bad states.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + Cudd_Ref( p->ddR->bFunc ); + // create init state in the working and global manager + bCurrent = Llb_CoreComputeCube( p->dd, p->vVarsCs, 1, NULL ); Cudd_Ref( bCurrent ); + bReached = Llb_CoreComputeCube( p->ddG, p->vVarsCs, 0, NULL ); Cudd_Ref( bReached ); +//Extra_bddPrint( p->dd, bCurrent ); printf( "\n" ); +//Extra_bddPrint( p->ddG, bReached ); printf( "\n" ); + } + + // compute onion rings + for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ ) + { + clk2 = Abc_Clock(); + // check the runtime limit + if ( p->pPars->TimeLimit && Abc_Clock() > p->pPars->TimeTarget ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + + // save the onion ring + bTemp = Extra_TransferPermute( p->dd, p->ddR, bCurrent, pLoc2GloR ); + if ( bTemp == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bTemp ); + Vec_PtrPush( p->vRings, bTemp ); + + // check it for bad states + if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) ) + { + assert( p->pInit->pSeqModel == NULL ); + if ( !p->pPars->fBackward ) + p->pInit->pSeqModel = Llb_CoreDeriveCex( p ); + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + if ( !p->pPars->fSilent ) + { + if ( !p->pPars->fBackward ) + Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", p->pInit->pSeqModel->iPo, p->pInit->pName, nIters ); + else + Abc_Print( 1, "Output ??? was asserted in frame %d (counter-example is not produced). ", nIters ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + p->pPars->iFrame = nIters - 1; + return 0; + } + + // compute the next states + bNext = Llb_ImgComputeImage( p->pAig, p->vDdMans, p->dd, bCurrent, + vQuant0, vQuant1, p->vDriRefs, p->pPars->TimeTarget, + p->pPars->fBackward, p->pPars->fReorder, p->pPars->fVeryVerbose ); + if ( bNext == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bNext ); + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; +//Extra_bddPrintSupport( p->dd, bNext ); printf( "\n" ); + + // remap these states into the global manager +// bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pLoc2Glo ); Cudd_Ref( bNext ); +// Cudd_RecursiveDeref( p->dd, bTemp ); + +// bNext = Extra_TransferPermuteTime( p->dd, p->ddG, bTemp = bNext, pLoc2Glo, p->pPars->TimeTarget ); + bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pLoc2Glo ); + if ( bNext == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bNext ); + Cudd_RecursiveDeref( p->dd, bTemp ); + + nBddSize = Cudd_DagSize(bNext); + // check if there are any new states + if ( Cudd_bddLeq( p->ddG, bNext, bReached ) ) // implication = no new states + { + Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; + break; + } + + // get the new states + bCurrent = Cudd_bddAnd( p->ddG, bNext, Cudd_Not(bReached) ); + if ( bCurrent == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->ddG, bNext ); + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bCurrent ); + + // remap these states into the current state vars +// bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc ); Cudd_Ref( bCurrent ); +// Cudd_RecursiveDeref( p->ddG, bTemp ); + +// bCurrent = Extra_TransferPermuteTime( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc, p->pPars->TimeTarget ); + bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc ); + if ( bCurrent == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->ddG, bTemp ); + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bCurrent ); + Cudd_RecursiveDeref( p->ddG, bTemp ); + + // add to the reached states + bReached = Cudd_bddOr( p->ddG, bTemp = bReached, bNext ); Cudd_Ref( bReached ); + Cudd_RecursiveDeref( p->ddG, bTemp ); + Cudd_RecursiveDeref( p->ddG, bNext ); + bNext = NULL; + + if ( p->pPars->fVeryVerbose ) + { + double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); +// Extra_bddPrint( p->ddG, bReached );printf( "\n" ); + fprintf( stdout, " Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); + fflush( stdout ); + } + if ( p->pPars->fVerbose ) + { + fprintf( stdout, "F =%3d : ", nIters ); + fprintf( stdout, "Image =%6d ", nBddSize ); + fprintf( stdout, "(%4d%4d) ", + Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) ); + fprintf( stdout, "Reach =%6d ", Cudd_DagSize(bReached) ); + fprintf( stdout, "(%4d%4d) ", + Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk2 ); + } + + // check timeframe limit + if ( nIters == p->pPars->nIterMax - 1 ) + { + if ( !p->pPars->fSilent ) + printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nIterMax ); + p->pPars->iFrame = nIters; + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + } + if ( bReached == NULL ) + { + p->pPars->iFrame = nIters - 1; + return 0; // reachable + } + if ( bCurrent ) + Cudd_RecursiveDeref( p->dd, bCurrent ); + // report the stats + if ( p->pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); + if ( nIters >= p->pPars->nIterMax ) + fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters ); + else + fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters ); + fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); + fflush( stdout ); + } + if ( p->pPars->fDumpReached ) + { + Llb_ManDumpReached( p->ddG, bReached, p->pAig->pName, "reached.blif" ); + printf( "Reached states with %d BDD nodes are dumpted into file \"reached.blif\".\n", Cudd_DagSize(bReached) ); + } + Cudd_RecursiveDeref( p->ddG, bReached ); + if ( nIters >= p->pPars->nIterMax ) + { + if ( !p->pPars->fSilent ) + { + printf( "Verified only for states reachable in %d frames. ", nIters ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + p->pPars->iFrame = p->pPars->nIterMax; + return -1; // undecided + } + if ( !p->pPars->fSilent ) + { + printf( "The miter is proved unreachable after %d iterations. ", nIters ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + p->pPars->iFrame = nIters - 1; + return 1; // unreachable +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_CoreReachability( Llb_Img_t * p ) +{ + Vec_Ptr_t * vSupps, * vQuant0, * vQuant1; + int RetValue; + // get supports and quantified variables + if ( p->pPars->fBackward ) + { + Vec_PtrReverseOrder( p->vDdMans ); + vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsNs, p->vVarsCs, 0, p->pPars->fVeryVerbose ); + } + else + vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsCs, p->vVarsNs, 0, p->pPars->fVeryVerbose ); + Llb_ImgSchedule( vSupps, &vQuant0, &vQuant1, p->pPars->fVeryVerbose ); + Vec_VecFree( (Vec_Vec_t *)vSupps ); + // remove variables + Llb_ImgQuantifyFirst( p->pAig, p->vDdMans, vQuant0, p->pPars->fVeryVerbose ); + // perform reachability + RetValue = Llb_CoreReachability_int( p, vQuant0, vQuant1 ); + Vec_VecFree( (Vec_Vec_t *)vQuant0 ); + Vec_VecFree( (Vec_Vec_t *)vQuant1 ); + return RetValue; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_CoreConstructAll( Aig_Man_t * p, Vec_Ptr_t * vResult, Vec_Int_t * vVarsNs, abctime TimeTarget ) +{ + DdManager * dd; + Vec_Ptr_t * vDdMans; + Vec_Ptr_t * vLower, * vUpper = NULL; + int i; + vDdMans = Vec_PtrStart( Vec_PtrSize(vResult) ); + Vec_PtrForEachEntryReverse( Vec_Ptr_t *, vResult, vLower, i ) + { + if ( i < Vec_PtrSize(vResult) - 1 ) + dd = Llb_ImgPartition( p, vLower, vUpper, TimeTarget ); + else + dd = Llb_DriverLastPartition( p, vVarsNs, TimeTarget ); + if ( dd == NULL ) + { + Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i ) + { + if ( dd == NULL ) + continue; + if ( dd->bFunc ) + Cudd_RecursiveDeref( dd, dd->bFunc ); + Extra_StopManager( dd ); + } + Vec_PtrFree( vDdMans ); + return NULL; + } + Vec_PtrWriteEntry( vDdMans, i, dd ); + vUpper = vLower; + } + return vDdMans; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_CoreSetVarMaps( Llb_Img_t * p ) +{ + Aig_Obj_t * pObj; + int i, iVarCs, iVarNs; + assert( p->vVarsCs != NULL ); + assert( p->vVarsNs != NULL ); + assert( p->vCs2Glo == NULL ); + assert( p->vNs2Glo == NULL ); + assert( p->vGlo2Cs == NULL ); + assert( p->vGlo2Ns == NULL ); + p->vCs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) ); + p->vNs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) ); + p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); + p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); + for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ ) + { + iVarCs = Vec_IntEntry( p->vVarsCs, i ); + iVarNs = Vec_IntEntry( p->vVarsNs, i ); + assert( iVarCs >= 0 && iVarCs < Aig_ManObjNumMax(p->pAig) ); + assert( iVarNs >= 0 && iVarNs < Aig_ManObjNumMax(p->pAig) ); + Vec_IntWriteEntry( p->vCs2Glo, iVarCs, i ); + Vec_IntWriteEntry( p->vNs2Glo, iVarNs, i ); + Vec_IntWriteEntry( p->vGlo2Cs, i, iVarCs ); + Vec_IntWriteEntry( p->vGlo2Ns, i, iVarNs ); + } + // add mapping of the PIs + Saig_ManForEachPi( p->pAig, pObj, i ) + Vec_IntWriteEntry( p->vCs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Img_t * Llb_CoreStart( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) +{ + Llb_Img_t * p; + p = ABC_CALLOC( Llb_Img_t, 1 ); + p->pInit = pInit; + p->pAig = pAig; + p->pPars = pPars; + p->dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + p->ddG = Cudd_Init( Aig_ManRegNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + p->ddR = Cudd_Init( Aig_ManCiNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); + Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT ); + Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT ); + p->vRings = Vec_PtrAlloc( 100 ); + p->vDriRefs = Llb_DriverCountRefs( pAig ); + p->vVarsCs = Llb_DriverCollectCs( pAig ); + p->vVarsNs = Llb_DriverCollectNs( pAig, p->vDriRefs ); + Llb_CoreSetVarMaps( p ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_CoreStop( Llb_Img_t * p ) +{ + DdManager * dd; + DdNode * bTemp; + int i; + if ( p->vDdMans ) + Vec_PtrForEachEntry( DdManager *, p->vDdMans, dd, i ) + { + if ( dd->bFunc ) + Cudd_RecursiveDeref( dd, dd->bFunc ); + if ( dd->bFunc2 ) + Cudd_RecursiveDeref( dd, dd->bFunc2 ); + Extra_StopManager( dd ); + } + Vec_PtrFreeP( &p->vDdMans ); + if ( p->ddR->bFunc ) + Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc ); + Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i ) + Cudd_RecursiveDeref( p->ddR, bTemp ); + Vec_PtrFree( p->vRings ); + Extra_StopManager( p->dd ); + Extra_StopManager( p->ddG ); + Extra_StopManager( p->ddR ); + Vec_IntFreeP( &p->vDriRefs ); + Vec_IntFreeP( &p->vVarsCs ); + Vec_IntFreeP( &p->vVarsNs ); + Vec_IntFreeP( &p->vCs2Glo ); + Vec_IntFreeP( &p->vNs2Glo ); + Vec_IntFreeP( &p->vGlo2Cs ); + Vec_IntFreeP( &p->vGlo2Ns ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_CoreExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, abctime TimeTarget ) +{ + int RetValue; + Llb_Img_t * p; +// printf( "\n" ); +// pPars->fVerbose = 1; + p = Llb_CoreStart( pInit, pAig, pPars ); + p->vDdMans = Llb_CoreConstructAll( pAig, vResult, p->vVarsNs, TimeTarget ); + if ( p->vDdMans == NULL ) + { + if ( !pPars->fSilent ) + printf( "Reached timeout (%d seconds) while deriving the partitions.\n", pPars->TimeLimit ); + Llb_CoreStop( p ); + return -1; + } + RetValue = Llb_CoreReachability( p ); + Llb_CoreStop( p ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManReachMinCut( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) +{ + extern Vec_Ptr_t * Llb_ManComputeCuts( Aig_Man_t * p, int Num, int fVerbose, int fVeryVerbose ); + Vec_Ptr_t * vResult; + Aig_Man_t * p; + int RetValue = -1; + abctime clk = Abc_Clock(); + + // compute time to stop + pPars->TimeTarget = pPars->TimeLimit ? pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0; + + p = Aig_ManDupFlopsOnly( pAig ); +//Aig_ManShow( p, 0, NULL ); + if ( pPars->fVerbose ) + Aig_ManPrintStats( pAig ); + if ( pPars->fVerbose ) + Aig_ManPrintStats( p ); + Aig_ManFanoutStart( p ); + + vResult = Llb_ManComputeCuts( p, pPars->nPartValue, pPars->fVerbose, pPars->fVeryVerbose ); + + if ( pPars->TimeLimit && Abc_Clock() > pPars->TimeTarget ) + { + if ( !pPars->fSilent ) + printf( "Reached timeout (%d seconds) after partitioning.\n", pPars->TimeLimit ); + + Vec_VecFree( (Vec_Vec_t *)vResult ); + Aig_ManFanoutStop( p ); + Aig_ManCleanMarkAB( p ); + Aig_ManStop( p ); + return RetValue; + } + + if ( !pPars->fSkipReach ) + RetValue = Llb_CoreExperiment( pAig, p, pPars, vResult, pPars->TimeTarget ); + + Vec_VecFree( (Vec_Vec_t *)vResult ); + Aig_ManFanoutStop( p ); + Aig_ManCleanMarkAB( p ); + Aig_ManStop( p ); + + if ( RetValue == -1 ) + Abc_PrintTime( 1, "Total runtime of the min-cut-based reachability engine", Abc_Clock() - clk ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb2Driver.c b/src/bdd/llb/llb2Driver.c new file mode 100644 index 00000000..1471f377 --- /dev/null +++ b/src/bdd/llb/llb2Driver.c @@ -0,0 +1,222 @@ +/**CFile**************************************************************** + + FileName [llb2Driver.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Procedures working with flop drivers.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Driver.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// driver issue:arises when creating +// - driver ref-counter array +// - Ns2Glo maps +// - final partition +// - change-phase cube + +// LI variable is used when +// - driver drives more than one LI +// - driver is a PI +// - driver is a constant + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the array of times each flop driver is referenced.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_DriverCountRefs( Aig_Man_t * p ) +{ + Vec_Int_t * vCounts; + Aig_Obj_t * pObj; + int i; + vCounts = Vec_IntStart( Aig_ManObjNumMax(p) ); + Saig_ManForEachLi( p, pObj, i ) + Vec_IntAddToEntry( vCounts, Aig_ObjFaninId0(pObj), 1 ); + return vCounts; +} + +/**Function************************************************************* + + Synopsis [Returns array of NS variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_DriverCollectNs( Aig_Man_t * pAig, Vec_Int_t * vDriRefs ) +{ + Vec_Int_t * vVars; + Aig_Obj_t * pObj, * pDri; + int i; + vVars = Vec_IntAlloc( Aig_ManRegNum(pAig) ); + Saig_ManForEachLi( pAig, pObj, i ) + { + pDri = Aig_ObjFanin0(pObj); + if ( Vec_IntEntry( vDriRefs, Aig_ObjId(pDri) ) != 1 || Saig_ObjIsPi(pAig, pDri) || Aig_ObjIsConst1(pDri) ) + Vec_IntPush( vVars, Aig_ObjId(pObj) ); + else + Vec_IntPush( vVars, Aig_ObjId(pDri) ); + } + return vVars; +} + +/**Function************************************************************* + + Synopsis [Returns array of CS variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_DriverCollectCs( Aig_Man_t * pAig ) +{ + Vec_Int_t * vVars; + Aig_Obj_t * pObj; + int i; + vVars = Vec_IntAlloc( Aig_ManRegNum(pAig) ); + Saig_ManForEachLo( pAig, pObj, i ) + Vec_IntPush( vVars, Aig_ObjId(pObj) ); + return vVars; +} + +/**Function************************************************************* + + Synopsis [Create cube for phase swapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_DriverPhaseCube( Aig_Man_t * pAig, Vec_Int_t * vDriRefs, DdManager * dd ) +{ + DdNode * bCube, * bVar, * bTemp; + Aig_Obj_t * pObj; + int i; + abctime TimeStop; + TimeStop = dd->TimeStop; dd->TimeStop = 0; + bCube = Cudd_ReadOne( dd ); Cudd_Ref( bCube ); + Saig_ManForEachLi( pAig, pObj, i ) + { + assert( Vec_IntEntry( vDriRefs, Aig_ObjFaninId0(pObj) ) >= 1 ); + if ( Vec_IntEntry( vDriRefs, Aig_ObjFaninId0(pObj) ) != 1 ) + continue; + if ( !Aig_ObjFaninC0(pObj) ) + continue; + bVar = Cudd_bddIthVar( dd, Aig_ObjFaninId0(pObj) ); + bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bCube ); + dd->TimeStop = TimeStop; + return bCube; +} + +/**Function************************************************************* + + Synopsis [Compute the last partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdManager * Llb_DriverLastPartition( Aig_Man_t * p, Vec_Int_t * vVarsNs, abctime TimeTarget ) +{ +// int fVerbose = 1; + DdManager * dd; + DdNode * bVar1, * bVar2, * bProd, * bRes, * bTemp; + Aig_Obj_t * pObj; + int i; + dd = Cudd_Init( Aig_ManObjNumMax(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + dd->TimeStop = TimeTarget; + bRes = Cudd_ReadOne(dd); Cudd_Ref( bRes ); + + // mark the duplicated flop inputs + Aig_ManForEachObjVec( vVarsNs, p, pObj, i ) + { + if ( !Saig_ObjIsLi(p, pObj) ) + continue; + bVar1 = Cudd_bddIthVar( dd, Aig_ObjId(pObj) ); + bVar2 = Cudd_bddIthVar( dd, Aig_ObjFaninId0(pObj) ); + if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) + bVar2 = Cudd_ReadOne(dd); + bVar2 = Cudd_NotCond( bVar2, Aig_ObjFaninC0(pObj) ); + bProd = Cudd_bddXnor( dd, bVar1, bVar2 ); Cudd_Ref( bProd ); +// bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); Cudd_Ref( bRes ); +// bRes = Extra_bddAndTime( dd, bTemp = bRes, bProd, TimeTarget ); + bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bProd ); + return NULL; + } + Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bProd ); + } + +/* + Saig_ManForEachLi( p, pObj, i ) + printf( "%d ", Aig_ObjId(pObj) ); + printf( "\n" ); + Saig_ManForEachLi( p, pObj, i ) + printf( "%c%d ", Aig_ObjFaninC0(pObj)? '-':'+', Aig_ObjFaninId0(pObj) ); + printf( "\n" ); +*/ + Cudd_AutodynDisable( dd ); +// Cudd_RecursiveDeref( dd, bRes ); +// Extra_StopManager( dd ); + dd->bFunc = bRes; + dd->TimeStop = 0; + return dd; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb2Dump.c b/src/bdd/llb/llb2Dump.c new file mode 100644 index 00000000..74f07922 --- /dev/null +++ b/src/bdd/llb/llb2Dump.c @@ -0,0 +1,104 @@ +/**CFile**************************************************************** + + FileName [llb2Dump.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Dumps the BDD of reached states into a file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Dump.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns a dummy name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Llb_ManGetDummyName( char * pPrefix, int Num, int nDigits ) +{ + static char Buffer[2000]; + sprintf( Buffer, "%s%0*d", pPrefix, nDigits, Num ); + return Buffer; +} + +/**Function************************************************************* + + Synopsis [Writes reached state BDD into a BLIF file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManDumpReached( DdManager * ddG, DdNode * bReached, char * pModel, char * pFileName ) +{ + FILE * pFile; + Vec_Ptr_t * vNamesIn, * vNamesOut; + char * pName; + int i, nDigits; + // reorder the BDD + Cudd_ReduceHeap( ddG, CUDD_REORDER_SYMM_SIFT, 1 ); + + // create input names + nDigits = Abc_Base10Log( Cudd_ReadSize(ddG) ); + vNamesIn = Vec_PtrAlloc( Cudd_ReadSize(ddG) ); + for ( i = 0; i < Cudd_ReadSize(ddG); i++ ) + { + pName = Llb_ManGetDummyName( "ff", i, nDigits ); + Vec_PtrPush( vNamesIn, Extra_UtilStrsav(pName) ); + } + // create output names + vNamesOut = Vec_PtrAlloc( 1 ); + Vec_PtrPush( vNamesOut, Extra_UtilStrsav("Reached") ); + + // write the file + pFile = fopen( pFileName, "wb" ); + Cudd_DumpBlif( ddG, 1, &bReached, (char **)Vec_PtrArray(vNamesIn), (char **)Vec_PtrArray(vNamesOut), pModel, pFile, 0 ); + fclose( pFile ); + + // cleanup + Vec_PtrForEachEntry( char *, vNamesIn, pName, i ) + ABC_FREE( pName ); + Vec_PtrForEachEntry( char *, vNamesOut, pName, i ) + ABC_FREE( pName ); + Vec_PtrFree( vNamesIn ); + Vec_PtrFree( vNamesOut ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb2Flow.c b/src/bdd/llb/llb2Flow.c new file mode 100644 index 00000000..64db32b3 --- /dev/null +++ b/src/bdd/llb/llb2Flow.c @@ -0,0 +1,1376 @@ +/**CFile**************************************************************** + + FileName [llb2Flow.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Flow computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Flow.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Llb_ObjSetPath( Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { pObj->pData = (void *)pNext; return 1; } +static inline Aig_Obj_t * Llb_ObjGetPath( Aig_Obj_t * pObj ) { return (Aig_Obj_t *)pObj->pData; } +static inline Aig_Obj_t * Llb_ObjGetFanoutPath( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pFanout; + int i, iFanout = -1; + assert( Llb_ObjGetPath(pObj) ); + Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) + if ( Llb_ObjGetPath(pFanout) == pObj ) + return pFanout; + return NULL; +} + +extern Vec_Ptr_t * Llb_ManCutSupp( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +/**Function************************************************************* + + Synopsis [For each cut, returns PIs that can be quantified.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManCutSupps( Aig_Man_t * p, Vec_Ptr_t * vResult ) +{ + Vec_Ptr_t * vSupps, * vOne, * vLower, * vUpper; + int i; + vSupps = Vec_PtrAlloc( 100 ); + Vec_PtrPush( vSupps, Vec_PtrAlloc(0) ); + vLower = (Vec_Ptr_t *)Vec_PtrEntry( vResult, 0 ); + Vec_PtrForEachEntryStart( Vec_Ptr_t *, vResult, vUpper, i, 1 ) + { + vOne = Llb_ManCutSupp( p, vLower, vUpper ); + Vec_PtrPush( vSupps, vOne ); + vLower = vUpper; + } + assert( Vec_PtrSize(vSupps) == Vec_PtrSize(vResult) ); + return vSupps; +} + +/**Function************************************************************* + + Synopsis [For each cut, returns PIs that can be quantified.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManCutMap( Aig_Man_t * p, Vec_Ptr_t * vResult, Vec_Ptr_t * vSupps ) +{ + int fShowMatrix = 1; + Vec_Ptr_t * vMaps, * vOne; + Vec_Int_t * vMap, * vPrev, * vNext; + Aig_Obj_t * pObj; + int * piFirst, * piLast; + int i, k, CounterPlus, CounterMinus, Counter; + + vMaps = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Vec_Ptr_t *, vResult, vOne, i ) + { + vMap = Vec_IntStart( Aig_ManObjNumMax(p) ); + Vec_PtrForEachEntry( Aig_Obj_t *, vOne, pObj, k ) + { + if ( !Saig_ObjIsPi(p, pObj) ) + Vec_IntWriteEntry( vMap, pObj->Id, 1 ); +// else +//printf( "*" ); +//printf( "%d ", pObj->Id ); + } + Vec_PtrPush( vMaps, vMap ); +//printf( "\n" ); + } + Vec_PtrPush( vMaps, Vec_IntStart( Aig_ManObjNumMax(p) ) ); + assert( Vec_PtrSize(vMaps) == Vec_PtrSize(vResult)+1 ); + + // collect the first and last PIs + piFirst = ABC_ALLOC( int, Saig_ManPiNum(p) ); + piLast = ABC_ALLOC( int, Saig_ManPiNum(p) ); + Saig_ManForEachPi( p, pObj, i ) + piFirst[i] = piLast[i] = -1; + Vec_PtrForEachEntry( Vec_Ptr_t *, vSupps, vOne, i ) + { + Vec_PtrForEachEntry( Aig_Obj_t *, vOne, pObj, k ) + { + if ( !Saig_ObjIsPi(p, pObj) ) + continue; + if ( piFirst[Aig_ObjCioId(pObj)] == -1 ) + piFirst[Aig_ObjCioId(pObj)] = i; + piLast[Aig_ObjCioId(pObj)] = i; + } + } + // PIs feeding into the flops should be extended to the last frame + Saig_ManForEachLi( p, pObj, i ) + { + if ( !Saig_ObjIsPi(p, Aig_ObjFanin0(pObj)) ) + continue; + piLast[Aig_ObjCioId(Aig_ObjFanin0(pObj))] = Vec_PtrSize(vMaps)-1; + } + + // set the PI map + Saig_ManForEachPi( p, pObj, i ) + { + if ( piFirst[i] == -1 ) + continue; + if ( piFirst[i] == piLast[i] ) + { + vMap = (Vec_Int_t *)Vec_PtrEntry( vMaps, piFirst[i] ); + Vec_IntWriteEntry( vMap, pObj->Id, 2 ); + continue; + } + + // set support for all in between + for ( k = piFirst[i]; k <= piLast[i]; k++ ) + { + vMap = (Vec_Int_t *)Vec_PtrEntry( vMaps, k ); + Vec_IntWriteEntry( vMap, pObj->Id, 1 ); + } + } + ABC_FREE( piFirst ); + ABC_FREE( piLast ); + + + // find all that will appear here + Counter = Aig_ManRegNum(p); + printf( "%d ", Counter ); + Vec_PtrForEachEntryStart( Vec_Int_t *, vMaps, vMap, i, 1 ) + { + vPrev = (Vec_Int_t *)Vec_PtrEntry( vMaps, i-1 ); + vNext = (i == Vec_PtrSize(vMaps)-1)? NULL: (Vec_Int_t *)Vec_PtrEntry( vMaps, i+1 ); + + CounterPlus = CounterMinus = 0; + Aig_ManForEachObj( p, pObj, k ) + { + if ( Saig_ObjIsPi(p, pObj) ) + { + if ( Vec_IntEntry(vPrev, k) == 0 && Vec_IntEntry(vMap, k) == 1 ) + CounterPlus++; + if ( Vec_IntEntry(vMap, k) == 1 && (vNext == NULL || Vec_IntEntry(vNext, k) == 0) ) + CounterMinus++; + } + else + { + if ( Vec_IntEntry(vPrev, k) == 0 && Vec_IntEntry(vMap, k) == 1 ) + CounterPlus++; + if ( Vec_IntEntry(vPrev, k) == 1 && Vec_IntEntry(vMap, k) == 0 ) + CounterMinus++; + } + } + Counter = Counter + CounterPlus - CounterMinus; + printf( "%d=%d ", i, Counter ); + } + printf( "\n" ); + + if ( !fShowMatrix ) + return vMaps; + Aig_ManForEachObj( p, pObj, i ) + { + if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) ) + continue; + Vec_PtrForEachEntry( Vec_Int_t *, vMaps, vMap, k ) + if ( Vec_IntEntry(vMap, i) ) + break; + if ( k == Vec_PtrSize(vMaps) ) + continue; + printf( "Obj = %4d : ", i ); + if ( Saig_ObjIsPi(p,pObj) ) + printf( "pi " ); + else if ( Saig_ObjIsLo(p,pObj) ) + printf( "lo " ); + else if ( Aig_ObjIsNode(pObj) ) + printf( "and " ); + + Vec_PtrForEachEntry( Vec_Int_t *, vMaps, vMap, k ) + printf( "%d", Vec_IntEntry(vMap, i) ); + printf( "\n" ); + } + return vMaps; +} + +/**Function************************************************************* + + Synopsis [Counts the number of PIs in the cut] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManCutPiNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) + if ( Saig_ObjIsPi(p,pObj) ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of LOs in the cut] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManCutLoNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) + if ( Saig_ObjIsLo(p,pObj) ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of LIs in the cut] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManCutLiNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) +{ + Aig_Obj_t * pFanout; + Aig_Obj_t * pObj; + int i, k, iFanout = -1, Counter = 0; + Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) + { + if ( Aig_ObjIsCi(pObj) ) + continue; + Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, k ) + { + if ( Saig_ObjIsLi(p, pFanout) ) + { + Counter++; + break; + } + } + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManCutVolume_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return 0; + Aig_ObjSetTravIdCurrent(p, pObj); + assert( Aig_ObjIsNode(pObj) ); + return 1 + Llb_ManCutVolume_rec(p, Aig_ObjFanin0(pObj)) + + Llb_ManCutVolume_rec(p, Aig_ObjFanin1(pObj)); +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManCutVolume( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + // mark the lower cut with the traversal ID + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // count the upper cut + Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) + Counter += Llb_ManCutVolume_rec( p, pObj ); + return Counter; +} + + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManCutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + assert( Aig_ObjIsNode(pObj) ); + Llb_ManCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); + Llb_ManCutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + // mark the lower cut with the traversal ID + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // count the upper cut + vNodes = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) + Llb_ManCutNodes_rec( p, pObj, vNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManCutSupp( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) +{ + Vec_Ptr_t * vNodes, * vSupp; + Aig_Obj_t * pObj; + int i; + vNodes = Llb_ManCutNodes( p, vLower, vUpper ); + // mark support of the nodes + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + assert( Aig_ObjIsNode(pObj) ); + Aig_ObjSetTravIdCurrent( p, Aig_ObjFanin0(pObj) ); + Aig_ObjSetTravIdCurrent( p, Aig_ObjFanin1(pObj) ); + } + Vec_PtrFree( vNodes ); + // collect the support nodes + vSupp = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + Vec_PtrPush( vSupp, pObj ); + return vSupp; + +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManCutRange( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) +{ + Vec_Ptr_t * vRange; + Aig_Obj_t * pObj; + int i; + // mark the lower cut with the traversal ID + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // collect the upper ones that are not marked + vRange = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) + if ( !Aig_ObjIsTravIdCurrent(p, pObj) ) + Vec_PtrPush( vRange, pObj ); + return vRange; +} + + + + +/**Function************************************************************* + + Synopsis [Prints the given cluster.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManCutPrint( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) +{ + Vec_Ptr_t * vSupp, * vRange; + int Pis, Ffs, And; + + Pis = Llb_ManCutPiNum(p, vLower); + Ffs = Llb_ManCutLoNum(p, vLower); + And = Vec_PtrSize(vLower) - Pis - Ffs; + printf( "Leaf: %3d=%3d+%3d+%3d ", Vec_PtrSize(vLower), Pis, Ffs, And ); + + Pis = Llb_ManCutPiNum(p, vUpper); + Ffs = Llb_ManCutLiNum(p, vUpper); + And = Vec_PtrSize(vUpper) - Pis - Ffs; + printf( "Root: %3d=%3d+%3d+%3d ", Vec_PtrSize(vUpper), Pis, Ffs, And ); + + vSupp = Llb_ManCutSupp( p, vLower, vUpper ); + Pis = Llb_ManCutPiNum(p, vSupp); + Ffs = Llb_ManCutLoNum(p, vSupp); + And = Vec_PtrSize(vSupp) - Pis - Ffs; + printf( "Supp: %3d=%3d+%3d+%3d ", Vec_PtrSize(vSupp), Pis, Ffs, And ); + + vRange = Llb_ManCutRange( p, vLower, vUpper ); + Pis = Llb_ManCutPiNum(p, vRange); + Ffs = Llb_ManCutLiNum(p, vRange); + And = Vec_PtrSize(vRange) - Pis - Ffs; + printf( "Range: %3d=%3d+%3d+%3d ", Vec_PtrSize(vRange), Pis, Ffs, And ); + + printf( "S =%3d. V =%3d.\n", + Vec_PtrSize(vSupp)+Vec_PtrSize(vRange), Llb_ManCutVolume(p, vLower, vUpper) ); + Vec_PtrFree( vSupp ); + Vec_PtrFree( vRange ); +/* + { + Aig_Obj_t * pObj; + int i; + printf( "Lower: " ); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + printf( " %d", pObj->Id ); + printf( " " ); + printf( "Upper: " ); + Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) + printf( " %d", pObj->Id ); + printf( "\n" ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Prints the given cluster.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManResultPrint( Aig_Man_t * p, Vec_Ptr_t * vResult ) +{ + Vec_Ptr_t * vLower, * vUpper = NULL; + int i; + Vec_PtrForEachEntryReverse( Vec_Ptr_t *, vResult, vLower, i ) + { + if ( i < Vec_PtrSize(vResult) - 1 ) + Llb_ManCutPrint( p, vLower, vUpper ); + vUpper = vLower; + } +} + +/**Function************************************************************* + + Synopsis [Tries to find an augmenting path originating in this node.] + + Description [This procedure works for directed graphs only!] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManFlowBwdPath2_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pFanout; + assert( Aig_ObjIsNode(pObj) || Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) ); + // skip visited nodes + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return 0; + Aig_ObjSetTravIdCurrent(p, pObj); + // process node without flow + if ( !Llb_ObjGetPath(pObj) ) + { + // start the path if we reached a terminal node + if ( pObj->fMarkA ) + return Llb_ObjSetPath( pObj, (Aig_Obj_t *)1 ); + // explore the fanins +// Abc_ObjForEachFanin( pObj, pFanin, i ) +// if ( Abc_NtkMaxFlowBwdPath2_rec(pFanin) ) +// return Abc_ObjSetPath( pObj, pFanin ); + if ( Aig_ObjIsNode(pObj) ) + { + if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ) ) + return Llb_ObjSetPath( pObj, Aig_ObjFanin0(pObj) ); + if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ) ) + return Llb_ObjSetPath( pObj, Aig_ObjFanin1(pObj) ); + } + return 0; + } + // pObj has flow - find the fanout with flow + pFanout = Llb_ObjGetFanoutPath( p, pObj ); + if ( pFanout == NULL ) + return 0; + // go through the fanins of the fanout with flow +// Abc_ObjForEachFanin( pFanout, pFanin, i ) +// if ( Abc_NtkMaxFlowBwdPath2_rec( pFanin ) ) +// return Abc_ObjSetPath( pFanout, pFanin ); + assert( Aig_ObjIsNode(pFanout) ); + if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pFanout) ) ) + return Llb_ObjSetPath( pFanout, Aig_ObjFanin0(pFanout) ); + if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pFanout) ) ) + return Llb_ObjSetPath( pFanout, Aig_ObjFanin1(pFanout) ); + // try the fanout + if ( Llb_ManFlowBwdPath2_rec( p, pFanout ) ) + return Llb_ObjSetPath( pFanout, NULL ); + return 0; +} + + +/**Function************************************************************* + + Synopsis [Cleans markB.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowLabelTfi_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) ) + return; + assert( Aig_ObjIsNode(pObj) ); + Llb_ManFlowLabelTfi_rec( p, Aig_ObjFanin0(pObj) ); + Llb_ManFlowLabelTfi_rec( p, Aig_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowUpdateCut( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) +{ + Aig_Obj_t * pObj; + int i; + // label the TFI of the cut nodes + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) + Llb_ManFlowLabelTfi_rec( p, pObj ); + // collect labeled fanins of non-labeled nodes + Vec_PtrClear( vMinCut ); + Aig_ManIncrementTravId(p); + Aig_ManForEachObj( p, pObj, i ) + { + if ( !Aig_ObjIsCo(pObj) && !Aig_ObjIsNode(pObj) ) + continue; + if ( Aig_ObjIsTravIdCurrent(p, pObj) || Aig_ObjIsTravIdPrevious(p, pObj) ) + continue; + if ( Aig_ObjIsTravIdPrevious(p, Aig_ObjFanin0(pObj)) ) + { + Aig_ObjSetTravIdCurrent(p, Aig_ObjFanin0(pObj)); + Vec_PtrPush( vMinCut, Aig_ObjFanin0(pObj) ); + } + if ( Aig_ObjIsNode(pObj) && Aig_ObjIsTravIdPrevious(p, Aig_ObjFanin1(pObj)) ) + { + Aig_ObjSetTravIdCurrent(p, Aig_ObjFanin1(pObj)); + Vec_PtrPush( vMinCut, Aig_ObjFanin1(pObj) ); + } + } +} + +/**Function************************************************************* + + Synopsis [Find minimum-volume minumum cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManFlowMinCut( Aig_Man_t * p ) +{ + Vec_Ptr_t * vMinCut; + Aig_Obj_t * pObj; + int i; + // collect the cut nodes + vMinCut = Vec_PtrAlloc( Aig_ManRegNum(p) ); + Aig_ManForEachObj( p, pObj, i ) + { + // node without flow is not a cut node + if ( !Llb_ObjGetPath(pObj) ) + continue; + // unvisited node is below the cut + if ( !Aig_ObjIsTravIdCurrent(p, pObj) ) + continue; + // add terminal with flow or node whose path is not visited + if ( pObj->fMarkA || !Aig_ObjIsTravIdCurrent( p, Llb_ObjGetPath(pObj) ) ) + Vec_PtrPush( vMinCut, pObj ); + } + return vMinCut; +} + +/**Function************************************************************* + + Synopsis [Verifies the min-cut is indeed a cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManFlowVerifyCut_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + // skip visited nodes + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return 1; + Aig_ObjSetTravIdCurrent(p, pObj); + // visit the node + if ( Aig_ObjIsConst1(pObj) ) + return 1; + if ( Aig_ObjIsCi(pObj) ) + return 0; + // explore the fanins + assert( Aig_ObjIsNode(pObj) ); + if ( !Llb_ManFlowVerifyCut_rec(p, Aig_ObjFanin0(pObj)) ) + return 0; + if ( !Llb_ManFlowVerifyCut_rec(p, Aig_ObjFanin1(pObj)) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Verifies the min-cut is indeed a cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManFlowVerifyCut( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) +{ + Aig_Obj_t * pObj; + int i; + // mark the cut with the current traversal ID + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // search from the latches for a path to the COs/CIs + Saig_ManForEachLi( p, pObj, i ) + { + if ( !Llb_ManFlowVerifyCut_rec( p, Aig_ObjFanin0(pObj) ) ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Implementation of max-flow/min-cut computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManFlow( Aig_Man_t * p, Vec_Ptr_t * vSources, int * pnFlow ) +{ + Vec_Ptr_t * vMinCut; + Aig_Obj_t * pObj; + int Flow, FlowCur, RetValue, i; + // find the max-flow + Flow = 0; + Aig_ManCleanData( p ); + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vSources, pObj, i ) + { + assert( !pObj->fMarkA && pObj->fMarkB ); + if ( !Aig_ObjFanin0(pObj)->fMarkB ) + { + FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ); + Flow += FlowCur; + if ( FlowCur ) + Aig_ManIncrementTravId(p); + } + if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB ) + { + FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ); + Flow += FlowCur; + if ( FlowCur ) + Aig_ManIncrementTravId(p); + } + } + if ( pnFlow ) + *pnFlow = Flow; + + // mark the nodes reachable from the latches + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vSources, pObj, i ) + { + assert( !pObj->fMarkA && pObj->fMarkB ); + if ( !Aig_ObjFanin0(pObj)->fMarkB ) + { + RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ); + assert( RetValue == 0 ); + } + if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB ) + { + RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ); + assert( RetValue == 0 ); + } + } + + // find the min-cut with the smallest volume + vMinCut = Llb_ManFlowMinCut( p ); + assert( Vec_PtrSize(vMinCut) == Flow ); + // verify the cut + if ( !Llb_ManFlowVerifyCut(p, vMinCut) ) + printf( "Llb_ManFlow() error! The computed min-cut is not a cut!\n" ); +// Llb_ManFlowPrintCut( p, vMinCut ); + return vMinCut; +} + +/**Function************************************************************* + + Synopsis [Implementation of max-flow/min-cut computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManFlowCompute( Aig_Man_t * p ) +{ + Vec_Ptr_t * vMinCut; + Aig_Obj_t * pObj; + int Flow, FlowCur, RetValue, i; + // find the max-flow + Flow = 0; + Aig_ManCleanData( p ); + Aig_ManIncrementTravId(p); + Aig_ManForEachObj( p, pObj, i ) + { + if ( !pObj->fMarkB ) + continue; + assert( !pObj->fMarkA ); + if ( !Aig_ObjFanin0(pObj)->fMarkB ) + { +//printf( "%d ", Aig_ObjFanin0(pObj)->Id ); + FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ); + Flow += FlowCur; + if ( FlowCur ) + Aig_ManIncrementTravId(p); + } + if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB ) + { +//printf( "%d ", Aig_ObjFanin1(pObj)->Id ); + FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ); + Flow += FlowCur; + if ( FlowCur ) + Aig_ManIncrementTravId(p); + } + } +//printf( "\n" ); + + // mark the nodes reachable from the latches + Aig_ManIncrementTravId(p); + Aig_ManForEachObj( p, pObj, i ) + { + if ( !pObj->fMarkB ) + continue; + assert( !pObj->fMarkA ); + if ( !Aig_ObjFanin0(pObj)->fMarkB ) + { + RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ); + assert( RetValue == 0 ); + } + if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB ) + { + RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ); + assert( RetValue == 0 ); + } + } + // find the min-cut with the smallest volume + vMinCut = Llb_ManFlowMinCut( p ); + assert( Vec_PtrSize(vMinCut) == Flow ); +//printf( "%d ", Vec_PtrSize(vMinCut) ); + Llb_ManFlowUpdateCut( p, vMinCut ); +//printf( "%d ", Vec_PtrSize(vMinCut) ); + // verify the cut + if ( !Llb_ManFlowVerifyCut(p, vMinCut) ) + printf( "Llb_ManFlow() error! The computed min-cut is not a cut!\n" ); +// Llb_ManFlowPrintCut( p, vMinCut ); + return vMinCut; +} + + + + +/**Function************************************************************* + + Synopsis [Cleans markB.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowCleanMarkB_rec( Aig_Obj_t * pObj ) +{ + if ( pObj->fMarkB == 0 ) + return; + pObj->fMarkB = 0; + assert( Aig_ObjIsNode(pObj) ); + Llb_ManFlowCleanMarkB_rec( Aig_ObjFanin0(pObj) ); + Llb_ManFlowCleanMarkB_rec( Aig_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Cleans markB.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowSetMarkA_rec( Aig_Obj_t * pObj ) +{ + if ( pObj->fMarkA ) + return; + pObj->fMarkA = 1; + if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) ) + return; + assert( Aig_ObjIsNode(pObj) ); + Llb_ManFlowSetMarkA_rec( Aig_ObjFanin0(pObj) ); + Llb_ManFlowSetMarkA_rec( Aig_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Prepares flow computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowPrepareCut( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) +{ + Aig_Obj_t * pObj; + int i; + // reset marks + Aig_ManForEachObj( p, pObj, i ) + { + pObj->fMarkA = 0; + pObj->fMarkB = 1; + } + // clean PIs and const + Aig_ManConst1(p)->fMarkB = 0; + Aig_ManForEachCi( p, pObj, i ) + pObj->fMarkB = 0; + // clean upper cut +//printf( "Upper: "); + Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) + { + Llb_ManFlowCleanMarkB_rec( pObj ); +//printf( "%d ", pObj->Id ); + } +//printf( "\n" ); + // set lower cut +//printf( "Lower: "); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + { +//printf( "%d ", pObj->Id ); + assert( pObj->fMarkB == 0 ); + Llb_ManFlowSetMarkA_rec( pObj ); + } +//printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Prepares flow computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowUnmarkCone( Aig_Man_t * p, Vec_Ptr_t * vCone ) +{ + Aig_Obj_t * pObj; + int i; + Vec_PtrForEachEntry( Aig_Obj_t *, vCone, pObj, i ) + { + assert( Aig_ObjIsNode(pObj) ); + assert( pObj->fMarkB == 1 ); + pObj->fMarkB = 0; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowCollectAndMarkCone_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vCone ) +{ + Aig_Obj_t * pFanout; + int i, iFanout = -1; + if ( Saig_ObjIsLi(p, pObj) ) + return; + if ( pObj->fMarkB ) + return; + if ( pObj->fMarkA == 0 ) + { + assert( Aig_ObjIsNode(pObj) ); + pObj->fMarkB = 1; + if ( Aig_ObjIsNode(pObj) ) + Vec_PtrPush( vCone, pObj ); + } + Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) + Llb_ManFlowCollectAndMarkCone_rec( p, pFanout, vCone ); +} + +/**Function************************************************************* + + Synopsis [Collects the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowCollectAndMarkCone( Aig_Man_t * p, Vec_Ptr_t * vStarts, Vec_Ptr_t * vCone ) +{ + Aig_Obj_t * pObj; + int i; + Vec_PtrClear( vCone ); + Vec_PtrForEachEntry( Aig_Obj_t *, vStarts, pObj, i ) + { + assert( pObj->fMarkA && !pObj->fMarkB ); + Llb_ManFlowCollectAndMarkCone_rec( p, pObj, vCone ); + } +} + + + + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManComputeCutLo( Aig_Man_t * p ) +{ + Vec_Ptr_t * vMinCut; + Aig_Obj_t * pObj; + int i; + vMinCut = Vec_PtrAlloc( 100 ); + Aig_ManForEachCi( p, pObj, i ) + Vec_PtrPush( vMinCut, pObj ); + return vMinCut; +} + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManComputeCutLi( Aig_Man_t * p ) +{ + Vec_Ptr_t * vMinCut; + Aig_Obj_t * pObj; + int i; + assert( Saig_ManPoNum(p) == 0 ); + vMinCut = Vec_PtrAlloc( 100 ); + Aig_ManIncrementTravId(p); + Saig_ManForEachLi( p, pObj, i ) + { + pObj = Aig_ObjFanin0(pObj); + if ( Aig_ObjIsConst1(pObj) ) + continue; + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + continue; + Aig_ObjSetTravIdCurrent(p, pObj); + Vec_PtrPush( vMinCut, pObj ); + } + return vMinCut; +} + + + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowGetObjSet( Aig_Man_t * p, Vec_Ptr_t * vLower, int iStart, int nSize, Vec_Ptr_t * vSet ) +{ + Aig_Obj_t * pObj; + int i; + Vec_PtrClear( vSet ); + for ( i = 0; i < nSize; i++ ) + { + pObj = (Aig_Obj_t *)Vec_PtrEntry( vLower, (iStart + i) % Vec_PtrSize(vLower) ); + Vec_PtrPush( vSet, pObj ); + } +} + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManFlowFindBestCut( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, int Num ) +{ + int nVolMin = Aig_ManNodeNum(p) / Num / 2; + Vec_Ptr_t * vMinCut; + Vec_Ptr_t * vCone, * vSet; + Aig_Obj_t * pObj; + int i, s, Vol, VolLower, VolUpper, VolCmp; + int iBest = -1, iMinCut = ABC_INFINITY, iVolBest = 0; + + Vol = Llb_ManCutVolume( p, vLower, vUpper ); + assert( Vol > nVolMin ); + VolCmp = Abc_MinInt( nVolMin, Vol - nVolMin ); + vCone = Vec_PtrAlloc( 100 ); + vSet = Vec_PtrAlloc( 100 ); + Llb_ManFlowPrepareCut( p, vLower, vUpper ); + for ( s = 1; s < Aig_ManRegNum(p); s += 5 ) + { + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + { + Llb_ManFlowGetObjSet( p, vLower, i, s, vSet ); + Llb_ManFlowCollectAndMarkCone( p, vSet, vCone ); + if ( Vec_PtrSize(vCone) == 0 ) + continue; + vMinCut = Llb_ManFlowCompute( p ); + Llb_ManFlowUnmarkCone( p, vCone ); + + VolLower = Llb_ManCutVolume( p, vLower, vMinCut ); + VolUpper = Llb_ManCutVolume( p, vMinCut, vUpper ); + Vol = Abc_MinInt( VolLower, VolUpper ); + if ( Vol >= VolCmp && (iMinCut == -1 || + iMinCut > Vec_PtrSize(vMinCut) || + (iMinCut == Vec_PtrSize(vMinCut) && iVolBest < Vol)) ) + { + iBest = i; + iMinCut = Vec_PtrSize(vMinCut); + iVolBest = Vol; + } + Vec_PtrFree( vMinCut ); + } + if ( iBest >= 0 ) + break; + } + if ( iBest == -1 ) + { + // cleanup + Vec_PtrFree( vCone ); + Vec_PtrFree( vSet ); + return NULL; + } + // get the best cut + assert( iBest >= 0 ); + Llb_ManFlowGetObjSet( p, vLower, iBest, s, vSet ); + Llb_ManFlowCollectAndMarkCone( p, vSet, vCone ); + vMinCut = Llb_ManFlowCompute( p ); + Llb_ManFlowUnmarkCone( p, vCone ); + // cleanup + Vec_PtrFree( vCone ); + Vec_PtrFree( vSet ); + return vMinCut; +} + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManComputeCuts( Aig_Man_t * p, int Num, int fVerbose, int fVeryVerbose ) +{ + int nVolMax = Aig_ManNodeNum(p) / Num; + Vec_Ptr_t * vResult, * vMinCut = NULL, * vLower, * vUpper; + int i, k, nVol; + abctime clk = Abc_Clock(); + vResult = Vec_PtrAlloc( 100 ); + Vec_PtrPush( vResult, Llb_ManComputeCutLo(p) ); + Vec_PtrPush( vResult, Llb_ManComputeCutLi(p) ); + while ( 1 ) + { + // find a place to insert new cut + vLower = (Vec_Ptr_t *)Vec_PtrEntry( vResult, 0 ); + Vec_PtrForEachEntryStart( Vec_Ptr_t *, vResult, vUpper, i, 1 ) + { + nVol = Llb_ManCutVolume( p, vLower, vUpper ); + if ( nVol <= nVolMax ) + { + vLower = vUpper; + continue; + } + + if ( fVeryVerbose ) + Llb_ManCutPrint( p, vLower, vUpper ); + vMinCut = Llb_ManFlowFindBestCut( p, vLower, vUpper, Num ); + if ( vMinCut == NULL ) + { + if ( fVeryVerbose ) + printf( "Could not break the cut.\n" ); + if ( fVeryVerbose ) + printf( "\n" ); + vLower = vUpper; + continue; + } + + if ( fVeryVerbose ) + Llb_ManCutPrint( p, vMinCut, vUpper ); + if ( fVeryVerbose ) + Llb_ManCutPrint( p, vLower, vMinCut ); + if ( fVeryVerbose ) + printf( "\n" ); + + break; + } + if ( i == Vec_PtrSize(vResult) ) + break; + // insert vMinCut before vUpper + Vec_PtrPush( vResult, NULL ); + for ( k = Vec_PtrSize(vResult) - 1; k > i; k-- ) + Vec_PtrWriteEntry( vResult, k, Vec_PtrEntry(vResult, k-1) ); + Vec_PtrWriteEntry( vResult, i, vMinCut ); + } + if ( fVerbose ) + { + printf( "Finished computing %d partitions. ", Vec_PtrSize(vResult) - 1 ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + Llb_ManResultPrint( p, vResult ); + } + return vResult; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_BddSetDefaultParams( Gia_ParLlb_t * p ) +{ + memset( p, 0, sizeof(Gia_ParLlb_t) ); + p->nBddMax = 1000000; + p->nIterMax = 10000000; + p->nClusterMax = 20; + p->nHintDepth = 0; + p->HintFirst = 0; + p->fUseFlow = 0; // use flow + p->nVolumeMax = 100; // max volume + p->nVolumeMin = 30; // min volume + p->fReorder = 1; + p->fIndConstr = 0; + p->fUsePivots = 0; + p->fCluster = 0; + p->fSchedule = 0; + p->fVerbose = 0; + p->fVeryVerbose = 0; + p->fSilent = 0; + p->TimeLimit = 0; +// p->TimeLimit = 0; + p->TimeLimitGlo = 0; + p->TimeTarget = 0; + p->iFrame = -1; +} + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManMinCutTest( Aig_Man_t * pAig, int Num ) +{ + extern void Llb_BddConstructTest( Aig_Man_t * p, Vec_Ptr_t * vResult ); + extern void Llb_BddExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, Vec_Ptr_t * vMaps ); + + +// int fVerbose = 1; + Gia_ParLlb_t Pars, * pPars = &Pars; + Vec_Ptr_t * vResult;//, * vSupps, * vMaps; + Aig_Man_t * p; + + Llb_BddSetDefaultParams( pPars ); + + p = Aig_ManDupFlopsOnly( pAig ); +//Aig_ManShow( p, 0, NULL ); + Aig_ManPrintStats( pAig ); + Aig_ManPrintStats( p ); + Aig_ManFanoutStart( p ); + + vResult = Llb_ManComputeCuts( p, Num, 1, 0 ); +// vSupps = Llb_ManCutSupps( p, vResult ); +// vMaps = Llb_ManCutMap( p, vResult, vSupps ); + +// Llb_BddExperiment( pAig, p, pPars, vResult, vMaps ); + Llb_CoreExperiment( pAig, p, pPars, vResult, 0 ); + +// Vec_VecFree( (Vec_Vec_t *)vMaps ); +// Vec_VecFree( (Vec_Vec_t *)vSupps ); + Vec_VecFree( (Vec_Vec_t *)vResult ); + + Aig_ManFanoutStop( p ); + Aig_ManCleanMarkAB( p ); + Aig_ManStop( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb2Image.c b/src/bdd/llb/llb2Image.c new file mode 100644 index 00000000..e245ba36 --- /dev/null +++ b/src/bdd/llb/llb2Image.c @@ -0,0 +1,482 @@ +/**CFile**************************************************************** + + FileName [llb2Image.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Computes image using partitioned structure.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern Vec_Ptr_t * Llb_ManCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ); +extern Vec_Ptr_t * Llb_ManCutRange( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes supports of the partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ImgSupports( Aig_Man_t * p, Vec_Ptr_t * vDdMans, Vec_Int_t * vStart, Vec_Int_t * vStop, int fAddPis, int fVerbose ) +{ + Vec_Ptr_t * vSupps; + Vec_Int_t * vOne; + Aig_Obj_t * pObj; + DdManager * dd; + DdNode * bSupp, * bTemp; + int i, Entry, nSize; + nSize = Cudd_ReadSize( (DdManager *)Vec_PtrEntry( vDdMans, 0 ) ); + vSupps = Vec_PtrAlloc( 100 ); + // create initial + vOne = Vec_IntStart( nSize ); + Vec_IntForEachEntry( vStart, Entry, i ) + Vec_IntWriteEntry( vOne, Entry, 1 ); + Vec_PtrPush( vSupps, vOne ); + // create intermediate + Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i ) + { + vOne = Vec_IntStart( nSize ); + bSupp = Cudd_Support( dd, dd->bFunc ); Cudd_Ref( bSupp ); + for ( bTemp = bSupp; bTemp != Cudd_ReadOne(dd); bTemp = cuddT(bTemp) ) + Vec_IntWriteEntry( vOne, bTemp->index, 1 ); + Cudd_RecursiveDeref( dd, bSupp ); + Vec_PtrPush( vSupps, vOne ); + } + // create final + vOne = Vec_IntStart( nSize ); + Vec_IntForEachEntry( vStop, Entry, i ) + Vec_IntWriteEntry( vOne, Entry, 1 ); + if ( fAddPis ) + Saig_ManForEachPi( p, pObj, i ) + Vec_IntWriteEntry( vOne, Aig_ObjId(pObj), 1 ); + Vec_PtrPush( vSupps, vOne ); + + // print supports + assert( nSize == Aig_ManObjNumMax(p) ); + if ( !fVerbose ) + return vSupps; + Aig_ManForEachObj( p, pObj, i ) + { + int k, Counter = 0; + Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k ) + Counter += Vec_IntEntry(vOne, i); + if ( Counter == 0 ) + continue; + printf( "Obj = %4d : ", i ); + if ( Saig_ObjIsPi(p,pObj) ) + printf( "pi " ); + else if ( Saig_ObjIsLo(p,pObj) ) + printf( "lo " ); + else if ( Saig_ObjIsLi(p,pObj) ) + printf( "li " ); + else if ( Aig_ObjIsNode(pObj) ) + printf( "and " ); + Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k ) + printf( "%d", Vec_IntEntry(vOne, i) ); + printf( "\n" ); + } + return vSupps; +} + +/**Function************************************************************* + + Synopsis [Computes quantification schedule.] + + Description [Input array contains supports: 0=starting, ... intermediate... + N-1=final. Output arrays contain immediately quantifiable vars (vQuant0) + and vars that should be quantified after conjunction (vQuant1).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ImgSchedule( Vec_Ptr_t * vSupps, Vec_Ptr_t ** pvQuant0, Vec_Ptr_t ** pvQuant1, int fVerbose ) +{ + Vec_Int_t * vOne; + int nVarsAll, Counter, iSupp = -1, Entry, i, k; + // start quantification arrays + *pvQuant0 = Vec_PtrAlloc( Vec_PtrSize(vSupps) ); + *pvQuant1 = Vec_PtrAlloc( Vec_PtrSize(vSupps) ); + Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k ) + { + Vec_PtrPush( *pvQuant0, Vec_IntAlloc(16) ); + Vec_PtrPush( *pvQuant1, Vec_IntAlloc(16) ); + } + // count how many times each var appears + nVarsAll = Vec_IntSize( (Vec_Int_t *)Vec_PtrEntry(vSupps, 0) ); + for ( i = 0; i < nVarsAll; i++ ) + { + Counter = 0; + Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k ) + if ( Vec_IntEntry(vOne, i) ) + { + iSupp = k; + Counter++; + } + if ( Counter == 0 ) + continue; + if ( Counter == 1 ) + Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(*pvQuant0, iSupp), i ); + else // if ( Counter > 1 ) + Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(*pvQuant1, iSupp), i ); + } + + if ( fVerbose ) + for ( i = 0; i < Vec_PtrSize(vSupps); i++ ) + { + printf( "%2d : Quant0 = ", i ); + Vec_IntForEachEntry( (Vec_Int_t *)Vec_PtrEntry(*pvQuant0, i), Entry, k ) + printf( "%d ", Entry ); + printf( "\n" ); + } + + if ( fVerbose ) + for ( i = 0; i < Vec_PtrSize(vSupps); i++ ) + { + printf( "%2d : Quant1 = ", i ); + Vec_IntForEachEntry( (Vec_Int_t *)Vec_PtrEntry(*pvQuant1, i), Entry, k ) + printf( "%d ", Entry ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Computes one partition in a separate BDD manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdManager * Llb_ImgPartition( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, abctime TimeTarget ) +{ + Vec_Ptr_t * vNodes, * vRange; + Aig_Obj_t * pObj; + DdManager * dd; + DdNode * bBdd0, * bBdd1, * bProd, * bRes, * bTemp; + int i; + + dd = Cudd_Init( Aig_ManObjNumMax(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + dd->TimeStop = TimeTarget; + + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + pObj->pData = Cudd_bddIthVar( dd, Aig_ObjId(pObj) ); + + vNodes = Llb_ManCutNodes( p, vLower, vUpper ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); +// pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData ); +// pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeTarget ); + pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); + if ( pObj->pData == NULL ) + { + Cudd_Quit( dd ); + Vec_PtrFree( vNodes ); + return NULL; + } + Cudd_Ref( (DdNode *)pObj->pData ); + } + + vRange = Llb_ManCutRange( p, vLower, vUpper ); + bRes = Cudd_ReadOne(dd); Cudd_Ref( bRes ); + Vec_PtrForEachEntry( Aig_Obj_t *, vRange, pObj, i ) + { + assert( Aig_ObjIsNode(pObj) ); + bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), (DdNode *)pObj->pData ); Cudd_Ref( bProd ); +// bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); Cudd_Ref( bRes ); +// bRes = Extra_bddAndTime( dd, bTemp = bRes, bProd, TimeTarget ); + bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); + if ( bRes == NULL ) + { + Cudd_Quit( dd ); + Vec_PtrFree( vRange ); + Vec_PtrFree( vNodes ); + return NULL; + } + Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bProd ); + } + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + + Vec_PtrFree( vRange ); + Vec_PtrFree( vNodes ); + Cudd_AutodynDisable( dd ); +// Cudd_RecursiveDeref( dd, bRes ); +// Extra_StopManager( dd ); + dd->bFunc = bRes; + dd->TimeStop = 0; + return dd; +} + +/**Function************************************************************* + + Synopsis [Derives positive cube composed of nodes IDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ImgComputeCube( Aig_Man_t * pAig, Vec_Int_t * vNodeIds, DdManager * dd ) +{ + DdNode * bProd, * bTemp; + Aig_Obj_t * pObj; + int i; + abctime TimeStop; + TimeStop = dd->TimeStop; dd->TimeStop = 0; + bProd = Cudd_ReadOne(dd); Cudd_Ref( bProd ); + Aig_ManForEachObjVec( vNodeIds, pAig, pObj, i ) + { + bProd = Cudd_bddAnd( dd, bTemp = bProd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)) ); Cudd_Ref( bProd ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bProd ); + dd->TimeStop = TimeStop; + return bProd; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ImgQuantifyFirst( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, Vec_Ptr_t * vQuant0, int fVerbose ) +{ + DdManager * dd; + DdNode * bProd, * bRes, * bTemp; + int i; + abctime clk = Abc_Clock(); + Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i ) + { + // remember unquantified ones + assert( dd->bFunc2 == NULL ); + dd->bFunc2 = dd->bFunc; Cudd_Ref( dd->bFunc2 ); + + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + + bRes = dd->bFunc; + if ( fVerbose ) + Abc_Print( 1, "Part %2d : Init =%5d. ", i, Cudd_DagSize(bRes) ); + bProd = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, i+1), dd ); Cudd_Ref( bProd ); + bRes = Cudd_bddExistAbstract( dd, bTemp = bRes, bProd ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bProd ); + dd->bFunc = bRes; + + Cudd_AutodynDisable( dd ); + + if ( fVerbose ) + Abc_Print( 1, "Quant =%5d. ", Cudd_DagSize(bRes) ); + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + if ( fVerbose ) + Abc_Print( 1, "Reo = %5d. ", Cudd_DagSize(bRes) ); + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + if ( fVerbose ) + Abc_Print( 1, "Reo = %5d. ", Cudd_DagSize(bRes) ); + if ( fVerbose ) + Abc_Print( 1, "Supp = %3d. ", Cudd_SupportSize(dd, bRes) ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ImgQuantifyReset( Vec_Ptr_t * vDdMans ) +{ + DdManager * dd; + int i; + Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i ) + { + assert( dd->bFunc2 != NULL ); + Cudd_RecursiveDeref( dd, dd->bFunc ); + dd->bFunc = dd->bFunc2; + dd->bFunc2 = NULL; + } +} + +/**Function************************************************************* + + Synopsis [Computes image of the initial set of states.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ImgComputeImage( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, DdManager * dd, DdNode * bInit, + Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1, Vec_Int_t * vDriRefs, + abctime TimeTarget, int fBackward, int fReorder, int fVerbose ) +{ +// int fCheckSupport = 0; + DdManager * ddPart; + DdNode * bImage, * bGroup, * bCube, * bTemp; + int i; + abctime clk, clk0 = Abc_Clock(); + + bImage = bInit; Cudd_Ref( bImage ); + if ( fBackward ) + { + // change polarity + bCube = Llb_DriverPhaseCube( pAig, vDriRefs, dd ); Cudd_Ref( bCube ); + bImage = Extra_bddChangePolarity( dd, bTemp = bImage, bCube ); Cudd_Ref( bImage ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + } + else + { + // quantify unique vriables + bCube = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, 0), dd ); Cudd_Ref( bCube ); + bImage = Cudd_bddExistAbstract( dd, bTemp = bImage, bCube ); + if ( bImage == NULL ) + { + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + return NULL; + } + Cudd_Ref( bImage ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + } + // perform image computation + Vec_PtrForEachEntry( DdManager *, vDdMans, ddPart, i ) + { + clk = Abc_Clock(); +if ( fVerbose ) +printf( " %2d : ", i ); + // transfer the BDD from the group manager to the main manager + bGroup = Cudd_bddTransfer( ddPart, dd, ddPart->bFunc ); + if ( bGroup == NULL ) + return NULL; + Cudd_Ref( bGroup ); +if ( fVerbose ) +printf( "Pt0 =%6d. Pt1 =%6d. ", Cudd_DagSize(ddPart->bFunc), Cudd_DagSize(bGroup) ); + // perform partial product + bCube = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant1, i+1), dd ); Cudd_Ref( bCube ); +// bImage = Cudd_bddAndAbstract( dd, bTemp = bImage, bGroup, bCube ); +// bImage = Extra_bddAndAbstractTime( dd, bTemp = bImage, bGroup, bCube, TimeTarget ); + bImage = Cudd_bddAndAbstract( dd, bTemp = bImage, bGroup, bCube ); + if ( bImage == NULL ) + { + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + Cudd_RecursiveDeref( dd, bGroup ); + return NULL; + } + Cudd_Ref( bImage ); + +if ( fVerbose ) +printf( "Im0 =%6d. Im1 =%6d. ", Cudd_DagSize(bTemp), Cudd_DagSize(bImage) ); +//printf("\n"); Extra_bddPrintSupport(dd, bImage); printf("\n"); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + Cudd_RecursiveDeref( dd, bGroup ); + +// Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); +// Abc_Print( 1, "Reo =%6d. ", Cudd_DagSize(bImage) ); + +if ( fVerbose ) +printf( "Supp =%3d. ", Cudd_SupportSize(dd, bImage) ); +if ( fVerbose ) +Abc_PrintTime( 1, "T", Abc_Clock() - clk ); + } + + if ( !fBackward ) + { + // change polarity + bCube = Llb_DriverPhaseCube( pAig, vDriRefs, dd ); Cudd_Ref( bCube ); + bImage = Extra_bddChangePolarity( dd, bTemp = bImage, bCube ); Cudd_Ref( bImage ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + } + else + { + // quantify unique vriables + bCube = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, 0), dd ); Cudd_Ref( bCube ); + bImage = Cudd_bddExistAbstract( dd, bTemp = bImage, bCube ); Cudd_Ref( bImage ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + } + + if ( fReorder ) + { + if ( fVerbose ) + Abc_Print( 1, " Reordering... Before =%5d. ", Cudd_DagSize(bImage) ); + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + if ( fVerbose ) + Abc_Print( 1, "After =%5d. ", Cudd_DagSize(bImage) ); +// Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); +// Abc_Print( 1, "After =%5d. ", Cudd_DagSize(bImage) ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk0 ); +// Abc_Print( 1, "\n" ); + } + + Cudd_Deref( bImage ); + return bImage; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb3Image.c b/src/bdd/llb/llb3Image.c new file mode 100644 index 00000000..72c6120a --- /dev/null +++ b/src/bdd/llb/llb3Image.c @@ -0,0 +1,1095 @@ +/**CFile**************************************************************** + + FileName [llb3Image.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Computes image using partitioned structure.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb3Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Llb_Var_t_ Llb_Var_t; +struct Llb_Var_t_ +{ + int iVar; // variable number + int nScore; // variable score + Vec_Int_t * vParts; // partitions +}; + +typedef struct Llb_Prt_t_ Llb_Prt_t; +struct Llb_Prt_t_ +{ + int iPart; // partition number + int nSize; // the number of BDD nodes + DdNode * bFunc; // the partition + Vec_Int_t * vVars; // support +}; + +typedef struct Llb_Mgr_t_ Llb_Mgr_t; +struct Llb_Mgr_t_ +{ + Aig_Man_t * pAig; // AIG manager + Vec_Ptr_t * vLeaves; // leaves in the AIG manager + Vec_Ptr_t * vRoots; // roots in the AIG manager + DdManager * dd; // working BDD manager + int * pVars2Q; // variables to quantify + // internal + Llb_Prt_t ** pParts; // partitions + Llb_Var_t ** pVars; // variables + int iPartFree; // next free partition + int nVars; // the number of BDD variables + int nSuppMax; // maximum support size + // temporary + int * pSupp; // temporary support storage +}; + +static inline Llb_Var_t * Llb_MgrVar( Llb_Mgr_t * p, int i ) { return p->pVars[i]; } +static inline Llb_Prt_t * Llb_MgrPart( Llb_Mgr_t * p, int i ) { return p->pParts[i]; } + +// iterator over vars +#define Llb_MgrForEachVar( p, pVar, i ) \ + for ( i = 0; (i < p->nVars) && (((pVar) = Llb_MgrVar(p, i)), 1); i++ ) if ( pVar == NULL ) {} else +// iterator over parts +#define Llb_MgrForEachPart( p, pPart, i ) \ + for ( i = 0; (i < p->iPartFree) && (((pPart) = Llb_MgrPart(p, i)), 1); i++ ) if ( pPart == NULL ) {} else + +// iterator over vars of one partition +#define Llb_PartForEachVar( p, pPart, pVar, i ) \ + for ( i = 0; (i < Vec_IntSize(pPart->vVars)) && (((pVar) = Llb_MgrVar(p, Vec_IntEntry(pPart->vVars,i))), 1); i++ ) +// iterator over parts of one variable +#define Llb_VarForEachPart( p, pVar, pPart, i ) \ + for ( i = 0; (i < Vec_IntSize(pVar->vParts)) && (((pPart) = Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,i))), 1); i++ ) + +// statistics +abctime timeBuild, timeAndEx, timeOther; +int nSuppMax; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Removes one variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinRemoveVar( Llb_Mgr_t * p, Llb_Var_t * pVar ) +{ + assert( p->pVars[pVar->iVar] == pVar ); + p->pVars[pVar->iVar] = NULL; + Vec_IntFree( pVar->vParts ); + ABC_FREE( pVar ); +} + +/**Function************************************************************* + + Synopsis [Removes one partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinRemovePart( Llb_Mgr_t * p, Llb_Prt_t * pPart ) +{ + assert( p->pParts[pPart->iPart] == pPart ); + p->pParts[pPart->iPart] = NULL; + Vec_IntFree( pPart->vVars ); + Cudd_RecursiveDeref( p->dd, pPart->bFunc ); + ABC_FREE( pPart ); +} + +/**Function************************************************************* + + Synopsis [Create cube with singleton variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_NonlinCreateCube1( Llb_Mgr_t * p, Llb_Prt_t * pPart ) +{ + DdNode * bCube, * bTemp; + Llb_Var_t * pVar; + int i; + abctime TimeStop; + TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; + bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube ); + Llb_PartForEachVar( p, pPart, pVar, i ) + { + assert( Vec_IntSize(pVar->vParts) > 0 ); + if ( Vec_IntSize(pVar->vParts) != 1 ) + continue; + assert( Vec_IntEntry(pVar->vParts, 0) == pPart->iPart ); + bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Cudd_Deref( bCube ); + p->dd->TimeStop = TimeStop; + return bCube; +} + +/**Function************************************************************* + + Synopsis [Create cube of variables appearing only in two partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_NonlinCreateCube2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 ) +{ + DdNode * bCube, * bTemp; + Llb_Var_t * pVar; + int i; + abctime TimeStop; + TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; + bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube ); + Llb_PartForEachVar( p, pPart1, pVar, i ) + { + assert( Vec_IntSize(pVar->vParts) > 0 ); + if ( Vec_IntSize(pVar->vParts) != 2 ) + continue; + if ( (Vec_IntEntry(pVar->vParts, 0) == pPart1->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart2->iPart) || + (Vec_IntEntry(pVar->vParts, 0) == pPart2->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart1->iPart) ) + { + bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + } + Cudd_Deref( bCube ); + p->dd->TimeStop = TimeStop; + return bCube; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if partition has singleton variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinHasSingletonVars( Llb_Mgr_t * p, Llb_Prt_t * pPart ) +{ + Llb_Var_t * pVar; + int i; + Llb_PartForEachVar( p, pPart, pVar, i ) + if ( Vec_IntSize(pVar->vParts) == 1 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if partition has singleton variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinPrint( Llb_Mgr_t * p ) +{ + Llb_Prt_t * pPart; + Llb_Var_t * pVar; + int i, k; + printf( "\n" ); + Llb_MgrForEachVar( p, pVar, i ) + { + printf( "Var %3d : ", i ); + Llb_VarForEachPart( p, pVar, pPart, k ) + printf( "%d ", pPart->iPart ); + printf( "\n" ); + } + Llb_MgrForEachPart( p, pPart, i ) + { + printf( "Part %3d : ", i ); + Llb_PartForEachVar( p, pPart, pVar, k ) + printf( "%d ", pVar->iVar ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Quantifies singles belonging to one partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinQuantify1( Llb_Mgr_t * p, Llb_Prt_t * pPart, int fSubset ) +{ + Llb_Var_t * pVar; + Llb_Prt_t * pTemp; + Vec_Ptr_t * vSingles; + DdNode * bCube, * bTemp; + int i, RetValue, nSizeNew; + if ( fSubset ) + { + int Length; +// int nSuppSize = Cudd_SupportSize( p->dd, pPart->bFunc ); +// pPart->bFunc = Cudd_SubsetHeavyBranch( p->dd, bTemp = pPart->bFunc, nSuppSize, 3*pPart->nSize/4 ); Cudd_Ref( pPart->bFunc ); + pPart->bFunc = Cudd_LargestCube( p->dd, bTemp = pPart->bFunc, &Length ); Cudd_Ref( pPart->bFunc ); + + printf( "Subsetting %3d : ", pPart->iPart ); + printf( "(Supp =%3d Node =%5d) -> ", Cudd_SupportSize(p->dd, bTemp), Cudd_DagSize(bTemp) ); + printf( "(Supp =%3d Node =%5d)\n", Cudd_SupportSize(p->dd, pPart->bFunc), Cudd_DagSize(pPart->bFunc) ); + + RetValue = (Cudd_DagSize(bTemp) == Cudd_DagSize(pPart->bFunc)); + + Cudd_RecursiveDeref( p->dd, bTemp ); + + if ( RetValue ) + return 1; + } + else + { + // create cube to be quantified + bCube = Llb_NonlinCreateCube1( p, pPart ); Cudd_Ref( bCube ); +// assert( !Cudd_IsConstant(bCube) ); + // derive new function + pPart->bFunc = Cudd_bddExistAbstract( p->dd, bTemp = pPart->bFunc, bCube ); Cudd_Ref( pPart->bFunc ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bCube ); + } + // get support + vSingles = Vec_PtrAlloc( 0 ); + nSizeNew = Cudd_DagSize(pPart->bFunc); + Extra_SupportArray( p->dd, pPart->bFunc, p->pSupp ); + Llb_PartForEachVar( p, pPart, pVar, i ) + if ( p->pSupp[pVar->iVar] ) + { + assert( Vec_IntSize(pVar->vParts) > 1 ); + pVar->nScore -= pPart->nSize - nSizeNew; + } + else + { + RetValue = Vec_IntRemove( pVar->vParts, pPart->iPart ); + assert( RetValue ); + pVar->nScore -= pPart->nSize; + if ( Vec_IntSize(pVar->vParts) == 0 ) + Llb_NonlinRemoveVar( p, pVar ); + else if ( Vec_IntSize(pVar->vParts) == 1 ) + Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); + } + + // update partition + pPart->nSize = nSizeNew; + Vec_IntClear( pPart->vVars ); + for ( i = 0; i < p->nVars; i++ ) + if ( p->pSupp[i] && p->pVars2Q[i] ) + Vec_IntPush( pPart->vVars, i ); + // remove other variables + Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i ) + Llb_NonlinQuantify1( p, pTemp, 0 ); + Vec_PtrFree( vSingles ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Quantifies singles belonging to one partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinQuantify2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 ) +{ + int fVerbose = 0; + Llb_Var_t * pVar; + Llb_Prt_t * pTemp; + Vec_Ptr_t * vSingles; + DdNode * bCube, * bFunc; + int i, RetValue, nSuppSize; +// int iPart1 = pPart1->iPart; +// int iPart2 = pPart2->iPart; + + // create cube to be quantified + bCube = Llb_NonlinCreateCube2( p, pPart1, pPart2 ); Cudd_Ref( bCube ); +if ( fVerbose ) +{ +printf( "\n" ); +printf( "\n" ); +Llb_NonlinPrint( p ); +printf( "Conjoining partitions %d and %d.\n", pPart1->iPart, pPart2->iPart ); +Extra_bddPrintSupport( p->dd, bCube ); printf( "\n" ); +} + + // derive new function +// bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube ); Cudd_Ref( bFunc ); +/* + bFunc = Cudd_bddAndAbstractLimit( p->dd, pPart1->bFunc, pPart2->bFunc, bCube, Limit ); + if ( bFunc == NULL ) + { + int RetValue; + Cudd_RecursiveDeref( p->dd, bCube ); + if ( pPart1->nSize < pPart2->nSize ) + RetValue = Llb_NonlinQuantify1( p, pPart1, 1 ); + else + RetValue = Llb_NonlinQuantify1( p, pPart2, 1 ); + if ( RetValue ) + Limit = Limit + 1000; + Llb_NonlinQuantify2( p, pPart1, pPart2 ); + return 0; + } + Cudd_Ref( bFunc ); +*/ + +// bFunc = Extra_bddAndAbstractTime( p->dd, pPart1->bFunc, pPart2->bFunc, bCube, TimeOut ); + bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube ); + if ( bFunc == NULL ) + { + Cudd_RecursiveDeref( p->dd, bCube ); + return 0; + } + Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( p->dd, bCube ); + + // create new partition + pTemp = p->pParts[p->iPartFree] = ABC_CALLOC( Llb_Prt_t, 1 ); + pTemp->iPart = p->iPartFree++; + pTemp->nSize = Cudd_DagSize(bFunc); + pTemp->bFunc = bFunc; + pTemp->vVars = Vec_IntAlloc( 8 ); + // update variables + Llb_PartForEachVar( p, pPart1, pVar, i ) + { + RetValue = Vec_IntRemove( pVar->vParts, pPart1->iPart ); + assert( RetValue ); + pVar->nScore -= pPart1->nSize; + } + // update variables + Llb_PartForEachVar( p, pPart2, pVar, i ) + { + RetValue = Vec_IntRemove( pVar->vParts, pPart2->iPart ); + assert( RetValue ); + pVar->nScore -= pPart2->nSize; + } + // add variables to the new partition + nSuppSize = 0; + Extra_SupportArray( p->dd, bFunc, p->pSupp ); + for ( i = 0; i < p->nVars; i++ ) + { + nSuppSize += p->pSupp[i]; + if ( p->pSupp[i] && p->pVars2Q[i] ) + { + pVar = Llb_MgrVar( p, i ); + pVar->nScore += pTemp->nSize; + Vec_IntPush( pVar->vParts, pTemp->iPart ); + Vec_IntPush( pTemp->vVars, i ); + } + } + p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize ); + // remove variables and collect partitions with singleton variables + vSingles = Vec_PtrAlloc( 0 ); + Llb_PartForEachVar( p, pPart1, pVar, i ) + { + if ( Vec_IntSize(pVar->vParts) == 0 ) + Llb_NonlinRemoveVar( p, pVar ); + else if ( Vec_IntSize(pVar->vParts) == 1 ) + { + if ( fVerbose ) + printf( "Adding partition %d because of var %d.\n", + Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar ); + Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); + } + } + Llb_PartForEachVar( p, pPart2, pVar, i ) + { + if ( pVar == NULL ) + continue; + if ( Vec_IntSize(pVar->vParts) == 0 ) + Llb_NonlinRemoveVar( p, pVar ); + else if ( Vec_IntSize(pVar->vParts) == 1 ) + { + if ( fVerbose ) + printf( "Adding partition %d because of var %d.\n", + Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar ); + Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); + } + } + // remove partitions + Llb_NonlinRemovePart( p, pPart1 ); + Llb_NonlinRemovePart( p, pPart2 ); + // remove other variables +if ( fVerbose ) +Llb_NonlinPrint( p ); + Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i ) + { +if ( fVerbose ) +printf( "Updating partitiong %d with singlton vars.\n", pTemp->iPart ); + Llb_NonlinQuantify1( p, pTemp, 0 ); + } +if ( fVerbose ) +Llb_NonlinPrint( p ); + Vec_PtrFree( vSingles ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinCutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Saig_ObjIsLi(p, pObj) ) + { + Llb_NonlinCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); + return; + } + if ( Aig_ObjIsConst1(pObj) ) + return; + assert( Aig_ObjIsNode(pObj) ); + Llb_NonlinCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); + Llb_NonlinCutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_NonlinCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + // mark the lower cut with the traversal ID + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // count the upper cut + vNodes = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) + Llb_NonlinCutNodes_rec( p, pObj, vNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Returns array of BDDs for the roots in terms of the leaves.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_NonlinBuildBdds( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, DdManager * dd ) +{ + Vec_Ptr_t * vNodes, * vResult; + Aig_Obj_t * pObj; + DdNode * bBdd0, * bBdd1, * bProd; + int i, k; + + Aig_ManConst1(p)->pData = Cudd_ReadOne( dd ); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + pObj->pData = Cudd_bddIthVar( dd, Aig_ObjId(pObj) ); + + vNodes = Llb_NonlinCutNodes( p, vLower, vUpper ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); +// pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeOut ); + pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); + if ( pObj->pData == NULL ) + { + Vec_PtrForEachEntryStop( Aig_Obj_t *, vNodes, pObj, k, i ) + if ( pObj->pData ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + Vec_PtrFree( vNodes ); + return NULL; + } + Cudd_Ref( (DdNode *)pObj->pData ); + } + + vResult = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) + { + if ( Aig_ObjIsNode(pObj) ) + { + bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), (DdNode *)pObj->pData ); Cudd_Ref( bProd ); + } + else + { + assert( Saig_ObjIsLi(p, pObj) ); + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), bBdd0 ); Cudd_Ref( bProd ); + } + Vec_PtrPush( vResult, bProd ); + } + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + + Vec_PtrFree( vNodes ); + return vResult; +} + +/**Function************************************************************* + + Synopsis [Starts non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinAddPair( Llb_Mgr_t * p, DdNode * bFunc, int iPart, int iVar ) +{ + if ( p->pVars[iVar] == NULL ) + { + p->pVars[iVar] = ABC_CALLOC( Llb_Var_t, 1 ); + p->pVars[iVar]->iVar = iVar; + p->pVars[iVar]->nScore = 0; + p->pVars[iVar]->vParts = Vec_IntAlloc( 8 ); + } + Vec_IntPush( p->pVars[iVar]->vParts, iPart ); + Vec_IntPush( p->pParts[iPart]->vVars, iVar ); +} + +/**Function************************************************************* + + Synopsis [Starts non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinAddPartition( Llb_Mgr_t * p, int i, DdNode * bFunc ) +{ + int k, nSuppSize; + assert( !Cudd_IsConstant(bFunc) ); + // create partition + p->pParts[i] = ABC_CALLOC( Llb_Prt_t, 1 ); + p->pParts[i]->iPart = i; + p->pParts[i]->bFunc = bFunc; + p->pParts[i]->vVars = Vec_IntAlloc( 8 ); + // add support dependencies + nSuppSize = 0; + Extra_SupportArray( p->dd, bFunc, p->pSupp ); + for ( k = 0; k < p->nVars; k++ ) + { + nSuppSize += p->pSupp[k]; + if ( p->pSupp[k] && p->pVars2Q[k] ) + Llb_NonlinAddPair( p, bFunc, i, k ); + } + p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize ); +} + +/**Function************************************************************* + + Synopsis [Starts non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinStart( Llb_Mgr_t * p ) +{ + Vec_Ptr_t * vRootBdds; + DdNode * bFunc; + int i; + // create and collect BDDs + vRootBdds = Llb_NonlinBuildBdds( p->pAig, p->vLeaves, p->vRoots, p->dd ); // come referenced + if ( vRootBdds == NULL ) + return 0; + // add pairs (refs are consumed inside) + Vec_PtrForEachEntry( DdNode *, vRootBdds, bFunc, i ) + Llb_NonlinAddPartition( p, i, bFunc ); + Vec_PtrFree( vRootBdds ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks that each var appears in at least one partition.] + + Description [] + + SideEffects [] + + SeeAlso [] +**********************************************************************/ +void Llb_NonlinCheckVars( Llb_Mgr_t * p ) +{ + Llb_Var_t * pVar; + int i; + Llb_MgrForEachVar( p, pVar, i ) + assert( Vec_IntSize(pVar->vParts) > 1 ); +} + +/**Function************************************************************* + + Synopsis [Find next partition to quantify] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinNextPartitions( Llb_Mgr_t * p, Llb_Prt_t ** ppPart1, Llb_Prt_t ** ppPart2 ) +{ + Llb_Var_t * pVar, * pVarBest = NULL; + Llb_Prt_t * pPart, * pPart1Best = NULL, * pPart2Best = NULL; + int i; + Llb_NonlinCheckVars( p ); + // find variable with minimum score + Llb_MgrForEachVar( p, pVar, i ) + if ( pVarBest == NULL || pVarBest->nScore > pVar->nScore ) + pVarBest = pVar; + if ( pVarBest == NULL ) + return 0; + // find two partitions with minimum size + Llb_VarForEachPart( p, pVarBest, pPart, i ) + { + if ( pPart1Best == NULL ) + pPart1Best = pPart; + else if ( pPart2Best == NULL ) + pPart2Best = pPart; + else if ( pPart1Best->nSize > pPart->nSize || pPart2Best->nSize > pPart->nSize ) + { + if ( pPart1Best->nSize > pPart2Best->nSize ) + pPart1Best = pPart; + else + pPart2Best = pPart; + } + } + *ppPart1 = pPart1Best; + *ppPart2 = pPart2Best; + return 1; +} + +/**Function************************************************************* + + Synopsis [Reorders BDDs in the working manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinReorder( DdManager * dd, int fTwice, int fVerbose ) +{ + abctime clk = Abc_Clock(); + if ( fVerbose ) + Abc_Print( 1, "Reordering... Before =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + if ( fVerbose ) + Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + if ( fTwice ) + { + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + if ( fVerbose ) + Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + } + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [Recomputes scores after variable reordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinRecomputeScores( Llb_Mgr_t * p ) +{ + Llb_Prt_t * pPart; + Llb_Var_t * pVar; + int i, k; + Llb_MgrForEachPart( p, pPart, i ) + pPart->nSize = Cudd_DagSize(pPart->bFunc); + Llb_MgrForEachVar( p, pVar, i ) + { + pVar->nScore = 0; + Llb_VarForEachPart( p, pVar, pPart, k ) + pVar->nScore += pPart->nSize; + } +} + +/**Function************************************************************* + + Synopsis [Recomputes scores after variable reordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinVerifyScores( Llb_Mgr_t * p ) +{ + Llb_Prt_t * pPart; + Llb_Var_t * pVar; + int i, k, nScore; + Llb_MgrForEachPart( p, pPart, i ) + assert( pPart->nSize == Cudd_DagSize(pPart->bFunc) ); + Llb_MgrForEachVar( p, pVar, i ) + { + nScore = 0; + Llb_VarForEachPart( p, pVar, pPart, k ) + nScore += pPart->nSize; + assert( nScore == pVar->nScore ); + } +} + +/**Function************************************************************* + + Synopsis [Starts non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Mgr_t * Llb_NonlinAlloc( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, DdManager * dd ) +{ + Llb_Mgr_t * p; + p = ABC_CALLOC( Llb_Mgr_t, 1 ); + p->pAig = pAig; + p->vLeaves = vLeaves; + p->vRoots = vRoots; + p->dd = dd; + p->pVars2Q = pVars2Q; + p->nVars = Cudd_ReadSize(dd); + p->iPartFree = Vec_PtrSize(vRoots); + p->pVars = ABC_CALLOC( Llb_Var_t *, p->nVars ); + p->pParts = ABC_CALLOC( Llb_Prt_t *, 2 * p->iPartFree + 2 ); + p->pSupp = ABC_ALLOC( int, Cudd_ReadSize(dd) ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinFree( Llb_Mgr_t * p ) +{ + Llb_Prt_t * pPart; + Llb_Var_t * pVar; + int i; + Llb_MgrForEachVar( p, pVar, i ) + Llb_NonlinRemoveVar( p, pVar ); + Llb_MgrForEachPart( p, pPart, i ) + Llb_NonlinRemovePart( p, pPart ); + ABC_FREE( p->pVars ); + ABC_FREE( p->pParts ); + ABC_FREE( p->pSupp ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Performs image computation.] + + Description [Computes image of BDDs (vFuncs).] + + SideEffects [BDDs in vFuncs are derefed inside. The result is refed.] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_NonlinImage( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, + DdManager * dd, DdNode * bCurrent, int fReorder, int fVerbose, int * pOrder ) +{ + Llb_Prt_t * pPart, * pPart1, * pPart2; + Llb_Mgr_t * p; + DdNode * bFunc, * bTemp; + int i, nReorders, timeInside; + abctime clk = Abc_Clock(), clk2; + // start the manager + clk2 = Abc_Clock(); + p = Llb_NonlinAlloc( pAig, vLeaves, vRoots, pVars2Q, dd ); + if ( !Llb_NonlinStart( p ) ) + { + Llb_NonlinFree( p ); + return NULL; + } + // add partition + Llb_NonlinAddPartition( p, p->iPartFree++, bCurrent ); + // remove singles + Llb_MgrForEachPart( p, pPart, i ) + if ( Llb_NonlinHasSingletonVars(p, pPart) ) + Llb_NonlinQuantify1( p, pPart, 0 ); + timeBuild += Abc_Clock() - clk2; + timeInside = Abc_Clock() - clk2; + // compute scores + Llb_NonlinRecomputeScores( p ); + // save permutation + if ( pOrder ) + memcpy( pOrder, dd->invperm, sizeof(int) * dd->size ); + // iteratively quantify variables + while ( Llb_NonlinNextPartitions(p, &pPart1, &pPart2) ) + { + clk2 = Abc_Clock(); + nReorders = Cudd_ReadReorderings(dd); + if ( !Llb_NonlinQuantify2( p, pPart1, pPart2 ) ) + { + Llb_NonlinFree( p ); + return NULL; + } + timeAndEx += Abc_Clock() - clk2; + timeInside += Abc_Clock() - clk2; + if ( nReorders < Cudd_ReadReorderings(dd) ) + Llb_NonlinRecomputeScores( p ); +// else +// Llb_NonlinVerifyScores( p ); + } + // load partitions + bFunc = Cudd_ReadOne(p->dd); Cudd_Ref( bFunc ); + Llb_MgrForEachPart( p, pPart, i ) + { + bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + nSuppMax = p->nSuppMax; + Llb_NonlinFree( p ); + // reorder variables + if ( fReorder ) + Llb_NonlinReorder( dd, 0, fVerbose ); + timeOther += Abc_Clock() - clk - timeInside; + // return + Cudd_Deref( bFunc ); + return bFunc; +} + + + +static Llb_Mgr_t * p = NULL; + +/**Function************************************************************* + + Synopsis [Starts image computation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdManager * Llb_NonlinImageStart( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, int * pOrder, int fFirst, abctime TimeTarget ) +{ + DdManager * dd; + abctime clk = Abc_Clock(); + assert( p == NULL ); + // start a new manager (disable reordering) + dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + dd->TimeStop = TimeTarget; + Cudd_ShuffleHeap( dd, pOrder ); +// if ( fFirst ) + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + // start the manager + p = Llb_NonlinAlloc( pAig, vLeaves, vRoots, pVars2Q, dd ); + if ( !Llb_NonlinStart( p ) ) + { + Llb_NonlinFree( p ); + p = NULL; + return NULL; + } + timeBuild += Abc_Clock() - clk; +// if ( !fFirst ) +// Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + return dd; +} + +/**Function************************************************************* + + Synopsis [Performs image computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_NonlinImageCompute( DdNode * bCurrent, int fReorder, int fDrop, int fVerbose, int * pOrder ) +{ + Llb_Prt_t * pPart, * pPart1, * pPart2; + DdNode * bFunc, * bTemp; + int i, nReorders, timeInside = 0; + abctime clk = Abc_Clock(), clk2; + + // add partition + Llb_NonlinAddPartition( p, p->iPartFree++, bCurrent ); + // remove singles + Llb_MgrForEachPart( p, pPart, i ) + if ( Llb_NonlinHasSingletonVars(p, pPart) ) + Llb_NonlinQuantify1( p, pPart, 0 ); + // reorder + if ( fReorder ) + Llb_NonlinReorder( p->dd, 0, 0 ); + // save permutation + memcpy( pOrder, p->dd->invperm, sizeof(int) * p->dd->size ); + + // compute scores + Llb_NonlinRecomputeScores( p ); + // iteratively quantify variables + while ( Llb_NonlinNextPartitions(p, &pPart1, &pPart2) ) + { + clk2 = Abc_Clock(); + nReorders = Cudd_ReadReorderings(p->dd); + if ( !Llb_NonlinQuantify2( p, pPart1, pPart2 ) ) + { + Llb_NonlinFree( p ); + return NULL; + } + timeAndEx += Abc_Clock() - clk2; + timeInside += Abc_Clock() - clk2; + if ( nReorders < Cudd_ReadReorderings(p->dd) ) + Llb_NonlinRecomputeScores( p ); +// else +// Llb_NonlinVerifyScores( p ); + } + // load partitions + bFunc = Cudd_ReadOne(p->dd); Cudd_Ref( bFunc ); + Llb_MgrForEachPart( p, pPart, i ) + { + bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc ); + if ( bFunc == NULL ) + { + Cudd_RecursiveDeref( p->dd, bTemp ); + Llb_NonlinFree( p ); + return NULL; + } + Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + nSuppMax = p->nSuppMax; + // reorder variables +// if ( fReorder ) +// Llb_NonlinReorder( p->dd, 0, fVerbose ); + // save permutation +// memcpy( pOrder, p->dd->invperm, sizeof(int) * Cudd_ReadSize(p->dd) ); + + timeOther += Abc_Clock() - clk - timeInside; + // return + Cudd_Deref( bFunc ); + return bFunc; +} + +/**Function************************************************************* + + Synopsis [Quits image computation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinImageQuit() +{ + DdManager * dd; + if ( p == NULL ) + return; + dd = p->dd; + Llb_NonlinFree( p ); + if ( dd->bFunc ) + Cudd_RecursiveDeref( dd, dd->bFunc ); + Extra_StopManager( dd ); +// Cudd_Quit ( dd ); + p = NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb3Nonlin.c b/src/bdd/llb/llb3Nonlin.c new file mode 100644 index 00000000..94a48bbf --- /dev/null +++ b/src/bdd/llb/llb3Nonlin.c @@ -0,0 +1,872 @@ +/**CFile**************************************************************** + + FileName [llb2Nonlin.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Non-linear quantification scheduling.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Nonlin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Llb_Mnn_t_ Llb_Mnn_t; +struct Llb_Mnn_t_ +{ + Aig_Man_t * pInit; // AIG manager + Aig_Man_t * pAig; // AIG manager + Gia_ParLlb_t * pPars; // parameters + + DdManager * dd; // BDD manager + DdManager * ddG; // BDD manager + DdManager * ddR; // BDD manager + Vec_Ptr_t * vRings; // onion rings in ddR + + Vec_Ptr_t * vLeaves; + Vec_Ptr_t * vRoots; + int * pVars2Q; + int * pOrderL; + int * pOrderL2; + int * pOrderG; + + Vec_Int_t * vCs2Glo; // cur state variables into global variables + Vec_Int_t * vNs2Glo; // next state variables into global variables + Vec_Int_t * vGlo2Cs; // global variables into cur state variables + Vec_Int_t * vGlo2Ns; // global variables into next state variables + + int ddLocReos; + int ddLocGrbs; + + abctime timeImage; + abctime timeTran1; + abctime timeTran2; + abctime timeGloba; + abctime timeOther; + abctime timeTotal; + abctime timeReo; + abctime timeReoG; + +}; + +extern abctime timeBuild, timeAndEx, timeOther; +extern int nSuppMax; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Finds variable whose 0-cofactor is the smallest.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinFindBestVar( DdManager * dd, DdNode * bFunc, Aig_Man_t * pAig ) +{ + int fVerbose = 0; + Aig_Obj_t * pObj; + DdNode * bCof, * bVar; + int i, iVar, iVarBest = -1, iValue, iValueBest = ABC_INFINITY, Size0Best = -1; + int Size, Size0, Size1; + abctime clk = Abc_Clock(); + Size = Cudd_DagSize(bFunc); +// printf( "Original = %6d. SuppSize = %3d. Vars = %3d.\n", +// Size = Cudd_DagSize(bFunc), Cudd_SupportSize(dd, bFunc), Aig_ManRegNum(pAig) ); + Saig_ManForEachLo( pAig, pObj, i ) + { + iVar = Aig_ObjId(pObj); + +if ( fVerbose ) +printf( "Var =%3d : ", iVar ); + bVar = Cudd_bddIthVar(dd, iVar); + + bCof = Cudd_bddAnd( dd, bFunc, Cudd_Not(bVar) ); Cudd_Ref( bCof ); + Size0 = Cudd_DagSize(bCof); +if ( fVerbose ) +printf( "Supp0 =%3d ", Cudd_SupportSize(dd, bCof) ); +if ( fVerbose ) +printf( "Size0 =%6d ", Size0 ); + Cudd_RecursiveDeref( dd, bCof ); + + bCof = Cudd_bddAnd( dd, bFunc, bVar ); Cudd_Ref( bCof ); + Size1 = Cudd_DagSize(bCof); +if ( fVerbose ) +printf( "Supp1 =%3d ", Cudd_SupportSize(dd, bCof) ); +if ( fVerbose ) +printf( "Size1 =%6d ", Size1 ); + Cudd_RecursiveDeref( dd, bCof ); + + iValue = Abc_MaxInt(Size0, Size1) - Abc_MinInt(Size0, Size1) + Size0 + Size1 - Size; +if ( fVerbose ) +printf( "D =%6d ", Size0 + Size1 - Size ); +if ( fVerbose ) +printf( "B =%6d ", Abc_MaxInt(Size0, Size1) - Abc_MinInt(Size0, Size1) ); +if ( fVerbose ) +printf( "S =%6d\n", iValue ); + if ( Size0 > 1 && Size1 > 1 && iValueBest > iValue ) + { + iValueBest = iValue; + iVarBest = i; + Size0Best = Size0; + } + } + printf( "BestVar = %4d/%4d. Value =%6d. Orig =%6d. Size0 =%6d. ", + iVarBest, Aig_ObjId(Saig_ManLo(pAig,iVarBest)), iValueBest, Size, Size0Best ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return iVarBest; +} + + +/**Function************************************************************* + + Synopsis [Finds variable whose 0-cofactor is the smallest.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinTrySubsetting( DdManager * dd, DdNode * bFunc ) +{ + DdNode * bNew; + printf( "Original = %6d. SuppSize = %3d. ", + Cudd_DagSize(bFunc), Cudd_SupportSize(dd, bFunc) ); + bNew = Cudd_SubsetHeavyBranch( dd, bFunc, Cudd_SupportSize(dd, bFunc), 1000 ); Cudd_Ref( bNew ); + printf( "Result = %6d. SuppSize = %3d.\n", + Cudd_DagSize(bNew), Cudd_SupportSize(dd, bNew) ); + Cudd_RecursiveDeref( dd, bNew ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinPrepareVarMap( Llb_Mnn_t * p ) +{ + Aig_Obj_t * pObjLi, * pObjLo, * pObj; + int i, iVarLi, iVarLo; + p->vCs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) ); + p->vNs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) ); + p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); + p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); + Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) + { + iVarLi = Aig_ObjId(pObjLi); + iVarLo = Aig_ObjId(pObjLo); + assert( iVarLi >= 0 && iVarLi < Aig_ManObjNumMax(p->pAig) ); + assert( iVarLo >= 0 && iVarLo < Aig_ManObjNumMax(p->pAig) ); + Vec_IntWriteEntry( p->vCs2Glo, iVarLo, i ); + Vec_IntWriteEntry( p->vNs2Glo, iVarLi, i ); + Vec_IntWriteEntry( p->vGlo2Cs, i, iVarLo ); + Vec_IntWriteEntry( p->vGlo2Ns, i, iVarLi ); + } + // add mapping of the PIs + Saig_ManForEachPi( p->pAig, pObj, i ) + { + Vec_IntWriteEntry( p->vCs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i ); + Vec_IntWriteEntry( p->vNs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i ); + } +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_NonlinComputeInitState( Aig_Man_t * pAig, DdManager * dd ) +{ + Aig_Obj_t * pObj; + DdNode * bRes, * bVar, * bTemp; + int i, iVar; + abctime TimeStop; + TimeStop = dd->TimeStop; dd->TimeStop = 0; + bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); + Saig_ManForEachLo( pAig, pObj, i ) + { + iVar = (Cudd_ReadSize(dd) == Aig_ManRegNum(pAig)) ? i : Aig_ObjId(pObj); + bVar = Cudd_bddIthVar( dd, iVar ); + bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bRes ); + dd->TimeStop = TimeStop; + return bRes; +} + + +/**Function************************************************************* + + Synopsis [Derives counter-example by backward reachability.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Llb_NonlinDeriveCex( Llb_Mnn_t * p ) +{ + Abc_Cex_t * pCex; + Aig_Obj_t * pObj; + Vec_Int_t * vVarsNs; + DdNode * bState = NULL, * bImage, * bOneCube, * bTemp, * bRing; + int i, v, RetValue, nPiOffset; + char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) ); + assert( Vec_PtrSize(p->vRings) > 0 ); + + p->dd->TimeStop = 0; + p->ddR->TimeStop = 0; + + // update quantifiable vars + memset( p->pVars2Q, 0, sizeof(int) * Cudd_ReadSize(p->dd) ); + vVarsNs = Vec_IntAlloc( Aig_ManRegNum(p->pAig) ); + Saig_ManForEachLi( p->pAig, pObj, i ) + { + p->pVars2Q[Aig_ObjId(pObj)] = 1; + Vec_IntPush( vVarsNs, Aig_ObjId(pObj) ); + } +/* + Saig_ManForEachLo( p->pAig, pObj, i ) + printf( "%d ", pObj->Id ); + printf( "\n" ); + Saig_ManForEachLi( p->pAig, pObj, i ) + printf( "%d(%d) ", pObj->Id, Aig_ObjFaninId0(pObj) ); + printf( "\n" ); +*/ + // allocate room for the counter-example + pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) ); + pCex->iFrame = Vec_PtrSize(p->vRings) - 1; + pCex->iPo = -1; + + // get the last cube + bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc ); Cudd_Ref( bOneCube ); + RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); + Cudd_RecursiveDeref( p->ddR, bOneCube ); + assert( RetValue ); + + // write PIs of counter-example + nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1); + Saig_ManForEachPi( p->pAig, pObj, i ) + if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) + Abc_InfoSetBit( pCex->pData, nPiOffset + i ); + + // write state in terms of NS variables + if ( Vec_PtrSize(p->vRings) > 1 ) + { + bState = Llb_CoreComputeCube( p->dd, vVarsNs, 1, pValues ); Cudd_Ref( bState ); + } + // perform backward analysis + Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v ) + { + if ( v == Vec_PtrSize(p->vRings) - 1 ) + continue; +//Extra_bddPrintSupport( p->dd, bState ); printf( "\n" ); +//Extra_bddPrintSupport( p->dd, bRing ); printf( "\n" ); + // compute the next states + bImage = Llb_NonlinImage( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->dd, bState, + p->pPars->fReorder, p->pPars->fVeryVerbose, NULL ); // consumed reference + assert( bImage != NULL ); + Cudd_Ref( bImage ); +//Extra_bddPrintSupport( p->dd, bImage ); printf( "\n" ); + + // move reached states into ring manager + bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) ); Cudd_Ref( bImage ); + Cudd_RecursiveDeref( p->dd, bTemp ); + + // intersect with the previous set + bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing ); Cudd_Ref( bOneCube ); + Cudd_RecursiveDeref( p->ddR, bImage ); + + // find any assignment of the BDD + RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); + Cudd_RecursiveDeref( p->ddR, bOneCube ); + assert( RetValue ); + + // write PIs of counter-example + nPiOffset -= Saig_ManPiNum(p->pAig); + Saig_ManForEachPi( p->pAig, pObj, i ) + if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) + Abc_InfoSetBit( pCex->pData, nPiOffset + i ); + + // check that we get the init state + if ( v == 0 ) + { + Saig_ManForEachLo( p->pAig, pObj, i ) + assert( pValues[i] == 0 ); + break; + } + + // write state in terms of NS variables + bState = Llb_CoreComputeCube( p->dd, vVarsNs, 1, pValues ); Cudd_Ref( bState ); + } + assert( nPiOffset == Saig_ManRegNum(p->pAig) ); + // update the output number +//Abc_CexPrint( pCex ); + RetValue = Saig_ManFindFailedPoCex( p->pInit, pCex ); + assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pInit) ); // invalid CEX!!! + pCex->iPo = RetValue; + // cleanup + ABC_FREE( pValues ); + Vec_IntFree( vVarsNs ); + return pCex; +} + + +/**Function************************************************************* + + Synopsis [Perform reachability with hints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinReoHook( DdManager * dd, char * Type, void * Method ) +{ + Aig_Man_t * pAig = (Aig_Man_t *)dd->bFunc; + Aig_Obj_t * pObj; + int i; + printf( "Order: " ); + for ( i = 0; i < Cudd_ReadSize(dd); i++ ) + { + pObj = Aig_ManObj( pAig, i ); + if ( pObj == NULL ) + continue; + if ( Saig_ObjIsPi(pAig, pObj) ) + printf( "pi" ); + else if ( Saig_ObjIsLo(pAig, pObj) ) + printf( "lo" ); + else if ( Saig_ObjIsPo(pAig, pObj) ) + printf( "po" ); + else if ( Saig_ObjIsLi(pAig, pObj) ) + printf( "li" ); + else continue; + printf( "%d=%d ", i, dd->perm[i] ); + } + printf( "\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Perform reachability with hints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinCompPerms( DdManager * dd, int * pVar2Lev ) +{ + DdSubtable * pSubt; + int i, Sum = 0, Entry; + for ( i = 0; i < dd->size; i++ ) + { + pSubt = &(dd->subtables[dd->perm[i]]); + if ( pSubt->keys == pSubt->dead + 1 ) + continue; + Entry = Abc_MaxInt(dd->perm[i], pVar2Lev[i]) - Abc_MinInt(dd->perm[i], pVar2Lev[i]); + Sum += Entry; +//printf( "%d-%d(%d) ", dd->perm[i], pV2L[i], Entry ); + } + return Sum; +} + +/**Function************************************************************* + + Synopsis [Perform reachability with hints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinReachability( Llb_Mnn_t * p ) +{ + DdNode * bTemp, * bNext; + int nIters, nBddSize0, nBddSize = -1, NumCmp;//, Limit = p->pPars->nBddMax; + abctime clk2, clk3, clk = Abc_Clock(); + assert( Aig_ManRegNum(p->pAig) > 0 ); + + // compute time to stop + p->pPars->TimeTarget = p->pPars->TimeLimit ? p->pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0; + + // set the stop time parameter + p->dd->TimeStop = p->pPars->TimeTarget; + p->ddG->TimeStop = p->pPars->TimeTarget; + p->ddR->TimeStop = p->pPars->TimeTarget; + + // set reordering hooks + assert( p->dd->bFunc == NULL ); +// p->dd->bFunc = (DdNode *)p->pAig; +// Cudd_AddHook( p->dd, Llb_NonlinReoHook, CUDD_POST_REORDERING_HOOK ); + + // create bad state in the ring manager + p->ddR->bFunc = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget ); + if ( p->ddR->bFunc == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + Cudd_Ref( p->ddR->bFunc ); + // compute the starting set of states + Cudd_Quit( p->dd ); + p->dd = Llb_NonlinImageStart( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->pOrderL, 1, p->pPars->TimeTarget ); + if ( p->dd == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + p->dd->bFunc = Llb_NonlinComputeInitState( p->pAig, p->dd ); Cudd_Ref( p->dd->bFunc ); // current + p->ddG->bFunc = Llb_NonlinComputeInitState( p->pAig, p->ddG ); Cudd_Ref( p->ddG->bFunc ); // reached + p->ddG->bFunc2 = Llb_NonlinComputeInitState( p->pAig, p->ddG ); Cudd_Ref( p->ddG->bFunc2 ); // frontier + for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ ) + { + // check the runtime limit + clk2 = Abc_Clock(); + if ( p->pPars->TimeLimit && Abc_Clock() > p->pPars->TimeTarget ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Llb_NonlinImageQuit(); + return -1; + } + + // save the onion ring + bTemp = Extra_TransferPermute( p->dd, p->ddR, p->dd->bFunc, Vec_IntArray(p->vCs2Glo) ); + if ( bTemp == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during ring transfer.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Llb_NonlinImageQuit(); + return -1; + } + Cudd_Ref( bTemp ); + Vec_PtrPush( p->vRings, bTemp ); + + // check it for bad states + if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) ) + { + assert( p->pInit->pSeqModel == NULL ); + if ( !p->pPars->fBackward ) + p->pInit->pSeqModel = Llb_NonlinDeriveCex( p ); + if ( !p->pPars->fSilent ) + { + if ( !p->pPars->fBackward ) + Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", p->pInit->pSeqModel->iPo, nIters ); + else + Abc_Print( 1, "Output ??? was asserted in frame %d (counter-example is not produced). ", nIters ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + p->pPars->iFrame = nIters - 1; + Llb_NonlinImageQuit(); + return 0; + } + + // compute the next states + clk3 = Abc_Clock(); + nBddSize0 = Cudd_DagSize( p->dd->bFunc ); + bNext = Llb_NonlinImageCompute( p->dd->bFunc, p->pPars->fReorder, 0, 1, p->pOrderL ); // consumes ref +// bNext = Llb_NonlinImage( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->dd, bCurrent, +// p->pPars->fReorder, p->pPars->fVeryVerbose, NULL, ABC_INFINITY, p->pPars->TimeTarget ); + if ( bNext == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in quantification.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Llb_NonlinImageQuit(); + return -1; + } + Cudd_Ref( bNext ); + nBddSize = Cudd_DagSize( bNext ); + p->timeImage += Abc_Clock() - clk3; + + + // transfer to the state manager + clk3 = Abc_Clock(); + Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc2 ); + p->ddG->bFunc2 = Extra_TransferPermute( p->dd, p->ddG, bNext, Vec_IntArray(p->vNs2Glo) ); +// p->ddG->bFunc2 = Extra_bddAndPermute( p->ddG, Cudd_Not(p->ddG->bFunc), p->dd, bNext, Vec_IntArray(p->vNs2Glo) ); + if ( p->ddG->bFunc2 == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bNext ); + Llb_NonlinImageQuit(); + return -1; + } + Cudd_Ref( p->ddG->bFunc2 ); + Cudd_RecursiveDeref( p->dd, bNext ); + p->timeTran1 += Abc_Clock() - clk3; + + // save permutation + NumCmp = Llb_NonlinCompPerms( p->dd, p->pOrderL2 ); + // save order before image computation + memcpy( p->pOrderL2, p->dd->perm, sizeof(int) * p->dd->size ); + // update the image computation manager + p->timeReo += Cudd_ReadReorderingTime(p->dd); + p->ddLocReos += Cudd_ReadReorderings(p->dd); + p->ddLocGrbs += Cudd_ReadGarbageCollections(p->dd); + Llb_NonlinImageQuit(); + p->dd = Llb_NonlinImageStart( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->pOrderL, 0, p->pPars->TimeTarget ); + if ( p->dd == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + return -1; + } + //Extra_TestAndPerm( p->ddG, Cudd_Not(p->ddG->bFunc), p->ddG->bFunc2 ); + + // derive new states + clk3 = Abc_Clock(); + p->ddG->bFunc2 = Cudd_bddAnd( p->ddG, bTemp = p->ddG->bFunc2, Cudd_Not(p->ddG->bFunc) ); + if ( p->ddG->bFunc2 == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->ddG, bTemp ); + Llb_NonlinImageQuit(); + return -1; + } + Cudd_Ref( p->ddG->bFunc2 ); + Cudd_RecursiveDeref( p->ddG, bTemp ); + p->timeGloba += Abc_Clock() - clk3; + + if ( Cudd_IsConstant(p->ddG->bFunc2) ) + break; + // add to the reached set + clk3 = Abc_Clock(); + p->ddG->bFunc = Cudd_bddOr( p->ddG, bTemp = p->ddG->bFunc, p->ddG->bFunc2 ); + if ( p->ddG->bFunc == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->ddG, bTemp ); + Llb_NonlinImageQuit(); + return -1; + } + Cudd_Ref( p->ddG->bFunc ); + Cudd_RecursiveDeref( p->ddG, bTemp ); + p->timeGloba += Abc_Clock() - clk3; + + // reset permutation +// RetValue = Cudd_CheckZeroRef( dd ); +// assert( RetValue == 0 ); +// Cudd_ShuffleHeap( dd, pOrderG ); + + // move new states to the working manager + clk3 = Abc_Clock(); + p->dd->bFunc = Extra_TransferPermute( p->ddG, p->dd, p->ddG->bFunc2, Vec_IntArray(p->vGlo2Cs) ); + if ( p->dd->bFunc == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Llb_NonlinImageQuit(); + return -1; + } + Cudd_Ref( p->dd->bFunc ); + p->timeTran2 += Abc_Clock() - clk3; + + // report the results + if ( p->pPars->fVerbose ) + { + printf( "I =%3d : ", nIters ); + printf( "Fr =%7d ", nBddSize0 ); + printf( "Im =%7d ", nBddSize ); + printf( "(%4d %4d) ", p->ddLocReos, p->ddLocGrbs ); + printf( "Rea =%6d ", Cudd_DagSize(p->ddG->bFunc) ); + printf( "(%4d %4d) ", Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) ); + printf( "S =%4d ", nSuppMax ); + printf( "cL =%5d ", NumCmp ); + printf( "cG =%5d ", Llb_NonlinCompPerms( p->ddG, p->pOrderG ) ); + Abc_PrintTime( 1, "T", Abc_Clock() - clk2 ); + memcpy( p->pOrderG, p->ddG->perm, sizeof(int) * p->ddG->size ); + } +/* + if ( pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(ddG, bReached, Saig_ManRegNum(pAig) ); +// Extra_bddPrint( ddG, bReached );printf( "\n" ); + printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(pAig)) ); + fflush( stdout ); + } +*/ + if ( nIters == p->pPars->nIterMax - 1 ) + { + if ( !p->pPars->fSilent ) + printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nIterMax ); + p->pPars->iFrame = nIters; + Llb_NonlinImageQuit(); + return -1; + } + } + Llb_NonlinImageQuit(); + + // report the stats + if ( p->pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(p->ddG, p->ddG->bFunc, Saig_ManRegNum(p->pAig) ); + if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) + printf( "Reachability analysis is stopped after %d frames.\n", nIters ); + else + printf( "Reachability analysis completed after %d frames.\n", nIters ); + printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); + fflush( stdout ); + } + if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) + { + if ( !p->pPars->fSilent ) + printf( "Verified only for states reachable in %d frames. ", nIters ); + p->pPars->iFrame = p->pPars->nIterMax; + return -1; // undecided + } + // report + if ( !p->pPars->fSilent ) + printf( "The miter is proved unreachable after %d iterations. ", nIters ); + p->pPars->iFrame = nIters - 1; + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return 1; // unreachable +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Mnn_t * Llb_MnnStart( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) +{ + Llb_Mnn_t * p; + Aig_Obj_t * pObj; + int i; + p = ABC_CALLOC( Llb_Mnn_t, 1 ); + p->pInit = pInit; + p->pAig = pAig; + p->pPars = pPars; + p->dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + p->ddG = Cudd_Init( Aig_ManRegNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + p->ddR = Cudd_Init( Aig_ManCiNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); + Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT ); + Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT ); + p->vRings = Vec_PtrAlloc( 100 ); + // create leaves + p->vLeaves = Vec_PtrAlloc( Aig_ManCiNum(pAig) ); + Aig_ManForEachCi( pAig, pObj, i ) + Vec_PtrPush( p->vLeaves, pObj ); + // create roots + p->vRoots = Vec_PtrAlloc( Aig_ManCoNum(pAig) ); + Saig_ManForEachLi( pAig, pObj, i ) + Vec_PtrPush( p->vRoots, pObj ); + // variables to quantify + p->pOrderL = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); + p->pOrderL2= ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); + p->pOrderG = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); + p->pVars2Q = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); + Aig_ManForEachCi( pAig, pObj, i ) + p->pVars2Q[Aig_ObjId(pObj)] = 1; + for ( i = 0; i < Aig_ManObjNumMax(pAig); i++ ) + p->pOrderL[i] = p->pOrderL2[i] = p->pOrderG[i] = i; + Llb_NonlinPrepareVarMap( p ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MnnStop( Llb_Mnn_t * p ) +{ + DdNode * bTemp; + int i; + if ( p->pPars->fVerbose ) + { + p->timeOther = p->timeTotal - p->timeImage - p->timeTran1 - p->timeTran2 - p->timeGloba; + p->timeReoG = Cudd_ReadReorderingTime(p->ddG); + ABC_PRTP( "Image ", p->timeImage, p->timeTotal ); + ABC_PRTP( " build ", timeBuild, p->timeTotal ); + ABC_PRTP( " and-ex ", timeAndEx, p->timeTotal ); + ABC_PRTP( " other ", timeOther, p->timeTotal ); + ABC_PRTP( "Transfer1", p->timeTran1, p->timeTotal ); + ABC_PRTP( "Transfer2", p->timeTran2, p->timeTotal ); + ABC_PRTP( "Global ", p->timeGloba, p->timeTotal ); + ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); + ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); + ABC_PRTP( " reo ", p->timeReo, p->timeTotal ); + ABC_PRTP( " reoG ", p->timeReoG, p->timeTotal ); + } + if ( p->ddR->bFunc ) + Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc ); + Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i ) + Cudd_RecursiveDeref( p->ddR, bTemp ); + Vec_PtrFree( p->vRings ); + if ( p->ddG->bFunc ) + Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc ); + if ( p->ddG->bFunc2 ) + Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc2 ); +// printf( "manager1\n" ); +// Extra_StopManager( p->dd ); +// printf( "manager2\n" ); + Extra_StopManager( p->ddG ); +// printf( "manager3\n" ); + Extra_StopManager( p->ddR ); + Vec_IntFreeP( &p->vCs2Glo ); + Vec_IntFreeP( &p->vNs2Glo ); + Vec_IntFreeP( &p->vGlo2Cs ); + Vec_IntFreeP( &p->vGlo2Ns ); + Vec_PtrFree( p->vLeaves ); + Vec_PtrFree( p->vRoots ); + ABC_FREE( p->pVars2Q ); + ABC_FREE( p->pOrderL ); + ABC_FREE( p->pOrderL2 ); + ABC_FREE( p->pOrderG ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinExperiment( Aig_Man_t * pAig, int Num ) +{ + Llb_Mnn_t * pMnn; + Gia_ParLlb_t Pars, * pPars = &Pars; + Aig_Man_t * p; + abctime clk = Abc_Clock(); + + Llb_ManSetDefaultParams( pPars ); + pPars->fVerbose = 1; + + p = Aig_ManDupFlopsOnly( pAig ); +//Aig_ManShow( p, 0, NULL ); + Aig_ManPrintStats( pAig ); + Aig_ManPrintStats( p ); + + pMnn = Llb_MnnStart( pAig, p, pPars ); + Llb_NonlinReachability( pMnn ); + pMnn->timeTotal = Abc_Clock() - clk; + Llb_MnnStop( pMnn ); + + Aig_ManStop( p ); +} + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinCoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) +{ + Llb_Mnn_t * pMnn; + Aig_Man_t * p; + int RetValue = -1; + + p = Aig_ManDupFlopsOnly( pAig ); +//Aig_ManShow( p, 0, NULL ); + if ( pPars->fVerbose ) + Aig_ManPrintStats( pAig ); + if ( pPars->fVerbose ) + Aig_ManPrintStats( p ); + + if ( !pPars->fSkipReach ) + { + abctime clk = Abc_Clock(); + pMnn = Llb_MnnStart( pAig, p, pPars ); + RetValue = Llb_NonlinReachability( pMnn ); + pMnn->timeTotal = Abc_Clock() - clk; + Llb_MnnStop( pMnn ); + } + + Aig_ManStop( p ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb4Cex.c b/src/bdd/llb/llb4Cex.c new file mode 100644 index 00000000..18aeaf04 --- /dev/null +++ b/src/bdd/llb/llb4Cex.c @@ -0,0 +1,320 @@ +/**CFile**************************************************************** + + FileName [llb2Cex.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Non-linear quantification scheduling.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Cex.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" +#include "sat/cnf/cnf.h" +#include "sat/bsat/satSolver.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Translates a sequence of states into a counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Llb4_Nonlin4TransformCex( Aig_Man_t * pAig, Vec_Ptr_t * vStates, int iCexPo, int fVerbose ) +{ + Abc_Cex_t * pCex; + Cnf_Dat_t * pCnf; + Vec_Int_t * vAssumps; + sat_solver * pSat; + Aig_Obj_t * pObj; + unsigned * pNext, * pThis; + int i, k, iBit, status, nRegs;//, clk = Abc_Clock(); +/* + Vec_PtrForEachEntry( unsigned *, vStates, pNext, i ) + { + printf( "%4d : ", i ); + Extra_PrintBinary( stdout, pNext, Aig_ManRegNum(pAig) ); + printf( "\n" ); + } +*/ + // derive SAT solver + nRegs = Aig_ManRegNum(pAig); pAig->nRegs = 0; + pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) ); + pAig->nRegs = nRegs; +// Cnf_DataTranformPolarity( pCnf, 0 ); + // convert into SAT solver + pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + if ( pSat == NULL ) + { + printf( "Llb4_Nonlin4TransformCex(): Counter-example generation has failed.\n" ); + Cnf_DataFree( pCnf ); + return NULL; + } + // simplify the problem + status = sat_solver_simplify(pSat); + if ( status == 0 ) + { + printf( "Llb4_Nonlin4TransformCex(): SAT solver is invalid.\n" ); + sat_solver_delete( pSat ); + Cnf_DataFree( pCnf ); + return NULL; + } + // start the counter-example + pCex = Abc_CexAlloc( Saig_ManRegNum(pAig), Saig_ManPiNum(pAig), Vec_PtrSize(vStates) ); + pCex->iFrame = Vec_PtrSize(vStates)-1; + pCex->iPo = -1; + + // solve each time frame + iBit = Saig_ManRegNum(pAig); + pThis = (unsigned *)Vec_PtrEntry( vStates, 0 ); + vAssumps = Vec_IntAlloc( 2 * Aig_ManRegNum(pAig) ); + Vec_PtrForEachEntryStart( unsigned *, vStates, pNext, i, 1 ) + { + // create assumptions + Vec_IntClear( vAssumps ); + Saig_ManForEachLo( pAig, pObj, k ) + Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Abc_InfoHasBit(pThis,k) ) ); + Saig_ManForEachLi( pAig, pObj, k ) + Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Abc_InfoHasBit(pNext,k) ) ); + // solve SAT problem + status = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), + (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + // if the problem is SAT, get the counterexample + if ( status != l_True ) + { + printf( "Llb4_Nonlin4TransformCex(): There is no transition between state %d and %d.\n", i-1, i ); + Vec_IntFree( vAssumps ); + sat_solver_delete( pSat ); + Cnf_DataFree( pCnf ); + ABC_FREE( pCex ); + return NULL; + } + // get the assignment of PIs + Saig_ManForEachPi( pAig, pObj, k ) + if ( sat_solver_var_value(pSat, pCnf->pVarNums[Aig_ObjId(pObj)]) ) + Abc_InfoSetBit( pCex->pData, iBit + k ); + // update the counter + iBit += Saig_ManPiNum(pAig); + pThis = pNext; + } + + // add the last frame when the property fails + Vec_IntClear( vAssumps ); + if ( iCexPo >= 0 ) + { + Saig_ManForEachPo( pAig, pObj, k ) + if ( k == iCexPo ) + Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 ) ); + } + else + { + Saig_ManForEachPo( pAig, pObj, k ) + Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 ) ); + } + + // add clause + status = sat_solver_addclause( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps) ); + if ( status == 0 ) + { + printf( "Llb4_Nonlin4TransformCex(): The SAT solver is unsat after adding last clause.\n" ); + Vec_IntFree( vAssumps ); + sat_solver_delete( pSat ); + Cnf_DataFree( pCnf ); + ABC_FREE( pCex ); + return NULL; + } + // create assumptions + Vec_IntClear( vAssumps ); + Saig_ManForEachLo( pAig, pObj, k ) + Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Abc_InfoHasBit(pThis,k) ) ); + // solve the last frame + status = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), + (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + if ( status != l_True ) + { + printf( "Llb4_Nonlin4TransformCex(): There is no last transition that makes the property fail.\n" ); + Vec_IntFree( vAssumps ); + sat_solver_delete( pSat ); + Cnf_DataFree( pCnf ); + ABC_FREE( pCex ); + return NULL; + } + // get the assignment of PIs + Saig_ManForEachPi( pAig, pObj, k ) + if ( sat_solver_var_value(pSat, pCnf->pVarNums[Aig_ObjId(pObj)]) ) + Abc_InfoSetBit( pCex->pData, iBit + k ); + iBit += Saig_ManPiNum(pAig); + assert( iBit == pCex->nBits ); + + // free the sat_solver + Vec_IntFree( vAssumps ); + sat_solver_delete( pSat ); + Cnf_DataFree( pCnf ); + + // verify counter-example + status = Saig_ManFindFailedPoCex( pAig, pCex ); + if ( status >= 0 && status < Saig_ManPoNum(pAig) ) + pCex->iPo = status; + else + { + printf( "Llb4_Nonlin4TransformCex(): Counter-example verification has FAILED.\n" ); + ABC_FREE( pCex ); + return NULL; + } + // report the results +// if ( fVerbose ) +// Abc_PrintTime( 1, "SAT-based cex generation time", Abc_Clock() - clk ); + return pCex; +} + + +/**Function************************************************************* + + Synopsis [Resimulates the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb4_Nonlin4VerifyCex( Aig_Man_t * pAig, Abc_Cex_t * p ) +{ + Vec_Ptr_t * vStates; + Aig_Obj_t * pObj, * pObjRi, * pObjRo; + int i, k, iBit = 0; + // create storage for states + vStates = Vec_PtrAllocSimInfo( p->iFrame+1, Abc_BitWordNum(Aig_ManRegNum(pAig)) ); + Vec_PtrCleanSimInfo( vStates, 0, Abc_BitWordNum(Aig_ManRegNum(pAig)) ); + // verify counter-example + Aig_ManCleanMarkB(pAig); + Aig_ManConst1(pAig)->fMarkB = 1; + Saig_ManForEachLo( pAig, pObj, i ) + pObj->fMarkB = 0; //Abc_InfoHasBit(p->pData, iBit++); + // do not require equal flop count in the AIG and in the CEX + iBit = p->nRegs; + for ( i = 0; i <= p->iFrame; i++ ) + { + // save current state + Saig_ManForEachLo( pAig, pObj, k ) + if ( pObj->fMarkB ) + Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(vStates, i), k ); + // compute new state + Saig_ManForEachPi( pAig, pObj, k ) + pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++); + Aig_ManForEachNode( pAig, pObj, k ) + pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & + (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj)); + Aig_ManForEachCo( pAig, pObj, k ) + pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj); + if ( i == p->iFrame ) + break; + Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, k ) + pObjRo->fMarkB = pObjRi->fMarkB; + } +/* + { + unsigned * pNext; + Vec_PtrForEachEntry( unsigned *, vStates, pNext, i ) + { + printf( "%4d : ", i ); + Extra_PrintBinary( stdout, pNext, Aig_ManRegNum(pAig) ); + printf( "\n" ); + } + } +*/ + assert( iBit == p->nBits ); +// if ( Aig_ManCo(pAig, p->iPo)->fMarkB == 0 ) +// Vec_PtrFreeP( &vStates ); + for ( i = Saig_ManPoNum(pAig) - 1; i >= 0; i-- ) + { + if ( Aig_ManCo(pAig, i)->fMarkB ) + { + p->iPo = i; + break; + } + } + if ( i == -1 ) + Vec_PtrFreeP( &vStates ); + Aig_ManCleanMarkB(pAig); + return vStates; +} + +/**Function************************************************************* + + Synopsis [Translates a sequence of states into a counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Llb4_Nonlin4NormalizeCex( Aig_Man_t * pAigOrg, Aig_Man_t * pAigRpm, Abc_Cex_t * pCexRpm ) +{ + Abc_Cex_t * pCexOrg; + Vec_Ptr_t * vStates; + // check parameters of the AIG + if ( Saig_ManRegNum(pAigOrg) != Saig_ManRegNum(pAigRpm) ) + { + printf( "Llb4_Nonlin4NormalizeCex(): The number of flops in the original and reparametrized AIGs do not agree.\n" ); + return NULL; + } +/* + if ( Saig_ManRegNum(pAigRpm) != pCexRpm->nRegs ) + { + printf( "Llb4_Nonlin4NormalizeCex(): The number of flops in the reparametrized AIG and in the CEX do not agree.\n" ); + return NULL; + } +*/ + if ( Saig_ManPiNum(pAigRpm) != pCexRpm->nPis ) + { + printf( "Llb4_Nonlin4NormalizeCex(): The number of PIs in the reparametrized AIG and in the CEX do not agree.\n" ); + return NULL; + } + // get the sequence of states + vStates = Llb4_Nonlin4VerifyCex( pAigRpm, pCexRpm ); + if ( vStates == NULL ) + { + Abc_Print( 1, "Llb4_Nonlin4NormalizeCex(): The given CEX does not fail outputs of pAigRpm.\n" ); + return NULL; + } + // derive updated counter-example + pCexOrg = Llb4_Nonlin4TransformCex( pAigOrg, vStates, pCexRpm->iPo, 0 ); + Vec_PtrFree( vStates ); + return pCexOrg; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb4Cluster.c b/src/bdd/llb/llb4Cluster.c new file mode 100644 index 00000000..7e325597 --- /dev/null +++ b/src/bdd/llb/llb4Cluster.c @@ -0,0 +1,452 @@ +/**CFile**************************************************************** + + FileName [llb2Cluster.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Non-linear quantification scheduling.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Cluster.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Find good static variable ordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4FindOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter ) +{ + Aig_Obj_t * pFanin0, * pFanin1; + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return; + Aig_ObjSetTravIdCurrent( pAig, pObj ); + assert( Llb_ObjBddVar(vOrder, pObj) < 0 ); + if ( Aig_ObjIsCi(pObj) ) + { + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); + return; + } + // try fanins with higher level first + pFanin0 = Aig_ObjFanin0(pObj); + pFanin1 = Aig_ObjFanin1(pObj); +// if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) ) + if ( pFanin0->Level > pFanin1->Level ) + { + Llb_Nonlin4FindOrder_rec( pAig, pFanin0, vOrder, pCounter ); + Llb_Nonlin4FindOrder_rec( pAig, pFanin1, vOrder, pCounter ); + } + else + { + Llb_Nonlin4FindOrder_rec( pAig, pFanin1, vOrder, pCounter ); + Llb_Nonlin4FindOrder_rec( pAig, pFanin0, vOrder, pCounter ); + } + if ( pObj->fMarkA ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); +} + +/**Function************************************************************* + + Synopsis [Find good static variable ordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_Nonlin4FindOrder( Aig_Man_t * pAig, int * pCounter ) +{ + Vec_Int_t * vNodes = NULL; + Vec_Int_t * vOrder; + Aig_Obj_t * pObj; + int i, Counter = 0; + // mark nodes to exclude: AND with low level and CO drivers + Aig_ManCleanMarkA( pAig ); + Aig_ManForEachNode( pAig, pObj, i ) + if ( Aig_ObjLevel(pObj) > 3 ) + pObj->fMarkA = 1; + Aig_ManForEachCo( pAig, pObj, i ) + Aig_ObjFanin0(pObj)->fMarkA = 0; + + // collect nodes in the order + vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) ); + Aig_ManIncrementTravId( pAig ); + Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); +// Aig_ManForEachCo( pAig, pObj, i ) + Saig_ManForEachLi( pAig, pObj, i ) + { + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); + Llb_Nonlin4FindOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter ); + } + Aig_ManForEachCi( pAig, pObj, i ) + if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); + Aig_ManCleanMarkA( pAig ); + Vec_IntFreeP( &vNodes ); +// assert( Counter == Aig_ManObjNum(pAig) - 1 ); + +/* + Saig_ManForEachPi( pAig, pObj, i ) + printf( "pi%d ", Llb_ObjBddVar(vOrder, pObj) ); + printf( "\n" ); + Saig_ManForEachLo( pAig, pObj, i ) + printf( "lo%d ", Llb_ObjBddVar(vOrder, pObj) ); + printf( "\n" ); + Saig_ManForEachPo( pAig, pObj, i ) + printf( "po%d ", Llb_ObjBddVar(vOrder, pObj) ); + printf( "\n" ); + Saig_ManForEachLi( pAig, pObj, i ) + printf( "li%d ", Llb_ObjBddVar(vOrder, pObj) ); + printf( "\n" ); + Aig_ManForEachNode( pAig, pObj, i ) + printf( "n%d ", Llb_ObjBddVar(vOrder, pObj) ); + printf( "\n" ); +*/ + if ( pCounter ) + *pCounter = Counter; + return vOrder; +} + +/**Function************************************************************* + + Synopsis [Derives BDDs for the partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_Nonlin4FindPartitions_rec( DdManager * dd, Aig_Obj_t * pObj, Vec_Int_t * vOrder, Vec_Ptr_t * vRoots ) +{ + DdNode * bBdd, * bBdd0, * bBdd1, * bPart, * vVar; + if ( Aig_ObjIsConst1(pObj) ) + return Cudd_ReadOne(dd); + if ( Aig_ObjIsCi(pObj) ) + return Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + if ( pObj->pData ) + return (DdNode *)pObj->pData; + if ( Aig_ObjIsCo(pObj) ) + { + bBdd0 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) ); + bPart = Cudd_bddXnor( dd, Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ), bBdd0 ); Cudd_Ref( bPart ); + Vec_PtrPush( vRoots, bPart ); + return NULL; + } + bBdd0 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin1(pObj), vOrder, vRoots), Aig_ObjFaninC1(pObj) ); + bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bBdd ); + if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) + { + vVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + bPart = Cudd_bddXnor( dd, vVar, bBdd ); Cudd_Ref( bPart ); + Vec_PtrPush( vRoots, bPart ); + Cudd_RecursiveDeref( dd, bBdd ); + bBdd = vVar; Cudd_Ref( vVar ); + } + pObj->pData = bBdd; + return bBdd; +} + +/**Function************************************************************* + + Synopsis [Derives BDDs for the partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_Nonlin4FindPartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fOutputs ) +{ + Vec_Ptr_t * vRoots; + Aig_Obj_t * pObj; + int i; + Aig_ManCleanData( pAig ); + vRoots = Vec_PtrAlloc( 100 ); + if ( fOutputs ) + { + Saig_ManForEachPo( pAig, pObj, i ) + Llb_Nonlin4FindPartitions_rec( dd, pObj, vOrder, vRoots ); + } + else + { + Saig_ManForEachLi( pAig, pObj, i ) + Llb_Nonlin4FindPartitions_rec( dd, pObj, vOrder, vRoots ); + } + Aig_ManForEachNode( pAig, pObj, i ) + if ( pObj->pData ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + return vRoots; +} + +/**Function************************************************************* + + Synopsis [Creates quantifiable variables for both types of traversal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_Nonlin4FindVars2Q( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder ) +{ + Vec_Int_t * vVars2Q; + Aig_Obj_t * pObj; + int i; + vVars2Q = Vec_IntAlloc( 0 ); + Vec_IntFill( vVars2Q, Cudd_ReadSize(dd), 1 ); + Saig_ManForEachLo( pAig, pObj, i ) + Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 ); +// Aig_ManForEachCo( pAig, pObj, i ) + Saig_ManForEachLi( pAig, pObj, i ) + Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 ); + return vVars2Q; +} + +/**Function************************************************************* + + Synopsis [Creates quantifiable variables for both types of traversal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_Nonlin4CountTerms( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, DdNode * bFunc, int fCo, int fFlop ) +{ + DdNode * bSupp; + Aig_Obj_t * pObj; + int i, Counter = 0; + bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); + if ( !fCo && !fFlop ) + { + Saig_ManForEachPi( pAig, pObj, i ) + if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) + Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) ); + } + else if ( fCo && !fFlop ) + { + Saig_ManForEachPo( pAig, pObj, i ) + if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) + Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) ); + } + else if ( !fCo && fFlop ) + { + Saig_ManForEachLo( pAig, pObj, i ) + if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) + Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) ); + } + else if ( fCo && fFlop ) + { + Saig_ManForEachLi( pAig, pObj, i ) + if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) + Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) ); + } + Cudd_RecursiveDeref( dd, bSupp ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Creates quantifiable variables for both types of traversal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4PrintGroups( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups ) +{ + DdNode * bTemp; + int i, nSuppAll, nSuppPi, nSuppPo, nSuppLi, nSuppLo, nSuppAnd; + Vec_PtrForEachEntry( DdNode *, vGroups, bTemp, i ) + { +//Extra_bddPrintSupport(dd, bTemp); printf("\n" ); + nSuppAll = Cudd_SupportSize(dd,bTemp); + nSuppPi = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 0, 0); + nSuppPo = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 1, 0); + nSuppLi = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 0, 1); + nSuppLo = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 1, 1); + nSuppAnd = nSuppAll - (nSuppPi+nSuppPo+nSuppLi+nSuppLo); + + if ( Cudd_DagSize(bTemp) <= 10 ) + continue; + + printf( "%4d : bdd =%6d supp =%3d ", i, Cudd_DagSize(bTemp), nSuppAll ); + printf( "pi =%3d ", nSuppPi ); + printf( "po =%3d ", nSuppPo ); + printf( "lo =%3d ", nSuppLo ); + printf( "li =%3d ", nSuppLi ); + printf( "and =%3d", nSuppAnd ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Creates quantifiable variables for both types of traversal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4PrintSuppProfile( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups ) +{ + Aig_Obj_t * pObj; + int i, * pSupp; + int nSuppAll = 0, nSuppPi = 0, nSuppPo = 0, nSuppLi = 0, nSuppLo = 0, nSuppAnd = 0; + + pSupp = ABC_CALLOC( int, Cudd_ReadSize(dd) ); + Extra_VectorSupportArray( dd, (DdNode **)Vec_PtrArray(vGroups), Vec_PtrSize(vGroups), pSupp ); + + Aig_ManForEachObj( pAig, pObj, i ) + { + if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) + continue; + // remove variables that do not participate + if ( pSupp[Llb_ObjBddVar(vOrder, pObj)] == 0 ) + { + if ( Aig_ObjIsNode(pObj) ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), -1 ); + continue; + } + nSuppAll++; + if ( Saig_ObjIsPi(pAig, pObj) ) + nSuppPi++; + else if ( Saig_ObjIsLo(pAig, pObj) ) + nSuppLo++; + else if ( Saig_ObjIsPo(pAig, pObj) ) + nSuppPo++; + else if ( Saig_ObjIsLi(pAig, pObj) ) + nSuppLi++; + else + nSuppAnd++; + } + ABC_FREE( pSupp ); + + printf( "Groups =%3d ", Vec_PtrSize(vGroups) ); + printf( "Variables: all =%4d ", nSuppAll ); + printf( "pi =%4d ", nSuppPi ); + printf( "po =%4d ", nSuppPo ); + printf( "lo =%4d ", nSuppLo ); + printf( "li =%4d ", nSuppLi ); + printf( "and =%4d", nSuppAnd ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4Cluster( Aig_Man_t * pAig, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int nBddMax, int fVerbose ) +{ + DdManager * dd; + Vec_Int_t * vOrder, * vVars2Q; + Vec_Ptr_t * vParts, * vGroups; + DdNode * bTemp; + int i, nVarNum; + + // create the BDD manager + vOrder = Llb_Nonlin4FindOrder( pAig, &nVarNum ); + dd = Cudd_Init( nVarNum, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); +// Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + + vVars2Q = Llb_Nonlin4FindVars2Q( dd, pAig, vOrder ); + vParts = Llb_Nonlin4FindPartitions( dd, pAig, vOrder, 0 ); + + vGroups = Llb_Nonlin4Group( dd, vParts, vVars2Q, nBddMax ); + Vec_IntFree( vVars2Q ); + + Vec_PtrForEachEntry( DdNode *, vParts, bTemp, i ) + Cudd_RecursiveDeref( dd, bTemp ); + Vec_PtrFree( vParts ); + + +// if ( fVerbose ) + Llb_Nonlin4PrintSuppProfile( dd, pAig, vOrder, vGroups ); + if ( fVerbose ) + printf( "Before reordering\n" ); + if ( fVerbose ) + Llb_Nonlin4PrintGroups( dd, pAig, vOrder, vGroups ); + +// Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); +// printf( "After reordering\n" ); +// Llb_Nonlin4PrintGroups( dd, pAig, vOrder, vGroups ); + + if ( pvOrder ) + *pvOrder = vOrder; + else + Vec_IntFree( vOrder ); + + if ( pvGroups ) + *pvGroups = vGroups; + else + { + Vec_PtrForEachEntry( DdNode *, vGroups, bTemp, i ) + Cudd_RecursiveDeref( dd, bTemp ); + Vec_PtrFree( vGroups ); + } + + if ( pdd ) + *pdd = dd; + else + Extra_StopManager( dd ); +// Cudd_Quit( dd ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb4Image.c b/src/bdd/llb/llb4Image.c new file mode 100644 index 00000000..2ba4fcfd --- /dev/null +++ b/src/bdd/llb/llb4Image.c @@ -0,0 +1,863 @@ +/**CFile**************************************************************** + + FileName [llb3Image.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Computes image using partitioned structure.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb3Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Llb_Var_t_ Llb_Var_t; +struct Llb_Var_t_ +{ + int iVar; // variable number + int nScore; // variable score + Vec_Int_t * vParts; // partitions +}; + +typedef struct Llb_Prt_t_ Llb_Prt_t; +struct Llb_Prt_t_ +{ + int iPart; // partition number + int nSize; // the number of BDD nodes + DdNode * bFunc; // the partition + Vec_Int_t * vVars; // support +}; + +typedef struct Llb_Mgr_t_ Llb_Mgr_t; +struct Llb_Mgr_t_ +{ + DdManager * dd; // working BDD manager + Vec_Int_t * vVars2Q; // variables to quantify + int nSizeMax; // maximum size of the cluster + // internal + Llb_Prt_t ** pParts; // partitions + Llb_Var_t ** pVars; // variables + int iPartFree; // next free partition + int nVars; // the number of BDD variables + int nSuppMax; // maximum support size + // temporary + int * pSupp; // temporary support storage +}; + +static inline Llb_Var_t * Llb_MgrVar( Llb_Mgr_t * p, int i ) { return p->pVars[i]; } +static inline Llb_Prt_t * Llb_MgrPart( Llb_Mgr_t * p, int i ) { return p->pParts[i]; } + +// iterator over vars +#define Llb_MgrForEachVar( p, pVar, i ) \ + for ( i = 0; (i < p->nVars) && (((pVar) = Llb_MgrVar(p, i)), 1); i++ ) if ( pVar == NULL ) {} else +// iterator over parts +#define Llb_MgrForEachPart( p, pPart, i ) \ + for ( i = 0; (i < p->iPartFree) && (((pPart) = Llb_MgrPart(p, i)), 1); i++ ) if ( pPart == NULL ) {} else + +// iterator over vars of one partition +#define Llb_PartForEachVar( p, pPart, pVar, i ) \ + for ( i = 0; (i < Vec_IntSize(pPart->vVars)) && (((pVar) = Llb_MgrVar(p, Vec_IntEntry(pPart->vVars,i))), 1); i++ ) +// iterator over parts of one variable +#define Llb_VarForEachPart( p, pVar, pPart, i ) \ + for ( i = 0; (i < Vec_IntSize(pVar->vParts)) && (((pPart) = Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,i))), 1); i++ ) + +// statistics +//abctime timeBuild, timeAndEx, timeOther; +//int nSuppMax; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Removes one variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4RemoveVar( Llb_Mgr_t * p, Llb_Var_t * pVar ) +{ + assert( p->pVars[pVar->iVar] == pVar ); + p->pVars[pVar->iVar] = NULL; + Vec_IntFree( pVar->vParts ); + ABC_FREE( pVar ); +} + +/**Function************************************************************* + + Synopsis [Removes one partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4RemovePart( Llb_Mgr_t * p, Llb_Prt_t * pPart ) +{ +//printf( "Removing %d\n", pPart->iPart ); + assert( p->pParts[pPart->iPart] == pPart ); + p->pParts[pPart->iPart] = NULL; + Vec_IntFree( pPart->vVars ); + Cudd_RecursiveDeref( p->dd, pPart->bFunc ); + ABC_FREE( pPart ); +} + +/**Function************************************************************* + + Synopsis [Create cube with singleton variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_Nonlin4CreateCube1( Llb_Mgr_t * p, Llb_Prt_t * pPart ) +{ + DdNode * bCube, * bTemp; + Llb_Var_t * pVar; + int i; + abctime TimeStop; + TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; + bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube ); + Llb_PartForEachVar( p, pPart, pVar, i ) + { + assert( Vec_IntSize(pVar->vParts) > 0 ); + if ( Vec_IntSize(pVar->vParts) != 1 ) + continue; + assert( Vec_IntEntry(pVar->vParts, 0) == pPart->iPart ); + bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Cudd_Deref( bCube ); + p->dd->TimeStop = TimeStop; + return bCube; +} + +/**Function************************************************************* + + Synopsis [Create cube of variables appearing only in two partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_Nonlin4CreateCube2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 ) +{ + DdNode * bCube, * bTemp; + Llb_Var_t * pVar; + int i; + abctime TimeStop; + TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; + bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube ); + Llb_PartForEachVar( p, pPart1, pVar, i ) + { + assert( Vec_IntSize(pVar->vParts) > 0 ); + if ( Vec_IntSize(pVar->vParts) != 2 ) + continue; + if ( (Vec_IntEntry(pVar->vParts, 0) == pPart1->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart2->iPart) || + (Vec_IntEntry(pVar->vParts, 0) == pPart2->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart1->iPart) ) + { + bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + } + Cudd_Deref( bCube ); + p->dd->TimeStop = TimeStop; + return bCube; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if partition has singleton variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_Nonlin4HasSingletonVars( Llb_Mgr_t * p, Llb_Prt_t * pPart ) +{ + Llb_Var_t * pVar; + int i; + Llb_PartForEachVar( p, pPart, pVar, i ) + if ( Vec_IntSize(pVar->vParts) == 1 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if partition has singleton variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4Print( Llb_Mgr_t * p ) +{ + Llb_Prt_t * pPart; + Llb_Var_t * pVar; + int i, k; + printf( "\n" ); + Llb_MgrForEachVar( p, pVar, i ) + { + printf( "Var %3d : ", i ); + Llb_VarForEachPart( p, pVar, pPart, k ) + printf( "%d ", pPart->iPart ); + printf( "\n" ); + } + Llb_MgrForEachPart( p, pPart, i ) + { + printf( "Part %3d : ", i ); + Llb_PartForEachVar( p, pPart, pVar, k ) + printf( "%d ", pVar->iVar ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Quantifies singles belonging to one partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_Nonlin4Quantify1( Llb_Mgr_t * p, Llb_Prt_t * pPart ) +{ + Llb_Var_t * pVar; + Llb_Prt_t * pTemp; + Vec_Ptr_t * vSingles; + DdNode * bCube, * bTemp; + int i, RetValue, nSizeNew; + // create cube to be quantified + bCube = Llb_Nonlin4CreateCube1( p, pPart ); Cudd_Ref( bCube ); +// assert( !Cudd_IsConstant(bCube) ); + // derive new function + pPart->bFunc = Cudd_bddExistAbstract( p->dd, bTemp = pPart->bFunc, bCube ); Cudd_Ref( pPart->bFunc ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bCube ); + // get support + vSingles = Vec_PtrAlloc( 0 ); + nSizeNew = Cudd_DagSize(pPart->bFunc); + Extra_SupportArray( p->dd, pPart->bFunc, p->pSupp ); + Llb_PartForEachVar( p, pPart, pVar, i ) + if ( p->pSupp[pVar->iVar] ) + { + assert( Vec_IntSize(pVar->vParts) > 1 ); + pVar->nScore -= pPart->nSize - nSizeNew; + } + else + { + RetValue = Vec_IntRemove( pVar->vParts, pPart->iPart ); + assert( RetValue ); + pVar->nScore -= pPart->nSize; + if ( Vec_IntSize(pVar->vParts) == 0 ) + Llb_Nonlin4RemoveVar( p, pVar ); + else if ( Vec_IntSize(pVar->vParts) == 1 ) + Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); + } + + // update partition + pPart->nSize = nSizeNew; + Vec_IntClear( pPart->vVars ); + for ( i = 0; i < p->nVars; i++ ) + if ( p->pSupp[i] && Vec_IntEntry(p->vVars2Q, i) ) + Vec_IntPush( pPart->vVars, i ); + // remove other variables + Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i ) + Llb_Nonlin4Quantify1( p, pTemp ); + Vec_PtrFree( vSingles ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Quantifies singles belonging to one partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_Nonlin4Quantify2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 ) +{ + int fVerbose = 0; + Llb_Var_t * pVar; + Llb_Prt_t * pTemp; + Vec_Ptr_t * vSingles; + DdNode * bCube, * bFunc; + int i, RetValue, nSuppSize; +// int iPart1 = pPart1->iPart; +// int iPart2 = pPart2->iPart; + int liveBeg, liveEnd; + + // create cube to be quantified + bCube = Llb_Nonlin4CreateCube2( p, pPart1, pPart2 ); Cudd_Ref( bCube ); + +//printf( "Quantifying " ); Extra_bddPrintSupport( p->dd, bCube ); printf( "\n" ); + +if ( fVerbose ) +{ +printf( "\n" ); +printf( "\n" ); +Llb_Nonlin4Print( p ); +printf( "Conjoining partitions %d and %d.\n", pPart1->iPart, pPart2->iPart ); +Extra_bddPrintSupport( p->dd, bCube ); printf( "\n" ); +} +liveBeg = p->dd->keys - p->dd->dead; + bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube ); +liveEnd = p->dd->keys - p->dd->dead; +//printf( "%d ", liveEnd-liveBeg ); + + if ( bFunc == NULL ) + { + Cudd_RecursiveDeref( p->dd, bCube ); + return 0; + } + Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( p->dd, bCube ); + +//printf( "Creating part %d ", p->iPartFree ); Extra_bddPrintSupport( p->dd, bFunc ); printf( "\n" ); + +//printf( "Creating %d\n", p->iPartFree ); + + // create new partition + pTemp = p->pParts[p->iPartFree] = ABC_CALLOC( Llb_Prt_t, 1 ); + pTemp->iPart = p->iPartFree++; + pTemp->nSize = Cudd_DagSize(bFunc); + pTemp->bFunc = bFunc; + pTemp->vVars = Vec_IntAlloc( 8 ); + // update variables + Llb_PartForEachVar( p, pPart1, pVar, i ) + { + RetValue = Vec_IntRemove( pVar->vParts, pPart1->iPart ); + assert( RetValue ); + pVar->nScore -= pPart1->nSize; + } + // update variables + Llb_PartForEachVar( p, pPart2, pVar, i ) + { + RetValue = Vec_IntRemove( pVar->vParts, pPart2->iPart ); + assert( RetValue ); + pVar->nScore -= pPart2->nSize; + } + // add variables to the new partition + nSuppSize = 0; + Extra_SupportArray( p->dd, bFunc, p->pSupp ); + for ( i = 0; i < p->nVars; i++ ) + { + nSuppSize += p->pSupp[i]; + if ( p->pSupp[i] && Vec_IntEntry(p->vVars2Q, i) ) + { + pVar = Llb_MgrVar( p, i ); + pVar->nScore += pTemp->nSize; + Vec_IntPush( pVar->vParts, pTemp->iPart ); + Vec_IntPush( pTemp->vVars, i ); + } + } + p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize ); + // remove variables and collect partitions with singleton variables + vSingles = Vec_PtrAlloc( 0 ); + Llb_PartForEachVar( p, pPart1, pVar, i ) + { + if ( Vec_IntSize(pVar->vParts) == 0 ) + Llb_Nonlin4RemoveVar( p, pVar ); + else if ( Vec_IntSize(pVar->vParts) == 1 ) + { + if ( fVerbose ) + printf( "Adding partition %d because of var %d.\n", + Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar ); + Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); + } + } + Llb_PartForEachVar( p, pPart2, pVar, i ) + { + if ( pVar == NULL ) + continue; + if ( Vec_IntSize(pVar->vParts) == 0 ) + Llb_Nonlin4RemoveVar( p, pVar ); + else if ( Vec_IntSize(pVar->vParts) == 1 ) + { + if ( fVerbose ) + printf( "Adding partition %d because of var %d.\n", + Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar ); + Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); + } + } + // remove partitions + Llb_Nonlin4RemovePart( p, pPart1 ); + Llb_Nonlin4RemovePart( p, pPart2 ); + // remove other variables +if ( fVerbose ) +Llb_Nonlin4Print( p ); + Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i ) + { +if ( fVerbose ) +printf( "Updating partitiong %d with singlton vars.\n", pTemp->iPart ); + Llb_Nonlin4Quantify1( p, pTemp ); + } +if ( fVerbose ) +Llb_Nonlin4Print( p ); + Vec_PtrFree( vSingles ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4CutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Saig_ObjIsLi(p, pObj) ) + { + Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); + return; + } + if ( Aig_ObjIsConst1(pObj) ) + return; + assert( Aig_ObjIsNode(pObj) ); + Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); + Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_Nonlin4CutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + // mark the lower cut with the traversal ID + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // count the upper cut + vNodes = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) + Llb_Nonlin4CutNodes_rec( p, pObj, vNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Starts non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4AddPair( Llb_Mgr_t * p, int iPart, int iVar ) +{ + if ( p->pVars[iVar] == NULL ) + { + p->pVars[iVar] = ABC_CALLOC( Llb_Var_t, 1 ); + p->pVars[iVar]->iVar = iVar; + p->pVars[iVar]->nScore = 0; + p->pVars[iVar]->vParts = Vec_IntAlloc( 8 ); + } + Vec_IntPush( p->pVars[iVar]->vParts, iPart ); + Vec_IntPush( p->pParts[iPart]->vVars, iVar ); +} + +/**Function************************************************************* + + Synopsis [Starts non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4AddPartition( Llb_Mgr_t * p, int i, DdNode * bFunc ) +{ + int k, nSuppSize; + assert( !Cudd_IsConstant(bFunc) ); +//printf( "Creating init %d\n", i ); + // create partition + p->pParts[i] = ABC_CALLOC( Llb_Prt_t, 1 ); + p->pParts[i]->iPart = i; + p->pParts[i]->bFunc = bFunc; Cudd_Ref( bFunc ); + p->pParts[i]->vVars = Vec_IntAlloc( 8 ); + // add support dependencies + nSuppSize = 0; + Extra_SupportArray( p->dd, bFunc, p->pSupp ); + for ( k = 0; k < p->nVars; k++ ) + { + nSuppSize += p->pSupp[k]; + if ( p->pSupp[k] && Vec_IntEntry(p->vVars2Q, k) ) + Llb_Nonlin4AddPair( p, i, k ); + } + p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize ); +} + +/**Function************************************************************* + + Synopsis [Checks that each var appears in at least one partition.] + + Description [] + + SideEffects [] + + SeeAlso [] +**********************************************************************/ +void Llb_Nonlin4CheckVars( Llb_Mgr_t * p ) +{ + Llb_Var_t * pVar; + int i; + Llb_MgrForEachVar( p, pVar, i ) + assert( Vec_IntSize(pVar->vParts) > 1 ); +} + +/**Function************************************************************* + + Synopsis [Find next partition to quantify] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_Nonlin4NextPartitions( Llb_Mgr_t * p, Llb_Prt_t ** ppPart1, Llb_Prt_t ** ppPart2 ) +{ + Llb_Var_t * pVar, * pVarBest = NULL; + Llb_Prt_t * pPart, * pPart1Best = NULL, * pPart2Best = NULL; + int i; + Llb_Nonlin4CheckVars( p ); + // find variable with minimum score + Llb_MgrForEachVar( p, pVar, i ) + { + if ( p->nSizeMax && pVar->nScore > p->nSizeMax ) + continue; +// if ( pVarBest == NULL || Vec_IntSize(pVarBest->vParts) * pVarBest->nScore > Vec_IntSize(pVar->vParts) * pVar->nScore ) + if ( pVarBest == NULL || pVarBest->nScore > pVar->nScore ) + pVarBest = pVar; +// printf( "%d ", pVar->nScore ); + } +//printf( "\n" ); + if ( pVarBest == NULL ) + return 0; + // find two partitions with minimum size + Llb_VarForEachPart( p, pVarBest, pPart, i ) + { + if ( pPart1Best == NULL ) + pPart1Best = pPart; + else if ( pPart2Best == NULL ) + pPart2Best = pPart; + else if ( pPart1Best->nSize > pPart->nSize || pPart2Best->nSize > pPart->nSize ) + { + if ( pPart1Best->nSize > pPart2Best->nSize ) + pPart1Best = pPart; + else + pPart2Best = pPart; + } + } +//printf( "Selecting %d and parts %d and %d\n", pVarBest->iVar, pPart1Best->nSize, pPart2Best->nSize ); +//Extra_bddPrintSupport( p->dd, pPart1Best->bFunc ); printf( "\n" ); +//Extra_bddPrintSupport( p->dd, pPart2Best->bFunc ); printf( "\n" ); + + *ppPart1 = pPart1Best; + *ppPart2 = pPart2Best; + return 1; +} + +/**Function************************************************************* + + Synopsis [Recomputes scores after variable reordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4RecomputeScores( Llb_Mgr_t * p ) +{ + Llb_Prt_t * pPart; + Llb_Var_t * pVar; + int i, k; + Llb_MgrForEachPart( p, pPart, i ) + pPart->nSize = Cudd_DagSize(pPart->bFunc); + Llb_MgrForEachVar( p, pVar, i ) + { + pVar->nScore = 0; + Llb_VarForEachPart( p, pVar, pPart, k ) + pVar->nScore += pPart->nSize; + } +} + +/**Function************************************************************* + + Synopsis [Recomputes scores after variable reordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4VerifyScores( Llb_Mgr_t * p ) +{ + Llb_Prt_t * pPart; + Llb_Var_t * pVar; + int i, k, nScore; + Llb_MgrForEachPart( p, pPart, i ) + assert( pPart->nSize == Cudd_DagSize(pPart->bFunc) ); + Llb_MgrForEachVar( p, pVar, i ) + { + nScore = 0; + Llb_VarForEachPart( p, pVar, pPart, k ) + nScore += pPart->nSize; + assert( nScore == pVar->nScore ); + } +} + +/**Function************************************************************* + + Synopsis [Starts non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Mgr_t * Llb_Nonlin4Alloc( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q, int nSizeMax ) +{ + Llb_Mgr_t * p; + DdNode * bFunc; + int i; + p = ABC_CALLOC( Llb_Mgr_t, 1 ); + p->dd = dd; + p->nSizeMax = nSizeMax; + p->vVars2Q = vVars2Q; + p->nVars = Cudd_ReadSize(dd); + p->iPartFree = Vec_PtrSize(vParts); + p->pVars = ABC_CALLOC( Llb_Var_t *, p->nVars ); + p->pParts = ABC_CALLOC( Llb_Prt_t *, 2 * p->iPartFree + 2 ); + p->pSupp = ABC_ALLOC( int, Cudd_ReadSize(dd) ); + // add pairs (refs are consumed inside) + Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i ) + Llb_Nonlin4AddPartition( p, i, bFunc ); + // add partition + if ( bCurrent ) + Llb_Nonlin4AddPartition( p, p->iPartFree++, bCurrent ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4Free( Llb_Mgr_t * p ) +{ + Llb_Prt_t * pPart; + Llb_Var_t * pVar; + int i; + Llb_MgrForEachVar( p, pVar, i ) + Llb_Nonlin4RemoveVar( p, pVar ); + Llb_MgrForEachPart( p, pPart, i ) + Llb_Nonlin4RemovePart( p, pPart ); + ABC_FREE( p->pVars ); + ABC_FREE( p->pParts ); + ABC_FREE( p->pSupp ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_Nonlin4Image( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q ) +{ + Llb_Prt_t * pPart, * pPart1, * pPart2; + Llb_Mgr_t * p; + DdNode * bFunc, * bTemp; + int i, nReorders; + // start the manager + p = Llb_Nonlin4Alloc( dd, vParts, bCurrent, vVars2Q, 0 ); + // remove singles + Llb_MgrForEachPart( p, pPart, i ) + if ( Llb_Nonlin4HasSingletonVars(p, pPart) ) + Llb_Nonlin4Quantify1( p, pPart ); + // compute scores + Llb_Nonlin4RecomputeScores( p ); + // iteratively quantify variables + while ( Llb_Nonlin4NextPartitions(p, &pPart1, &pPart2) ) + { + nReorders = Cudd_ReadReorderings(dd); + if ( !Llb_Nonlin4Quantify2( p, pPart1, pPart2 ) ) + { + Llb_Nonlin4Free( p ); + return NULL; + } + if ( nReorders < Cudd_ReadReorderings(dd) ) + Llb_Nonlin4RecomputeScores( p ); +// else +// Llb_Nonlin4VerifyScores( p ); + } + // load partitions + bFunc = Cudd_ReadOne(p->dd); Cudd_Ref( bFunc ); + Llb_MgrForEachPart( p, pPart, i ) + { + bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } +// nSuppMax = p->nSuppMax; + Llb_Nonlin4Free( p ); +//printf( "\n" ); + // return + Cudd_Deref( bFunc ); + return bFunc; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_Nonlin4Group( DdManager * dd, Vec_Ptr_t * vParts, Vec_Int_t * vVars2Q, int nSizeMax ) +{ + Vec_Ptr_t * vGroups; + Llb_Prt_t * pPart, * pPart1, * pPart2; + Llb_Mgr_t * p; + int i, nReorders;//, clk = Abc_Clock(); + // start the manager + p = Llb_Nonlin4Alloc( dd, vParts, NULL, vVars2Q, nSizeMax ); + // remove singles + Llb_MgrForEachPart( p, pPart, i ) + if ( Llb_Nonlin4HasSingletonVars(p, pPart) ) + Llb_Nonlin4Quantify1( p, pPart ); + // compute scores + Llb_Nonlin4RecomputeScores( p ); + // iteratively quantify variables + while ( Llb_Nonlin4NextPartitions(p, &pPart1, &pPart2) ) + { + nReorders = Cudd_ReadReorderings(dd); + if ( !Llb_Nonlin4Quantify2( p, pPart1, pPart2 ) ) + { + Llb_Nonlin4Free( p ); + return NULL; + } + if ( nReorders < Cudd_ReadReorderings(dd) ) + Llb_Nonlin4RecomputeScores( p ); +// else +// Llb_Nonlin4VerifyScores( p ); + } + // load partitions + vGroups = Vec_PtrAlloc( 1000 ); + Llb_MgrForEachPart( p, pPart, i ) + { +//printf( "Iteration %d ", pPart->iPart ); + if ( Cudd_IsConstant(pPart->bFunc) ) + { +//printf( "Constant\n" ); + assert( !Cudd_IsComplement(pPart->bFunc) ); + continue; + } +//printf( "\n" ); + Vec_PtrPush( vGroups, pPart->bFunc ); + Cudd_Ref( pPart->bFunc ); +//printf( "Part %d ", pPart->iPart ); +//Extra_bddPrintSupport( p->dd, pPart->bFunc ); printf( "\n" ); + } + Llb_Nonlin4Free( p ); +//Abc_PrintTime( 1, "Reparametrization time", Abc_Clock() - clk ); + return vGroups; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb4Map.c b/src/bdd/llb/llb4Map.c new file mode 100644 index 00000000..4487ce25 --- /dev/null +++ b/src/bdd/llb/llb4Map.c @@ -0,0 +1,123 @@ +/**CFile**************************************************************** + + FileName [llb2Map.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Non-linear quantification scheduling.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Map.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" +#include "base/abc/abc.h" +#include "map/if/if.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns internal nodes used in the mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_AigMap( Aig_Man_t * pAig, int nLutSize, int nLutMin ) +{ + extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); + extern If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); + extern void Gia_ManSetIfParsDefault( void * pPars ); + If_Par_t Pars, * pPars = &Pars; + If_Man_t * pIfMan; + If_Obj_t * pAnd; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode; + Vec_Int_t * vNodes; + Aig_Obj_t * pObj; + int i; + + // create ABC network + pNtk = Abc_NtkFromAigPhase( pAig ); + assert( Abc_NtkIsStrash(pNtk) ); + + // derive mapping parameters + Gia_ManSetIfParsDefault( pPars ); + pPars->nLutSize = nLutSize; + + // get timing information + pPars->pTimesArr = Abc_NtkGetCiArrivalFloats(pNtk); + pPars->pTimesReq = Abc_NtkGetCoRequiredFloats(pNtk); + + // perform LUT mapping + pIfMan = Abc_NtkToIf( pNtk, pPars ); + if ( pIfMan == NULL ) + { + Abc_NtkDelete( pNtk ); + return NULL; + } + if ( !If_ManPerformMapping( pIfMan ) ) + { + Abc_NtkDelete( pNtk ); + If_ManStop( pIfMan ); + return NULL; + } + + // mark nodes in the AIG used in the mapping + Aig_ManCleanMarkA( pAig ); + Aig_ManForEachNode( pAig, pObj, i ) + { + pNode = (Abc_Obj_t *)pObj->pData; + if ( pNode == NULL ) + continue; + pAnd = (If_Obj_t *)pNode->pCopy; + if ( pAnd == NULL ) + continue; + if ( pAnd->nRefs > 0 && (int)If_ObjCutBest(pAnd)->nLeaves >= nLutMin ) + pObj->fMarkA = 1; + } + Abc_NtkDelete( pNtk ); + If_ManStop( pIfMan ); + + // unmark flop drivers + Saig_ManForEachLi( pAig, pObj, i ) + Aig_ObjFanin0(pObj)->fMarkA = 0; + + // collect mapping + vNodes = Vec_IntAlloc( 100 ); + Aig_ManForEachNode( pAig, pObj, i ) + if ( pObj->fMarkA ) + Vec_IntPush( vNodes, Aig_ObjId(pObj) ); + Aig_ManCleanMarkA( pAig ); + return vNodes; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb4Nonlin.c b/src/bdd/llb/llb4Nonlin.c new file mode 100644 index 00000000..a9421358 --- /dev/null +++ b/src/bdd/llb/llb4Nonlin.c @@ -0,0 +1,1185 @@ +/**CFile**************************************************************** + + FileName [llb2Nonlin.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Non-linear quantification scheduling.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Nonlin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" +#include "base/abc/abc.h" +#include "aig/gia/giaAig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Llb_Mnx_t_ Llb_Mnx_t; +struct Llb_Mnx_t_ +{ + // user info + Aig_Man_t * pAig; // AIG manager + Gia_ParLlb_t * pPars; // parameters + + // intermediate BDDs + DdManager * dd; // BDD manager + DdNode * bBad; // bad states in terms of CIs + DdNode * bReached; // reached states + DdNode * bCurrent; // from states + DdNode * bNext; // to states + Vec_Ptr_t * vRings; // onion rings in ddR + Vec_Ptr_t * vRoots; // BDDs for partitions + + // structural info + Vec_Int_t * vOrder; // for each object ID, its BDD variable number or -1 + Vec_Int_t * vVars2Q; // 1 if variable is quantifiable; 0 othervise + + abctime timeImage; + abctime timeRemap; + abctime timeReo; + abctime timeOther; + abctime timeTotal; +}; + +//extern int timeBuild, timeAndEx, timeOther; +//extern int nSuppMax; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes bad in working manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_Nonlin4ComputeBad( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder ) +{ + Vec_Ptr_t * vNodes; + DdNode * bBdd, * bBdd0, * bBdd1, * bTemp, * bResult, * bCube; + Aig_Obj_t * pObj; + int i; + Aig_ManCleanData( pAig ); + // assign elementary variables + Aig_ManConst1(pAig)->pData = Cudd_ReadOne(dd); + Aig_ManForEachCi( pAig, pObj, i ) + pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + // compute internal nodes + vNodes = Aig_ManDfsNodes( pAig, (Aig_Obj_t **)Vec_PtrArray(pAig->vCos), Saig_ManPoNum(pAig) ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) ) + continue; + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); + bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); + if ( bBdd == NULL ) + { + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + if ( Aig_ObjIsNode(pObj) && pObj->pData != NULL ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + Vec_PtrFree( vNodes ); + return NULL; + } + Cudd_Ref( bBdd ); + pObj->pData = bBdd; + } + // quantify PIs of each PO + bResult = Cudd_ReadLogicZero( dd ); Cudd_Ref( bResult ); + Saig_ManForEachPo( pAig, pObj, i ) + { + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bResult = Cudd_bddOr( dd, bTemp = bResult, bBdd0 ); + if ( bResult == NULL ) + { + Cudd_RecursiveDeref( dd, bTemp ); + break; + } + Cudd_Ref( bResult ); + Cudd_RecursiveDeref( dd, bTemp ); + } + // deref + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + if ( Aig_ObjIsNode(pObj) && pObj->pData != NULL ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + Vec_PtrFree( vNodes ); + if ( bResult ) + { + bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube ); + Saig_ManForEachPi( pAig, pObj, i ) + { + bCube = Cudd_bddAnd( dd, bTemp = bCube, (DdNode *)pObj->pData ); + if ( bCube == NULL ) + { + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bResult ); + bResult = NULL; + break; + } + Cudd_Ref( bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + } + if ( bResult != NULL ) + { + bResult = Cudd_bddExistAbstract( dd, bTemp = bResult, bCube ); Cudd_Ref( bResult ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + Cudd_Deref( bResult ); + } + } +//if ( bResult ) +//printf( "Bad state = %d.\n", Cudd_DagSize(bResult) ); + return bResult; +} + +/**Function************************************************************* + + Synopsis [Derives BDDs for the partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_Nonlin4DerivePartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder ) +{ + Vec_Ptr_t * vRoots; + Aig_Obj_t * pObj; + DdNode * bBdd, * bBdd0, * bBdd1, * bPart; + int i; + Aig_ManCleanData( pAig ); + // assign elementary variables + Aig_ManConst1(pAig)->pData = Cudd_ReadOne(dd); + Aig_ManForEachCi( pAig, pObj, i ) + pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + Aig_ManForEachNode( pAig, pObj, i ) + if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) + { + pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + Cudd_Ref( (DdNode *)pObj->pData ); + } + Saig_ManForEachLi( pAig, pObj, i ) + pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + // compute intermediate BDDs + vRoots = Vec_PtrAlloc( 100 ); + Aig_ManForEachNode( pAig, pObj, i ) + { + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); + bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); + if ( bBdd == NULL ) + goto finish; + Cudd_Ref( bBdd ); + if ( pObj->pData == NULL ) + { + pObj->pData = bBdd; + continue; + } + // create new partition + bPart = Cudd_bddXnor( dd, (DdNode *)pObj->pData, bBdd ); + if ( bPart == NULL ) + goto finish; + Cudd_Ref( bPart ); + Cudd_RecursiveDeref( dd, bBdd ); + Vec_PtrPush( vRoots, bPart ); +//printf( "%d ", Cudd_DagSize(bPart) ); + } + // compute register output BDDs + Saig_ManForEachLi( pAig, pObj, i ) + { + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bPart = Cudd_bddXnor( dd, (DdNode *)pObj->pData, bBdd0 ); + if ( bPart == NULL ) + goto finish; + Cudd_Ref( bPart ); + Vec_PtrPush( vRoots, bPart ); +//printf( "%d ", Cudd_DagSize(bPart) ); + } +//printf( "\n" ); + Aig_ManForEachNode( pAig, pObj, i ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + return vRoots; + // early termination +finish: + Aig_ManForEachNode( pAig, pObj, i ) + if ( pObj->pData ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + Vec_PtrForEachEntry( DdNode *, vRoots, bPart, i ) + Cudd_RecursiveDeref( dd, bPart ); + Vec_PtrFree( vRoots ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Find simple variable ordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_Nonlin4CreateOrderSimple( Aig_Man_t * pAig ) +{ + Vec_Int_t * vOrder; + Aig_Obj_t * pObj; + int i, Counter = 0; + vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) ); + Aig_ManForEachCi( pAig, pObj, i ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); + Saig_ManForEachLi( pAig, pObj, i ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); + return vOrder; +} + +/**Function************************************************************* + + Synopsis [Find good static variable ordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4CreateOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter ) +{ + Aig_Obj_t * pFanin0, * pFanin1; + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return; + Aig_ObjSetTravIdCurrent( pAig, pObj ); + assert( Llb_ObjBddVar(vOrder, pObj) < 0 ); + if ( Aig_ObjIsCi(pObj) ) + { +// if ( Saig_ObjIsLo(pAig, pObj) ) +// Vec_IntWriteEntry( vOrder, Aig_ObjId(Saig_ObjLoToLi(pAig, pObj)), (*pCounter)++ ); + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); + return; + } + // try fanins with higher level first + pFanin0 = Aig_ObjFanin0(pObj); + pFanin1 = Aig_ObjFanin1(pObj); +// if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) ) + if ( pFanin0->Level > pFanin1->Level ) + { + Llb_Nonlin4CreateOrder_rec( pAig, pFanin0, vOrder, pCounter ); + Llb_Nonlin4CreateOrder_rec( pAig, pFanin1, vOrder, pCounter ); + } + else + { + Llb_Nonlin4CreateOrder_rec( pAig, pFanin1, vOrder, pCounter ); + Llb_Nonlin4CreateOrder_rec( pAig, pFanin0, vOrder, pCounter ); + } + if ( pObj->fMarkA ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); +} + +/**Function************************************************************* + + Synopsis [Collect nodes with the given fanout count.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_Nonlin4CollectHighRefNodes( Aig_Man_t * pAig, int nFans ) +{ + Vec_Int_t * vNodes; + Aig_Obj_t * pObj; + int i; + Aig_ManCleanMarkA( pAig ); + Aig_ManForEachNode( pAig, pObj, i ) + if ( Aig_ObjRefs(pObj) >= nFans ) + pObj->fMarkA = 1; + // unmark flop drivers + Saig_ManForEachLi( pAig, pObj, i ) + Aig_ObjFanin0(pObj)->fMarkA = 0; + // collect mapping + vNodes = Vec_IntAlloc( 100 ); + Aig_ManForEachNode( pAig, pObj, i ) + if ( pObj->fMarkA ) + Vec_IntPush( vNodes, Aig_ObjId(pObj) ); + Aig_ManCleanMarkA( pAig ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Find good static variable ordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_Nonlin4CreateOrder( Aig_Man_t * pAig ) +{ + Vec_Int_t * vNodes = NULL; + Vec_Int_t * vOrder; + Aig_Obj_t * pObj; + int i, Counter = 0; +/* + // mark internal nodes to be used + Aig_ManCleanMarkA( pAig ); + vNodes = Llb_Nonlin4CollectHighRefNodes( pAig, 4 ); + Aig_ManForEachObjVec( vNodes, pAig, pObj, i ) + pObj->fMarkA = 1; +printf( "Techmapping added %d pivots.\n", Vec_IntSize(vNodes) ); +*/ + // collect nodes in the order + vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) ); + Aig_ManIncrementTravId( pAig ); + Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); + Saig_ManForEachLi( pAig, pObj, i ) + { + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); + Llb_Nonlin4CreateOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter ); + } + Aig_ManForEachCi( pAig, pObj, i ) + if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) + { +// if ( Saig_ObjIsLo(pAig, pObj) ) +// Vec_IntWriteEntry( vOrder, Aig_ObjId(Saig_ObjLoToLi(pAig, pObj)), Counter++ ); + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); + } + assert( Counter <= Aig_ManCiNum(pAig) + Aig_ManRegNum(pAig) + (vNodes?Vec_IntSize(vNodes):0) ); + Aig_ManCleanMarkA( pAig ); + Vec_IntFreeP( &vNodes ); + return vOrder; +} + + +/**Function************************************************************* + + Synopsis [Creates quantifiable varaibles for both types of traversal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_Nonlin4CreateVars2Q( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fBackward ) +{ + Vec_Int_t * vVars2Q; + Aig_Obj_t * pObjLi, * pObjLo; + int i; + vVars2Q = Vec_IntAlloc( 0 ); + Vec_IntFill( vVars2Q, Cudd_ReadSize(dd), 1 ); + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, fBackward ? pObjLo : pObjLi), 0 ); + return vVars2Q; +} + +/**Function************************************************************* + + Synopsis [Compute initial state in terms of current state variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4SetupVarMap( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder ) +{ + DdNode ** pVarsX, ** pVarsY; + Aig_Obj_t * pObjLo, * pObjLi; + int i; + pVarsX = ABC_ALLOC( DdNode *, Cudd_ReadSize(dd) ); + pVarsY = ABC_ALLOC( DdNode *, Cudd_ReadSize(dd) ); + Saig_ManForEachLiLo( pAig, pObjLo, pObjLi, i ) + { + assert( Llb_ObjBddVar(vOrder, pObjLo) >= 0 ); + assert( Llb_ObjBddVar(vOrder, pObjLi) >= 0 ); + pVarsX[i] = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLo) ); + pVarsY[i] = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLi) ); + } + Cudd_SetVarMap( dd, pVarsX, pVarsY, Aig_ManRegNum(pAig) ); + ABC_FREE( pVarsX ); + ABC_FREE( pVarsY ); +} + +/**Function************************************************************* + + Synopsis [Compute initial state in terms of current state variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_Nonlin4ComputeInitState( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fBackward ) +{ + Aig_Obj_t * pObjLi, * pObjLo; + DdNode * bRes, * bVar, * bTemp; + int i; + abctime TimeStop; + TimeStop = dd->TimeStop; dd->TimeStop = 0; + bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + { + bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, fBackward? pObjLi : pObjLo) ); + bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bRes ); + dd->TimeStop = TimeStop; + return bRes; +} + +/**Function************************************************************* + + Synopsis [Compute initial state in terms of current state variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_Nonlin4ComputeCube( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, char * pValues, int Flag ) +{ + Aig_Obj_t * pObjLo, * pObjLi, * pObjTemp; + DdNode * bRes, * bVar, * bTemp; + int i; + abctime TimeStop; + TimeStop = dd->TimeStop; dd->TimeStop = 0; + bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + { + if ( Flag ) + pObjTemp = pObjLo, pObjLo = pObjLi, pObjLi = pObjTemp; + // get the correspoding flop input variable + bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLi) ); + if ( pValues[Llb_ObjBddVar(vOrder, pObjLo)] != 1 ) + bVar = Cudd_Not(bVar); + // create cube + bRes = Cudd_bddAnd( dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bRes ); + dd->TimeStop = TimeStop; + return bRes; +} + +/**Function************************************************************* + + Synopsis [Compute initial state in terms of current state variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4RecordState( Aig_Man_t * pAig, Vec_Int_t * vOrder, unsigned * pState, char * pValues, int fBackward ) +{ + Aig_Obj_t * pObjLo, * pObjLi; + int i; + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + if ( pValues[Llb_ObjBddVar(vOrder, fBackward? pObjLi : pObjLo)] == 1 ) + Abc_InfoSetBit( pState, i ); +} + +/**Function************************************************************* + + Synopsis [Multiply every partition by the cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_Nonlin4Multiply( DdManager * dd, DdNode * bCube, Vec_Ptr_t * vParts ) +{ + Vec_Ptr_t * vNew; + DdNode * bTemp, * bFunc; + int i; + vNew = Vec_PtrAlloc( Vec_PtrSize(vParts) ); + Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i ) + { + bTemp = Cudd_bddAnd( dd, bFunc, bCube ); Cudd_Ref( bTemp ); + Vec_PtrPush( vNew, bTemp ); + } + return vNew; +} + +/**Function************************************************************* + + Synopsis [Multiply every partition by the cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4Deref( DdManager * dd, Vec_Ptr_t * vParts ) +{ + DdNode * bFunc; + int i; + Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i ) + Cudd_RecursiveDeref( dd, bFunc ); + Vec_PtrFree( vParts ); +} + +/**Function************************************************************* + + Synopsis [Derives counter-example by backward reachability.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_Nonlin4DeriveCex( Llb_Mnx_t * p, int fBackward, int fVerbose ) +{ + Vec_Int_t * vVars2Q; + Vec_Ptr_t * vStates, * vRootsNew; + Aig_Obj_t * pObj; + DdNode * bState = NULL, * bImage, * bOneCube, * bRing; + int i, v, RetValue;//, clk = Abc_Clock(); + char * pValues; + assert( Vec_PtrSize(p->vRings) > 0 ); + // disable the timeout + p->dd->TimeStop = 0; + + // start the state set + vStates = Vec_PtrAllocSimInfo( Vec_PtrSize(p->vRings), Abc_BitWordNum(Aig_ManRegNum(p->pAig)) ); + Vec_PtrCleanSimInfo( vStates, 0, Abc_BitWordNum(Aig_ManRegNum(p->pAig)) ); + if ( fBackward ) + Vec_PtrReverseOrder( vStates ); + + // get the last cube + pValues = ABC_ALLOC( char, Cudd_ReadSize(p->dd) ); + bOneCube = Cudd_bddIntersect( p->dd, (DdNode *)Vec_PtrEntryLast(p->vRings), p->bBad ); Cudd_Ref( bOneCube ); + RetValue = Cudd_bddPickOneCube( p->dd, bOneCube, pValues ); + Cudd_RecursiveDeref( p->dd, bOneCube ); + assert( RetValue ); + + // record the cube + Llb_Nonlin4RecordState( p->pAig, p->vOrder, (unsigned *)Vec_PtrEntryLast(vStates), pValues, fBackward ); + + // write state in terms of NS variables + if ( Vec_PtrSize(p->vRings) > 1 ) + { + bState = Llb_Nonlin4ComputeCube( p->dd, p->pAig, p->vOrder, pValues, fBackward ); Cudd_Ref( bState ); + } + // perform backward analysis + vVars2Q = Llb_Nonlin4CreateVars2Q( p->dd, p->pAig, p->vOrder, !fBackward ); + Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v ) + { + if ( v == Vec_PtrSize(p->vRings) - 1 ) + continue; + + // preprocess partitions + vRootsNew = Llb_Nonlin4Multiply( p->dd, bState, p->vRoots ); + Cudd_RecursiveDeref( p->dd, bState ); + + // compute the next states + bImage = Llb_Nonlin4Image( p->dd, vRootsNew, NULL, vVars2Q ); Cudd_Ref( bImage ); + Llb_Nonlin4Deref( p->dd, vRootsNew ); + + // intersect with the previous set + bOneCube = Cudd_bddIntersect( p->dd, bImage, bRing ); Cudd_Ref( bOneCube ); + Cudd_RecursiveDeref( p->dd, bImage ); + + // find any assignment of the BDD + RetValue = Cudd_bddPickOneCube( p->dd, bOneCube, pValues ); + Cudd_RecursiveDeref( p->dd, bOneCube ); + assert( RetValue ); + + // record the cube + Llb_Nonlin4RecordState( p->pAig, p->vOrder, (unsigned *)Vec_PtrEntry(vStates, v), pValues, fBackward ); + + // check that we get the init state + if ( v == 0 ) + { + Saig_ManForEachLo( p->pAig, pObj, i ) + assert( fBackward || pValues[Llb_ObjBddVar(p->vOrder, pObj)] == 0 ); + break; + } + + // write state in terms of NS variables + bState = Llb_Nonlin4ComputeCube( p->dd, p->pAig, p->vOrder, pValues, fBackward ); Cudd_Ref( bState ); + } + Vec_IntFree( vVars2Q ); + ABC_FREE( pValues ); + if ( fBackward ) + Vec_PtrReverseOrder( vStates ); +// if ( fVerbose ) +// Abc_PrintTime( 1, "BDD-based cex generation time", Abc_Clock() - clk ); + return vStates; +} + + +/**Function************************************************************* + + Synopsis [Perform reachability with hints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_Nonlin4Reachability( Llb_Mnx_t * p ) +{ + DdNode * bAux; + int nIters, nBddSizeFr = 0, nBddSizeTo = 0, nBddSizeTo2 = 0; + abctime clkTemp, clkIter, clk = Abc_Clock(); + assert( Aig_ManRegNum(p->pAig) > 0 ); + + if ( p->pPars->fBackward ) + { + // create bad state in the ring manager + if ( !p->pPars->fSkipOutCheck ) + { + p->bBad = Llb_Nonlin4ComputeInitState( p->dd, p->pAig, p->vOrder, p->pPars->fBackward ); Cudd_Ref( p->bBad ); + } + // create init state + if ( p->pPars->fCluster ) + p->bCurrent = p->dd->bFunc, p->dd->bFunc = NULL; + else + { + p->bCurrent = Llb_Nonlin4ComputeBad( p->dd, p->pAig, p->vOrder ); + if ( p->bCurrent == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + Cudd_Ref( p->bCurrent ); + } + // remap into the next states + p->bCurrent = Cudd_bddVarMap( p->dd, bAux = p->bCurrent ); + if ( p->bCurrent == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during remapping bad states.\n", p->pPars->TimeLimit ); + Cudd_RecursiveDeref( p->dd, bAux ); + p->pPars->iFrame = -1; + return -1; + } + Cudd_Ref( p->bCurrent ); + Cudd_RecursiveDeref( p->dd, bAux ); + } + else + { + // create bad state in the ring manager + if ( !p->pPars->fSkipOutCheck ) + { + if ( p->pPars->fCluster ) + p->bBad = p->dd->bFunc, p->dd->bFunc = NULL; + else + { + p->bBad = Llb_Nonlin4ComputeBad( p->dd, p->pAig, p->vOrder ); + if ( p->bBad == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + Cudd_Ref( p->bBad ); + } + } + else if ( p->dd->bFunc ) + Cudd_RecursiveDeref( p->dd, p->dd->bFunc ), p->dd->bFunc = NULL; + // compute the starting set of states + p->bCurrent = Llb_Nonlin4ComputeInitState( p->dd, p->pAig, p->vOrder, p->pPars->fBackward ); Cudd_Ref( p->bCurrent ); + } + // perform iterations + p->bReached = p->bCurrent; Cudd_Ref( p->bReached ); + for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ ) + { + clkIter = Abc_Clock(); + // check the runtime limit + if ( p->pPars->TimeLimit && Abc_Clock() > p->pPars->TimeTarget ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + return -1; + } + + // save the onion ring + Vec_PtrPush( p->vRings, p->bCurrent ); Cudd_Ref( p->bCurrent ); + + // check it for bad states + if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->dd, p->bCurrent, Cudd_Not(p->bBad) ) ) + { + Vec_Ptr_t * vStates; + assert( p->pAig->pSeqModel == NULL ); + vStates = Llb_Nonlin4DeriveCex( p, p->pPars->fBackward, p->pPars->fVerbose ); + p->pAig->pSeqModel = Llb4_Nonlin4TransformCex( p->pAig, vStates, -1, p->pPars->fVerbose ); + Vec_PtrFreeP( &vStates ); + if ( !p->pPars->fSilent ) + { + Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", p->pAig->pSeqModel->iPo, p->pAig->pName, nIters ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + p->pPars->iFrame = nIters - 1; + return 0; + } + + // compute the next states + clkTemp = Abc_Clock(); + p->bNext = Llb_Nonlin4Image( p->dd, p->vRoots, p->bCurrent, p->vVars2Q ); + if ( p->bNext == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in quantification.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + return -1; + } + Cudd_Ref( p->bNext ); + p->timeImage += Abc_Clock() - clkTemp; + + // remap into current states + clkTemp = Abc_Clock(); + p->bNext = Cudd_bddVarMap( p->dd, bAux = p->bNext ); + if ( p->bNext == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during remapping next states.\n", p->pPars->TimeLimit ); + Cudd_RecursiveDeref( p->dd, bAux ); + p->pPars->iFrame = nIters - 1; + return -1; + } + Cudd_Ref( p->bNext ); + Cudd_RecursiveDeref( p->dd, bAux ); + p->timeRemap += Abc_Clock() - clkTemp; + + // collect statistics + if ( p->pPars->fVerbose ) + { + nBddSizeFr = Cudd_DagSize( p->bCurrent ); + nBddSizeTo = Cudd_DagSize( bAux ); + nBddSizeTo2 = Cudd_DagSize( p->bNext ); + } + Cudd_RecursiveDeref( p->dd, p->bCurrent ); p->bCurrent = NULL; + + // derive new states + p->bCurrent = Cudd_bddAnd( p->dd, p->bNext, Cudd_Not(p->bReached) ); + if ( p->bCurrent == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + return -1; + } + Cudd_Ref( p->bCurrent ); + Cudd_RecursiveDeref( p->dd, p->bNext ); p->bNext = NULL; + if ( Cudd_IsConstant(p->bCurrent) ) + break; +/* + // reduce BDD size using constrain // Cudd_bddRestrict + p->bCurrent = Cudd_bddRestrict( p->dd, bAux = p->bCurrent, Cudd_Not(p->bReached) ); + Cudd_Ref( p->bCurrent ); +printf( "Before = %d. After = %d.\n", Cudd_DagSize(bAux), Cudd_DagSize(p->bCurrent) ); + Cudd_RecursiveDeref( p->dd, bAux ); +*/ + + // add to the reached set + p->bReached = Cudd_bddOr( p->dd, bAux = p->bReached, p->bCurrent ); + if ( p->bReached == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bAux ); + return -1; + } + Cudd_Ref( p->bReached ); + Cudd_RecursiveDeref( p->dd, bAux ); + + + // report the results + if ( p->pPars->fVerbose ) + { + printf( "I =%5d : ", nIters ); + printf( "Fr =%7d ", nBddSizeFr ); + printf( "ImNs =%7d ", nBddSizeTo ); + printf( "ImCs =%7d ", nBddSizeTo2 ); + printf( "Rea =%7d ", Cudd_DagSize(p->bReached) ); + printf( "(%4d %4d) ", Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) ); + Abc_PrintTime( 1, "T", Abc_Clock() - clkIter ); + } +/* + if ( pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(p->dd, bReached, Saig_ManRegNum(p->pAig) ); +// Extra_bddPrint( p->dd, bReached );printf( "\n" ); + printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); + fflush( stdout ); + } +*/ + if ( nIters == p->pPars->nIterMax - 1 ) + { + if ( !p->pPars->fSilent ) + printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nIterMax ); + p->pPars->iFrame = nIters; + return -1; + } + } + + // report the stats + if ( p->pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(p->dd, p->bReached, Saig_ManRegNum(p->pAig) ); + if ( p->bCurrent && Cudd_IsConstant(p->bCurrent) ) + printf( "Reachability analysis completed after %d frames.\n", nIters ); + else + printf( "Reachability analysis is stopped after %d frames.\n", nIters ); + printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); + fflush( stdout ); + } + if ( p->bCurrent == NULL || !Cudd_IsConstant(p->bCurrent) ) + { + if ( !p->pPars->fSilent ) + printf( "Verified only for states reachable in %d frames. ", nIters ); + p->pPars->iFrame = p->pPars->nIterMax; + return -1; // undecided + } + // report + if ( !p->pPars->fSilent ) + printf( "The miter is proved unreachable after %d iterations. ", nIters ); + if ( !p->pPars->fSilent ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + p->pPars->iFrame = nIters - 1; + return 1; // unreachable +} + +/**Function************************************************************* + + Synopsis [Reorders BDDs in the working manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4Reorder( DdManager * dd, int fTwice, int fVerbose ) +{ + abctime clk = Abc_Clock(); + if ( fVerbose ) + Abc_Print( 1, "Reordering... Before =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + if ( fVerbose ) + Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + if ( fTwice ) + { + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + if ( fVerbose ) + Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + } + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Mnx_t * Llb_MnxStart( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) +{ + Llb_Mnx_t * p; + + p = ABC_CALLOC( Llb_Mnx_t, 1 ); + p->pAig = pAig; + p->pPars = pPars; + + // compute time to stop + p->pPars->TimeTarget = p->pPars->TimeLimit ? p->pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0; + + if ( pPars->fCluster ) + { +// Llb_Nonlin4Cluster( p->pAig, &p->dd, &p->vOrder, &p->vRoots, pPars->nBddMax, pPars->fVerbose ); +// Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); + Llb4_Nonlin4Sweep( p->pAig, pPars->nBddMax, pPars->nClusterMax, &p->dd, &p->vOrder, &p->vRoots, pPars->fVerbose ); + // set the stop time parameter + p->dd->TimeStop = p->pPars->TimeTarget; + } + else + { +// p->vOrder = Llb_Nonlin4CreateOrderSimple( pAig ); + p->vOrder = Llb_Nonlin4CreateOrder( pAig ); + p->dd = Cudd_Init( Vec_IntCountPositive(p->vOrder) + 1, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); + Cudd_SetMaxGrowth( p->dd, 1.05 ); + // set the stop time parameter + p->dd->TimeStop = p->pPars->TimeTarget; + p->vRoots = Llb_Nonlin4DerivePartitions( p->dd, pAig, p->vOrder ); + } + + Llb_Nonlin4SetupVarMap( p->dd, pAig, p->vOrder ); + p->vVars2Q = Llb_Nonlin4CreateVars2Q( p->dd, pAig, p->vOrder, p->pPars->fBackward ); + p->vRings = Vec_PtrAlloc( 100 ); + + if ( pPars->fReorder ) + Llb_Nonlin4Reorder( p->dd, 0, 1 ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MnxStop( Llb_Mnx_t * p ) +{ + DdNode * bTemp; + int i; + if ( p->pPars->fVerbose ) + { + p->timeReo = Cudd_ReadReorderingTime(p->dd); + p->timeOther = p->timeTotal - p->timeImage - p->timeRemap; + ABC_PRTP( "Image ", p->timeImage, p->timeTotal ); + ABC_PRTP( "Remap ", p->timeRemap, p->timeTotal ); + ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); + ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); + ABC_PRTP( " reo ", p->timeReo, p->timeTotal ); + } + // remove BDDs + if ( p->bBad ) + Cudd_RecursiveDeref( p->dd, p->bBad ); + if ( p->bReached ) + Cudd_RecursiveDeref( p->dd, p->bReached ); + if ( p->bCurrent ) + Cudd_RecursiveDeref( p->dd, p->bCurrent ); + if ( p->bNext ) + Cudd_RecursiveDeref( p->dd, p->bNext ); + if ( p->vRings ) + Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i ) + Cudd_RecursiveDeref( p->dd, bTemp ); + if ( p->vRoots ) + Vec_PtrForEachEntry( DdNode *, p->vRoots, bTemp, i ) + Cudd_RecursiveDeref( p->dd, bTemp ); + // remove arrays + Vec_PtrFreeP( &p->vRings ); + Vec_PtrFreeP( &p->vRoots ); +//Cudd_PrintInfo( p->dd, stdout ); + Extra_StopManager( p->dd ); + Vec_IntFreeP( &p->vOrder ); + Vec_IntFreeP( &p->vVars2Q ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MnxCheckNextStateVars( Llb_Mnx_t * p ) +{ + Aig_Obj_t * pObj; + int i, Counter0 = 0, Counter1 = 0; + Saig_ManForEachLi( p->pAig, pObj, i ) + if ( Saig_ObjIsLo(p->pAig, Aig_ObjFanin0(pObj)) ) + { + if ( Aig_ObjFaninC0(pObj) ) + Counter0++; + else + Counter1++; + } + printf( "Total = %d. Direct LO = %d. Compl LO = %d.\n", Aig_ManRegNum(p->pAig), Counter1, Counter0 ); +} + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) +{ + Llb_Mnx_t * pMnn; + int RetValue = -1; + if ( pPars->fVerbose ) + Aig_ManPrintStats( pAig ); + if ( pPars->fCluster && Aig_ManObjNum(pAig) >= (1 << 15) ) + { + printf( "The number of objects is more than 2^15. Clustering cannot be used.\n" ); + return RetValue; + } + { + abctime clk = Abc_Clock(); + pMnn = Llb_MnxStart( pAig, pPars ); +//Llb_MnxCheckNextStateVars( pMnn ); + if ( !pPars->fSkipReach ) + RetValue = Llb_Nonlin4Reachability( pMnn ); + pMnn->timeTotal = Abc_Clock() - clk; + Llb_MnxStop( pMnn ); + } + return RetValue; +} + + +/**Function************************************************************* + + Synopsis [Takes an AIG and returns an AIG representing reachable states.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Llb_ReachableStates( Aig_Man_t * pAig ) +{ + extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); + Vec_Int_t * vPermute; + Vec_Ptr_t * vNames; + Gia_ParLlb_t Pars, * pPars = &Pars; + DdManager * dd; + DdNode * bReached; + Llb_Mnx_t * pMnn; + Abc_Ntk_t * pNtk, * pNtkMuxes; + Aig_Obj_t * pObj; + int i, RetValue; + abctime clk = Abc_Clock(); + + // create parameters + Llb_ManSetDefaultParams( pPars ); + pPars->fSkipOutCheck = 1; + pPars->fCluster = 0; + pPars->fReorder = 0; + pPars->fSilent = 1; + pPars->nBddMax = 100; + pPars->nClusterMax = 500; + + // run reachability + pMnn = Llb_MnxStart( pAig, pPars ); + RetValue = Llb_Nonlin4Reachability( pMnn ); + assert( RetValue == 1 ); + + // print BDD +// Extra_bddPrint( pMnn->dd, pMnn->bReached ); +// Extra_bddPrintSupport( pMnn->dd, pMnn->bReached ); +// printf( "\n" ); + + // collect flop output variables + vPermute = Vec_IntStartFull( Cudd_ReadSize(pMnn->dd) ); + Saig_ManForEachLo( pAig, pObj, i ) + Vec_IntWriteEntry( vPermute, Llb_ObjBddVar(pMnn->vOrder, pObj), i ); + + // transfer the reached state BDD into the new manager + dd = Cudd_Init( Saig_ManRegNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + bReached = Extra_TransferPermute( pMnn->dd, dd, pMnn->bReached, Vec_IntArray(vPermute) ); Cudd_Ref( bReached ); + Vec_IntFree( vPermute ); + assert( Cudd_ReadSize(dd) == Saig_ManRegNum(pAig) ); + + // quit reachability engine + pMnn->timeTotal = Abc_Clock() - clk; + Llb_MnxStop( pMnn ); + + // derive the network + vNames = Abc_NodeGetFakeNames( Saig_ManRegNum(pAig) ); + pNtk = Abc_NtkDeriveFromBdd( dd, bReached, "reached", vNames ); + Abc_NodeFreeNames( vNames ); + Cudd_RecursiveDeref( dd, bReached ); + Cudd_Quit( dd ); + + // convert + pNtkMuxes = Abc_NtkBddToMuxes( pNtk ); + Abc_NtkDelete( pNtk ); + pNtk = Abc_NtkStrash( pNtkMuxes, 0, 1, 0 ); + Abc_NtkDelete( pNtkMuxes ); + pAig = Abc_NtkToDar( pNtk, 0, 0 ); + Abc_NtkDelete( pNtk ); + return pAig; +} +Gia_Man_t * Llb_ReachableStatesGia( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Aig_Man_t * pAig, * pReached; + pAig = Gia_ManToAigSimple( p ); + pReached = Llb_ReachableStates( pAig ); + Aig_ManStop( pAig ); + pNew = Gia_ManFromAigSimple( pReached ); + Aig_ManStop( pReached ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb4Sweep.c b/src/bdd/llb/llb4Sweep.c new file mode 100644 index 00000000..6b318572 --- /dev/null +++ b/src/bdd/llb/llb4Sweep.c @@ -0,0 +1,589 @@ +/**CFile**************************************************************** + + FileName [llb2Sweep.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Non-linear quantification scheduling.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Sweep.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Find good static variable ordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4SweepOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter, int fSaveAll ) +{ + Aig_Obj_t * pFanin0, * pFanin1; + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return; + Aig_ObjSetTravIdCurrent( pAig, pObj ); + assert( Llb_ObjBddVar(vOrder, pObj) < 0 ); + if ( Aig_ObjIsCi(pObj) ) + { + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); + return; + } + // try fanins with higher level first + pFanin0 = Aig_ObjFanin0(pObj); + pFanin1 = Aig_ObjFanin1(pObj); +// if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) ) + if ( pFanin0->Level > pFanin1->Level ) + { + Llb_Nonlin4SweepOrder_rec( pAig, pFanin0, vOrder, pCounter, fSaveAll ); + Llb_Nonlin4SweepOrder_rec( pAig, pFanin1, vOrder, pCounter, fSaveAll ); + } + else + { + Llb_Nonlin4SweepOrder_rec( pAig, pFanin1, vOrder, pCounter, fSaveAll ); + Llb_Nonlin4SweepOrder_rec( pAig, pFanin0, vOrder, pCounter, fSaveAll ); + } + if ( fSaveAll || pObj->fMarkA ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); +} + +/**Function************************************************************* + + Synopsis [Find good static variable ordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_Nonlin4SweepOrder( Aig_Man_t * pAig, int * pCounter, int fSaveAll ) +{ + Vec_Int_t * vOrder; + Aig_Obj_t * pObj; + int i, Counter = 0; + // collect nodes in the order + vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) ); + Aig_ManIncrementTravId( pAig ); + Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); + Aig_ManForEachCo( pAig, pObj, i ) + { + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); + Llb_Nonlin4SweepOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter, fSaveAll ); + } + Aig_ManForEachCi( pAig, pObj, i ) + if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); +// assert( Counter == Aig_ManObjNum(pAig) - 1 ); // no dangling nodes + if ( pCounter ) + *pCounter = Counter - Aig_ManCiNum(pAig) - Aig_ManCoNum(pAig); + return vOrder; +} + + +/**Function************************************************************* + + Synopsis [Performs BDD sweep on the netlist.] + + Description [Returns AIG with internal cut points labeled with fMarkA.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb4_Nonlin4SweepCutpoints( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nBddLimit, int fVerbose ) +{ + DdManager * dd; + DdNode * bFunc0, * bFunc1, * bFunc; + Aig_Obj_t * pObj; + int i, Counter = 0, Counter1 = 0; + dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + // assign elementary variables + Aig_ManCleanData( pAig ); + Aig_ManForEachCi( pAig, pObj, i ) + pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + // sweep internal nodes + Aig_ManForEachNode( pAig, pObj, i ) + { +/* + if ( pObj->nRefs >= 4 ) + { + bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); Cudd_Ref( bFunc ); + pObj->pData = bFunc; + Counter1++; + continue; + } +*/ + bFunc0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bFunc1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); + bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); + if ( Cudd_DagSize(bFunc) > nBddLimit ) + { +// if ( fVerbose ) +// printf( "Node %5d : Beg =%5d. ", i, Cudd_DagSize(bFunc) ); + + // add cutpoint at a larger one + Cudd_RecursiveDeref( dd, bFunc ); + if ( Cudd_DagSize(bFunc0) >= Cudd_DagSize(bFunc1) ) + { + Cudd_RecursiveDeref( dd, (DdNode *)Aig_ObjFanin0(pObj)->pData ); + bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, Aig_ObjFanin0(pObj)) ); + Aig_ObjFanin0(pObj)->pData = bFunc; Cudd_Ref( bFunc ); + Aig_ObjFanin0(pObj)->fMarkA = 1; + +// if ( fVerbose ) +// printf( "Ref =%3d ", Aig_ObjFanin0(pObj)->nRefs ); + } + else + { + Cudd_RecursiveDeref( dd, (DdNode *)Aig_ObjFanin1(pObj)->pData ); + bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, Aig_ObjFanin1(pObj)) ); + Aig_ObjFanin1(pObj)->pData = bFunc; Cudd_Ref( bFunc ); + Aig_ObjFanin1(pObj)->fMarkA = 1; + +// if ( fVerbose ) +// printf( "Ref =%3d ", Aig_ObjFanin1(pObj)->nRefs ); + } + // perform new operation + bFunc0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bFunc1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); + bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); +// assert( Cudd_DagSize(bFunc) <= nBddLimit ); + +// if ( fVerbose ) +// printf( "End =%5d.\n", Cudd_DagSize(bFunc) ); + Counter++; + } + pObj->pData = bFunc; +//printf( "%d ", Cudd_DagSize(bFunc) ); + } +//printf( "\n" ); + // clean up + Aig_ManForEachNode( pAig, pObj, i ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + Extra_StopManager( dd ); +// Aig_ManCleanMarkA( pAig ); + if ( fVerbose ) + printf( "Added %d cut points. Used %d high fanout points.\n", Counter, Counter1 ); + return Counter + Counter1; +} + +/**Function************************************************************* + + Synopsis [Derives BDDs for the partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_Nonlin4SweepPartitions_rec( DdManager * dd, Aig_Obj_t * pObj, Vec_Int_t * vOrder, Vec_Ptr_t * vRoots ) +{ + DdNode * bBdd, * bBdd0, * bBdd1, * bPart, * vVar; + if ( Aig_ObjIsConst1(pObj) ) + return Cudd_ReadOne(dd); + if ( Aig_ObjIsCi(pObj) ) + return Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + if ( pObj->pData ) + return (DdNode *)pObj->pData; + if ( Aig_ObjIsCo(pObj) ) + { + bBdd0 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) ); + bPart = Cudd_bddXnor( dd, Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ), bBdd0 ); Cudd_Ref( bPart ); + Vec_PtrPush( vRoots, bPart ); + return NULL; + } + bBdd0 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin1(pObj), vOrder, vRoots), Aig_ObjFaninC1(pObj) ); + bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bBdd ); + if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) + { + vVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + bPart = Cudd_bddXnor( dd, vVar, bBdd ); Cudd_Ref( bPart ); + Vec_PtrPush( vRoots, bPart ); + Cudd_RecursiveDeref( dd, bBdd ); + bBdd = vVar; Cudd_Ref( vVar ); + } + pObj->pData = bBdd; + return bBdd; +} + +/**Function************************************************************* + + Synopsis [Derives BDDs for the partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_Nonlin4SweepPartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fTransition ) +{ + Vec_Ptr_t * vRoots; + Aig_Obj_t * pObj; + int i; + Aig_ManCleanData( pAig ); + vRoots = Vec_PtrAlloc( 100 ); + if ( fTransition ) + { + Saig_ManForEachLi( pAig, pObj, i ) + Llb_Nonlin4SweepPartitions_rec( dd, pObj, vOrder, vRoots ); + } + else + { + Saig_ManForEachPo( pAig, pObj, i ) + Llb_Nonlin4SweepPartitions_rec( dd, pObj, vOrder, vRoots ); + } + Aig_ManForEachNode( pAig, pObj, i ) + if ( pObj->pData ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + return vRoots; +} + +/**Function************************************************************* + + Synopsis [Get bad state monitor.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb4_Nonlin4SweepBadMonitor( Aig_Man_t * pAig, Vec_Int_t * vOrder, DdManager * dd ) +{ + Aig_Obj_t * pObj; + DdNode * bRes, * bVar, * bTemp; + int i; + abctime TimeStop; + TimeStop = dd->TimeStop; dd->TimeStop = 0; + bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); + Saig_ManForEachPo( pAig, pObj, i ) + { + bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bRes ); + dd->TimeStop = TimeStop; + return Cudd_Not(bRes); +} + +/**Function************************************************************* + + Synopsis [Creates quantifiable variables for both types of traversal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_Nonlin4SweepVars2Q( Aig_Man_t * pAig, Vec_Int_t * vOrder, int fAddLis ) +{ + Vec_Int_t * vVars2Q; + Aig_Obj_t * pObj; + int i; + vVars2Q = Vec_IntAlloc( 0 ); + Vec_IntFill( vVars2Q, Aig_ManObjNumMax(pAig), 1 ); + // add flop outputs + Saig_ManForEachLo( pAig, pObj, i ) + Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 ); + // add flop inputs + if ( fAddLis ) + Saig_ManForEachLi( pAig, pObj, i ) + Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 ); + return vVars2Q; +} + +/**Function************************************************************* + + Synopsis [Multiply every partition by the cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4SweepDeref( DdManager * dd, Vec_Ptr_t * vParts ) +{ + DdNode * bFunc; + int i; + Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i ) + Cudd_RecursiveDeref( dd, bFunc ); + Vec_PtrFree( vParts ); +} + +/**Function************************************************************* + + Synopsis [Multiply every partition by the cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4SweepPrint( Vec_Ptr_t * vFuncs ) +{ + DdNode * bFunc; + int i; + printf( "(%d) ", Vec_PtrSize(vFuncs) ); + Vec_PtrForEachEntry( DdNode *, vFuncs, bFunc, i ) + printf( "%d ", Cudd_DagSize(bFunc) ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Computes bad states.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdManager * Llb4_Nonlin4SweepBadStates( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nVars ) +{ + DdManager * dd; + Vec_Ptr_t * vParts; + Vec_Int_t * vVars2Q; + DdNode * bMonitor, * bImage; + // get quantifiable variables + vVars2Q = Llb_Nonlin4SweepVars2Q( pAig, vOrder, 0 ); + // start BDD manager and create partitions + dd = Cudd_Init( nVars, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + vParts = Llb_Nonlin4SweepPartitions( dd, pAig, vOrder, 0 ); +//printf( "Outputs: " ); +//Llb_Nonlin4SweepPrint( vParts ); + // compute image of the partitions + bMonitor = Llb4_Nonlin4SweepBadMonitor( pAig, vOrder, dd ); Cudd_Ref( bMonitor ); + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + bImage = Llb_Nonlin4Image( dd, vParts, bMonitor, vVars2Q ); Cudd_Ref( bImage ); + Cudd_RecursiveDeref( dd, bMonitor ); + Llb_Nonlin4SweepDeref( dd, vParts ); + Vec_IntFree( vVars2Q ); + // save image and return + dd->bFunc = bImage; + return dd; +} + +/**Function************************************************************* + + Synopsis [Computes clusters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdManager * Llb4_Nonlin4SweepGroups( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nVars, Vec_Ptr_t ** pvGroups, int nBddLimitClp, int fVerbose ) +{ + DdManager * dd; + Vec_Ptr_t * vParts; + Vec_Int_t * vVars2Q; + // get quantifiable variables + vVars2Q = Llb_Nonlin4SweepVars2Q( pAig, vOrder, 1 ); + // start BDD manager and create partitions + dd = Cudd_Init( nVars, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + vParts = Llb_Nonlin4SweepPartitions( dd, pAig, vOrder, 1 ); +//printf( "Transitions: " ); +//Llb_Nonlin4SweepPrint( vParts ); + // compute image of the partitions + + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + *pvGroups = Llb_Nonlin4Group( dd, vParts, vVars2Q, nBddLimitClp ); + Llb_Nonlin4SweepDeref( dd, vParts ); +// *pvGroups = vParts; + +if ( fVerbose ) +{ +printf( "Groups: " ); +Llb_Nonlin4SweepPrint( *pvGroups ); +} + + Vec_IntFree( vVars2Q ); + return dd; +} + + +/**Function************************************************************* + + Synopsis [Creates quantifiable variables for both types of traversal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4SweepPrintSuppProfile( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups, int fVerbose ) +{ + Aig_Obj_t * pObj; + int i, * pSupp; + int nSuppAll = 0, nSuppPi = 0, nSuppPo = 0, nSuppLi = 0, nSuppLo = 0, nSuppAnd = 0; + + pSupp = ABC_CALLOC( int, Cudd_ReadSize(dd) ); + Extra_VectorSupportArray( dd, (DdNode **)Vec_PtrArray(vGroups), Vec_PtrSize(vGroups), pSupp ); + + Aig_ManForEachObj( pAig, pObj, i ) + { + if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) + continue; + // remove variables that do not participate + if ( pSupp[Llb_ObjBddVar(vOrder, pObj)] == 0 ) + { + if ( Aig_ObjIsNode(pObj) ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), -1 ); + continue; + } + nSuppAll++; + if ( Saig_ObjIsPi(pAig, pObj) ) + nSuppPi++; + else if ( Saig_ObjIsLo(pAig, pObj) ) + nSuppLo++; + else if ( Saig_ObjIsPo(pAig, pObj) ) + nSuppPo++; + else if ( Saig_ObjIsLi(pAig, pObj) ) + nSuppLi++; + else + nSuppAnd++; + } + ABC_FREE( pSupp ); + + if ( fVerbose ) + { + printf( "Groups =%3d ", Vec_PtrSize(vGroups) ); + printf( "Variables: all =%4d ", nSuppAll ); + printf( "pi =%4d ", nSuppPi ); + printf( "po =%4d ", nSuppPo ); + printf( "lo =%4d ", nSuppLo ); + printf( "li =%4d ", nSuppLi ); + printf( "and =%4d", nSuppAnd ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Performs BDD sweep on the netlist.] + + Description [Returns BDD manager, ordering, clusters, and bad states + inside dd->bFunc.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb4_Nonlin4Sweep( Aig_Man_t * pAig, int nSweepMax, int nClusterMax, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int fVerbose ) +{ + DdManager * ddBad, * ddWork; + Vec_Ptr_t * vGroups; + Vec_Int_t * vOrder; + int Counter, nCutPoints; + + // get the original ordering + Aig_ManCleanMarkA( pAig ); + vOrder = Llb_Nonlin4SweepOrder( pAig, &Counter, 1 ); + assert( Counter == Aig_ManNodeNum(pAig) ); + // mark the nodes + nCutPoints = Llb4_Nonlin4SweepCutpoints( pAig, vOrder, nSweepMax, fVerbose ); + Vec_IntFree( vOrder ); + // get better ordering + vOrder = Llb_Nonlin4SweepOrder( pAig, &Counter, 0 ); + assert( Counter == nCutPoints ); + Aig_ManCleanMarkA( pAig ); + // compute the BAD states + ddBad = Llb4_Nonlin4SweepBadStates( pAig, vOrder, nCutPoints + Aig_ManCiNum(pAig) + Aig_ManCoNum(pAig) ); + // compute the clusters + ddWork = Llb4_Nonlin4SweepGroups( pAig, vOrder, nCutPoints + Aig_ManCiNum(pAig) + Aig_ManCoNum(pAig), &vGroups, nClusterMax, fVerbose ); + // transfer the result from the Bad manager +//printf( "Bad before = %d.\n", Cudd_DagSize(ddBad->bFunc) ); + ddWork->bFunc = Cudd_bddTransfer( ddBad, ddWork, ddBad->bFunc ); Cudd_Ref( ddWork->bFunc ); + Cudd_RecursiveDeref( ddBad, ddBad->bFunc ); ddBad->bFunc = NULL; + Extra_StopManager( ddBad ); + // update ordering to exclude quantified variables +//printf( "Bad after = %d.\n", Cudd_DagSize(ddWork->bFunc) ); + + Llb_Nonlin4SweepPrintSuppProfile( ddWork, pAig, vOrder, vGroups, fVerbose ); + + // return the result + *pdd = ddWork; + *pvOrder = vOrder; + *pvGroups = vGroups; +} + +/**Function************************************************************* + + Synopsis [Performs BDD sweep on the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb4_Nonlin4SweepExperiment( Aig_Man_t * pAig ) +{ + DdManager * dd; + Vec_Int_t * vOrder; + Vec_Ptr_t * vGroups; + Llb4_Nonlin4Sweep( pAig, 100, 500, &dd, &vOrder, &vGroups, 1 ); + + Llb_Nonlin4SweepDeref( dd, vGroups ); + + Cudd_RecursiveDeref( dd, dd->bFunc ); + Extra_StopManager( dd ); + Vec_IntFree( vOrder ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llbInt.h b/src/bdd/llb/llbInt.h new file mode 100644 index 00000000..238da04e --- /dev/null +++ b/src/bdd/llb/llbInt.h @@ -0,0 +1,212 @@ +/**CFile**************************************************************** + + FileName [llbInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD-based reachability.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 8, 2010.] + + Revision [$Id: llbInt.h,v 1.00 2010/05/08 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__llb__llbInt_h +#define ABC__aig__llb__llbInt_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include <stdio.h> +#include "aig/aig/aig.h" +#include "aig/saig/saig.h" +#include "proof/ssw/ssw.h" +#include "llb.h" + +#include "bdd/extrab/extraBdd.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_HEADER_START + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Llb_Man_t_ Llb_Man_t; +typedef struct Llb_Mtr_t_ Llb_Mtr_t; +typedef struct Llb_Grp_t_ Llb_Grp_t; + +struct Llb_Man_t_ +{ + Gia_ParLlb_t * pPars; // parameters + Aig_Man_t * pAigGlo; // initial AIG manager (owned by the caller) + Aig_Man_t * pAig; // derived AIG manager (created in this package) + DdManager * dd; // BDD manager + DdManager * ddG; // BDD manager + DdManager * ddR; // BDD manager + Vec_Int_t * vObj2Var; // mapping AIG ObjId into BDD var index + Vec_Int_t * vVar2Obj; // mapping BDD var index into AIG ObjId + Vec_Ptr_t * vGroups; // group Id into group pointer + Llb_Mtr_t * pMatrix; // dependency matrix + // image computation + Vec_Ptr_t * vRings; // onion rings + Vec_Int_t * vVarBegs; // the first group where the var appears + Vec_Int_t * vVarEnds; // the last group where the var appears + // variable mapping + Vec_Int_t * vNs2Glo; // next state variables into global variables + Vec_Int_t * vCs2Glo; // next state variables into global variables + Vec_Int_t * vGlo2Cs; // global variables into current state variables + Vec_Int_t * vGlo2Ns; // global variables into current state variables + // flow computation +// Vec_Int_t * vMem; +// Vec_Ptr_t * vTops; +// Vec_Ptr_t * vBots; +// Vec_Ptr_t * vCuts; +}; + +struct Llb_Mtr_t_ +{ + int nPis; // number of primary inputs + int nFfs; // number of flip-flops + int nRows; // number of rows + int nCols; // number of columns + int * pColSums; // sum of values in a column + Llb_Grp_t ** pColGrps; // group structure for each col + int * pRowSums; // sum of values in a row + char ** pMatrix; // dependency matrix + Llb_Man_t * pMan; // manager + // partial product + char * pProdVars; // variables in the partial product + int * pProdNums; // var counts in the remaining partitions +}; + +struct Llb_Grp_t_ +{ + int Id; // group ID + Vec_Ptr_t * vIns; // input AIG objs + Vec_Ptr_t * vOuts; // output AIG objs + Vec_Ptr_t * vNodes; // internal AIG objs + Llb_Man_t * pMan; // manager + Llb_Grp_t * pPrev; // previous group + Llb_Grp_t * pNext; // next group +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Llb_ObjBddVar( Vec_Int_t * vOrder, Aig_Obj_t * pObj ) { return Vec_IntEntry(vOrder, Aig_ObjId(pObj)); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== llbConstr.c ======================================================*/ +extern Vec_Int_t * Llb_ManDeriveConstraints( Aig_Man_t * p ); +extern void Llb_ManPrintEntries( Aig_Man_t * p, Vec_Int_t * vCands ); +/*=== llbCore.c ======================================================*/ +extern int Llb_ManModelCheckAig( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars, Vec_Int_t * vHints, DdManager ** pddGlo ); +/*=== llbCluster.c ======================================================*/ +extern void Llb_ManCluster( Llb_Mtr_t * p ); +/*=== llbDump.c ======================================================*/ +extern void Llb_ManDumpReached( DdManager * ddG, DdNode * bReached, char * pModel, char * pFileName ); +/*=== llbFlow.c ======================================================*/ +extern Vec_Ptr_t * Llb_ManFlow( Aig_Man_t * p, Vec_Ptr_t * vSources, int * pnFlow ); +/*=== llbHint.c ======================================================*/ +extern int Llb_ManReachabilityWithHints( Llb_Man_t * p ); +extern int Llb_ManModelCheckAigWithHints( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars ); +/*=== llbMan.c =======================================================*/ +extern void Llb_ManPrepareVarMap( Llb_Man_t * p ); +extern Llb_Man_t * Llb_ManStart( Aig_Man_t * pAigGlo, Aig_Man_t * pAig, Gia_ParLlb_t * pPars ); +extern void Llb_ManStop( Llb_Man_t * p ); +/*=== llbMatrix.c ====================================================*/ +extern void Llb_MtrVerifyMatrix( Llb_Mtr_t * p ); +extern Llb_Mtr_t * Llb_MtrCreate( Llb_Man_t * p ); +extern void Llb_MtrFree( Llb_Mtr_t * p ); +extern void Llb_MtrPrint( Llb_Mtr_t * p, int fOrder ); +extern void Llb_MtrPrintMatrixStats( Llb_Mtr_t * p ); +/*=== llbPart.c ======================================================*/ +extern Llb_Grp_t * Llb_ManGroupAlloc( Llb_Man_t * pMan ); +extern void Llb_ManGroupStop( Llb_Grp_t * p ); +extern void Llb_ManPrepareGroups( Llb_Man_t * pMan ); +extern Llb_Grp_t * Llb_ManGroupsCombine( Llb_Grp_t * p1, Llb_Grp_t * p2 ); +extern Llb_Grp_t * Llb_ManGroupCreateFromCuts( Llb_Man_t * pMan, Vec_Int_t * vCut1, Vec_Int_t * vCut2 ); +extern void Llb_ManPrepareVarLimits( Llb_Man_t * p ); +/*=== llbPivot.c =====================================================*/ +extern int Llb_ManTracePaths( Aig_Man_t * p, Aig_Obj_t * pPivot ); +extern Vec_Int_t * Llb_ManMarkPivotNodes( Aig_Man_t * p, int fUseInternal ); +/*=== llbReach.c =====================================================*/ +extern int Llb_ManReachability( Llb_Man_t * p, Vec_Int_t * vHints, DdManager ** pddGlo ); +/*=== llbSched.c =====================================================*/ +extern void Llb_MtrSchedule( Llb_Mtr_t * p ); + +/*=== llb2Bad.c ======================================================*/ +extern DdNode * Llb_BddComputeBad( Aig_Man_t * pInit, DdManager * dd, abctime TimeOut ); +extern DdNode * Llb_BddQuantifyPis( Aig_Man_t * pInit, DdManager * dd, DdNode * bFunc ); +/*=== llb2Core.c ======================================================*/ +extern DdNode * Llb_CoreComputeCube( DdManager * dd, Vec_Int_t * vVars, int fUseVarIndex, char * pValues ); +extern int Llb_CoreExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, abctime TimeTarget ); +/*=== llb2Driver.c ======================================================*/ +extern Vec_Int_t * Llb_DriverCountRefs( Aig_Man_t * p ); +extern Vec_Int_t * Llb_DriverCollectNs( Aig_Man_t * pAig, Vec_Int_t * vDriRefs ); +extern Vec_Int_t * Llb_DriverCollectCs( Aig_Man_t * pAig ); +extern DdNode * Llb_DriverPhaseCube( Aig_Man_t * pAig, Vec_Int_t * vDriRefs, DdManager * dd ); +extern DdManager * Llb_DriverLastPartition( Aig_Man_t * p, Vec_Int_t * vVarsNs, abctime TimeTarget ); +/*=== llb2Image.c ======================================================*/ +extern Vec_Ptr_t * Llb_ImgSupports( Aig_Man_t * p, Vec_Ptr_t * vDdMans, Vec_Int_t * vStart, Vec_Int_t * vStop, int fAddPis, int fVerbose ); +extern void Llb_ImgSchedule( Vec_Ptr_t * vSupps, Vec_Ptr_t ** pvQuant0, Vec_Ptr_t ** pvQuant1, int fVerbose ); +extern DdManager * Llb_ImgPartition( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, abctime TimeTarget ); +extern void Llb_ImgQuantifyFirst( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, Vec_Ptr_t * vQuant0, int fVerbose ); +extern void Llb_ImgQuantifyReset( Vec_Ptr_t * vDdMans ); +extern DdNode * Llb_ImgComputeImage( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, DdManager * dd, DdNode * bInit, + Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1, Vec_Int_t * vDriRefs, + abctime TimeTarget, int fBackward, int fReorder, int fVerbose ); + +extern DdManager * Llb_NonlinImageStart( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, int * pOrder, int fFirst, abctime TimeTarget ); +extern DdNode * Llb_NonlinImageCompute( DdNode * bCurrent, int fReorder, int fDrop, int fVerbose, int * pOrder ); +extern void Llb_NonlinImageQuit(); + +/*=== llb3Image.c =======================================================*/ +extern DdNode * Llb_NonlinImage( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, + DdManager * dd, DdNode * bCurrent, int fReorder, int fVerbose, int * pOrder ); +/*=== llb3Nonlin.c ======================================================*/ +extern DdNode * Llb_NonlinComputeInitState( Aig_Man_t * pAig, DdManager * dd ); + + +/*=== llb4Cex.c =======================================================*/ +extern Abc_Cex_t * Llb4_Nonlin4TransformCex( Aig_Man_t * pAig, Vec_Ptr_t * vStates, int iCexPo, int fVerbose ); +/*=== llb4Cluster.c =======================================================*/ +//extern void Llb_Nonlin4Cluster( Aig_Man_t * pAig, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int nBddMax, int fVerbose ); +/*=== llb4Image.c =======================================================*/ +extern DdNode * Llb_Nonlin4Image( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q ); +extern Vec_Ptr_t * Llb_Nonlin4Group( DdManager * dd, Vec_Ptr_t * vParts, Vec_Int_t * vVars2Q, int nSizeMax ); +/*=== llb4Map.c =========================================================*/ +//extern Vec_Int_t * Llb_AigMap( Aig_Man_t * pAig, int nLutSize, int nLutMin ); +/*=== llb4Nonlin.c ======================================================*/ +//extern int Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ); +/*=== llb4Sweep.c ======================================================*/ +extern void Llb4_Nonlin4Sweep( Aig_Man_t * pAig, int nSweepMax, int nClusterMax, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int fVerbose ); + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/bdd/llb/module.make b/src/bdd/llb/module.make new file mode 100644 index 00000000..6d253d50 --- /dev/null +++ b/src/bdd/llb/module.make @@ -0,0 +1,22 @@ +SRC += src/bdd/llb/llb1Cluster.c \ + src/bdd/llb/llb1Constr.c \ + src/bdd/llb/llb1Core.c \ + src/bdd/llb/llb1Group.c \ + src/bdd/llb/llb1Hint.c \ + src/bdd/llb/llb1Man.c \ + src/bdd/llb/llb1Matrix.c \ + src/bdd/llb/llb1Pivot.c \ + src/bdd/llb/llb1Reach.c \ + src/bdd/llb/llb1Sched.c \ + src/bdd/llb/llb2Bad.c \ + src/bdd/llb/llb2Core.c \ + src/bdd/llb/llb2Driver.c \ + src/bdd/llb/llb2Dump.c \ + src/bdd/llb/llb2Flow.c \ + src/bdd/llb/llb2Image.c \ + src/bdd/llb/llb3Image.c \ + src/bdd/llb/llb3Nonlin.c \ + src/bdd/llb/llb4Cex.c \ + src/bdd/llb/llb4Image.c \ + src/bdd/llb/llb4Nonlin.c \ + src/bdd/llb/llb4Sweep.c |