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