| /**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 |
| |