| /**CFile**************************************************************** |
| |
| FileName [bbrReach.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [BDD-based reachability analysis.] |
| |
| Synopsis [Procedures to perform reachability analysis.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - June 20, 2005.] |
| |
| Revision [$Id: bbrReach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "bbr.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| extern Abc_Cex_t * Aig_ManVerifyUsingBddsCountExample( Aig_Man_t * p, DdManager * dd, |
| DdNode ** pbParts, Vec_Ptr_t * vOnionRings, DdNode * bCubeFirst, |
| int iOutput, int fVerbose, int fSilent ); |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [This procedure sets default resynthesis parameters.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Bbr_ManSetDefaultParams( Saig_ParBbr_t * p ) |
| { |
| memset( p, 0, sizeof(Saig_ParBbr_t) ); |
| p->TimeLimit = 0; |
| p->nBddMax = 50000; |
| p->nIterMax = 1000; |
| p->fPartition = 1; |
| p->fReorder = 1; |
| p->fReorderImage = 1; |
| p->fVerbose = 0; |
| p->fSilent = 0; |
| p->iFrame = -1; |
| } |
| |
| /**Function******************************************************************** |
| |
| Synopsis [Performs the reordering-sensitive step of Extra_bddMove().] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ******************************************************************************/ |
| DdNode * Bbr_bddComputeRangeCube( DdManager * dd, int iStart, int iStop ) |
| { |
| DdNode * bTemp, * bProd; |
| int i; |
| assert( iStart <= iStop ); |
| assert( iStart >= 0 && iStart <= dd->size ); |
| assert( iStop >= 0 && iStop <= dd->size ); |
| bProd = (dd)->one; Cudd_Ref( bProd ); |
| for ( i = iStart; i < iStop; i++ ) |
| { |
| bProd = Cudd_bddAnd( dd, bTemp = bProd, dd->vars[i] ); Cudd_Ref( bProd ); |
| Cudd_RecursiveDeref( dd, bTemp ); |
| } |
| Cudd_Deref( bProd ); |
| return bProd; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Bbr_StopManager( DdManager * dd ) |
| { |
| int RetValue; |
| // check for remaining references in the package |
| RetValue = Cudd_CheckZeroRef( dd ); |
| if ( RetValue > 0 ) |
| printf( "\nThe number of referenced nodes = %d\n\n", RetValue ); |
| // Cudd_PrintInfo( dd, stdout ); |
| Cudd_Quit( dd ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes the initial state and sets up the variable map.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| DdNode * Aig_ManInitStateVarMap( DdManager * dd, Aig_Man_t * p, int fVerbose ) |
| { |
| DdNode ** pbVarsX, ** pbVarsY; |
| DdNode * bTemp, * bProd; |
| Aig_Obj_t * pLatch; |
| int i; |
| |
| // set the variable mapping for Cudd_bddVarMap() |
| pbVarsX = ABC_ALLOC( DdNode *, dd->size ); |
| pbVarsY = ABC_ALLOC( DdNode *, dd->size ); |
| bProd = (dd)->one; Cudd_Ref( bProd ); |
| Saig_ManForEachLo( p, pLatch, i ) |
| { |
| pbVarsX[i] = dd->vars[ Saig_ManPiNum(p) + i ]; |
| pbVarsY[i] = dd->vars[ Saig_ManCiNum(p) + i ]; |
| // get the initial value of the latch |
| bProd = Cudd_bddAnd( dd, bTemp = bProd, Cudd_Not(pbVarsX[i]) ); Cudd_Ref( bProd ); |
| Cudd_RecursiveDeref( dd, bTemp ); |
| } |
| Cudd_SetVarMap( dd, pbVarsX, pbVarsY, Saig_ManRegNum(p) ); |
| ABC_FREE( pbVarsX ); |
| ABC_FREE( pbVarsY ); |
| |
| Cudd_Deref( bProd ); |
| return bProd; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Collects the array of output BDDs.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| DdNode ** Aig_ManCreateOutputs( DdManager * dd, Aig_Man_t * p ) |
| { |
| DdNode ** pbOutputs; |
| Aig_Obj_t * pNode; |
| int i; |
| // compute the transition relation |
| pbOutputs = ABC_ALLOC( DdNode *, Saig_ManPoNum(p) ); |
| Saig_ManForEachPo( p, pNode, i ) |
| { |
| pbOutputs[i] = Aig_ObjGlobalBdd(pNode); Cudd_Ref( pbOutputs[i] ); |
| } |
| return pbOutputs; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Collects the array of partition BDDs.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| DdNode ** Aig_ManCreatePartitions( DdManager * dd, Aig_Man_t * p, int fReorder, int fVerbose ) |
| { |
| DdNode ** pbParts; |
| DdNode * bVar; |
| Aig_Obj_t * pNode; |
| int i; |
| |
| // extand the BDD manager to represent NS variables |
| assert( dd->size == Saig_ManCiNum(p) ); |
| Cudd_bddIthVar( dd, Saig_ManCiNum(p) + Saig_ManRegNum(p) - 1 ); |
| |
| // enable reordering |
| if ( fReorder ) |
| Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); |
| else |
| Cudd_AutodynDisable( dd ); |
| |
| // compute the transition relation |
| pbParts = ABC_ALLOC( DdNode *, Saig_ManRegNum(p) ); |
| Saig_ManForEachLi( p, pNode, i ) |
| { |
| bVar = Cudd_bddIthVar( dd, Saig_ManCiNum(p) + i ); |
| pbParts[i] = Cudd_bddXnor( dd, bVar, Aig_ObjGlobalBdd(pNode) ); Cudd_Ref( pbParts[i] ); |
| } |
| // free global BDDs |
| Aig_ManFreeGlobalBdds( p, dd ); |
| |
| // reorder and disable reordering |
| if ( fReorder ) |
| { |
| if ( fVerbose ) |
| fprintf( stdout, "BDD nodes in the partitions before reordering %d.\n", Cudd_SharingSize(pbParts,Saig_ManRegNum(p)) ); |
| Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); |
| Cudd_AutodynDisable( dd ); |
| if ( fVerbose ) |
| fprintf( stdout, "BDD nodes in the partitions after reordering %d.\n", Cudd_SharingSize(pbParts,Saig_ManRegNum(p)) ); |
| } |
| return pbParts; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes the set of unreachable states.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Aig_ManComputeReachable( DdManager * dd, Aig_Man_t * p, DdNode ** pbParts, DdNode * bInitial, DdNode ** pbOutputs, Saig_ParBbr_t * pPars, int fCheckOutputs ) |
| { |
| int fInternalReorder = 0; |
| Bbr_ImageTree_t * pTree = NULL; // Suppress "might be used uninitialized" |
| Bbr_ImageTree2_t * pTree2 = NULL; // Supprses "might be used uninitialized" |
| DdNode * bReached, * bCubeCs; |
| DdNode * bCurrent; |
| DdNode * bNext = NULL; // Suppress "might be used uninitialized" |
| DdNode * bTemp; |
| Cudd_ReorderingType method; |
| int i, nIters, nBddSize = 0, status; |
| int nThreshold = 10000; |
| abctime clk = Abc_Clock(); |
| Vec_Ptr_t * vOnionRings; |
| int fixedPoint = 0; |
| |
| status = Cudd_ReorderingStatus( dd, &method ); |
| if ( status ) |
| Cudd_AutodynDisable( dd ); |
| |
| // start the image computation |
| bCubeCs = Bbr_bddComputeRangeCube( dd, Saig_ManPiNum(p), Saig_ManCiNum(p) ); Cudd_Ref( bCubeCs ); |
| if ( pPars->fPartition ) |
| pTree = Bbr_bddImageStart( dd, bCubeCs, Saig_ManRegNum(p), pbParts, Saig_ManRegNum(p), dd->vars+Saig_ManCiNum(p), pPars->nBddMax, pPars->fVerbose ); |
| else |
| pTree2 = Bbr_bddImageStart2( dd, bCubeCs, Saig_ManRegNum(p), pbParts, Saig_ManRegNum(p), dd->vars+Saig_ManCiNum(p), pPars->fVerbose ); |
| Cudd_RecursiveDeref( dd, bCubeCs ); |
| if ( pTree == NULL ) |
| { |
| if ( !pPars->fSilent ) |
| printf( "BDDs blew up during qualitification scheduling. " ); |
| return -1; |
| } |
| |
| if ( status ) |
| Cudd_AutodynEnable( dd, method ); |
| |
| // start the onion rings |
| vOnionRings = Vec_PtrAlloc( 1000 ); |
| |
| // perform reachability analysis |
| bCurrent = bInitial; Cudd_Ref( bCurrent ); |
| bReached = bInitial; Cudd_Ref( bReached ); |
| Vec_PtrPush( vOnionRings, bCurrent ); Cudd_Ref( bCurrent ); |
| for ( nIters = 0; nIters < pPars->nIterMax; nIters++ ) |
| { |
| // check the runtime limit |
| if ( pPars->TimeLimit && pPars->TimeLimit <= (Abc_Clock()-clk)/CLOCKS_PER_SEC ) |
| { |
| printf( "Reached timeout after image computation (%d seconds).\n", pPars->TimeLimit ); |
| Vec_PtrFree( vOnionRings ); |
| // undo the image tree |
| if ( pPars->fPartition ) |
| Bbr_bddImageTreeDelete( pTree ); |
| else |
| Bbr_bddImageTreeDelete2( pTree2 ); |
| pPars->iFrame = nIters - 1; |
| return -1; |
| } |
| |
| // compute the next states |
| if ( pPars->fPartition ) |
| bNext = Bbr_bddImageCompute( pTree, bCurrent ); |
| else |
| bNext = Bbr_bddImageCompute2( pTree2, bCurrent ); |
| if ( bNext == NULL ) |
| { |
| if ( !pPars->fSilent ) |
| printf( "BDDs blew up during image computation. " ); |
| if ( pPars->fPartition ) |
| Bbr_bddImageTreeDelete( pTree ); |
| else |
| Bbr_bddImageTreeDelete2( pTree2 ); |
| Vec_PtrFree( vOnionRings ); |
| pPars->iFrame = nIters - 1; |
| return -1; |
| } |
| Cudd_Ref( bNext ); |
| Cudd_RecursiveDeref( dd, bCurrent ); |
| |
| // remap these states into the current state vars |
| bNext = Cudd_bddVarMap( dd, bTemp = bNext ); Cudd_Ref( bNext ); |
| Cudd_RecursiveDeref( dd, bTemp ); |
| // check if there are any new states |
| if ( Cudd_bddLeq( dd, bNext, bReached ) ) { |
| fixedPoint = 1; |
| break; |
| } |
| // check the BDD size |
| nBddSize = Cudd_DagSize(bNext); |
| if ( nBddSize > pPars->nBddMax ) |
| break; |
| // check the result |
| for ( i = 0; i < Saig_ManPoNum(p); i++ ) |
| { |
| if ( fCheckOutputs && !Cudd_bddLeq( dd, bNext, Cudd_Not(pbOutputs[i]) ) ) |
| { |
| DdNode * bIntersect; |
| bIntersect = Cudd_bddIntersect( dd, bNext, pbOutputs[i] ); Cudd_Ref( bIntersect ); |
| assert( p->pSeqModel == NULL ); |
| p->pSeqModel = Aig_ManVerifyUsingBddsCountExample( p, dd, pbParts, |
| vOnionRings, bIntersect, i, pPars->fVerbose, pPars->fSilent ); |
| Cudd_RecursiveDeref( dd, bIntersect ); |
| if ( !pPars->fSilent ) |
| Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", i, p->pName, Vec_PtrSize(vOnionRings) ); |
| Cudd_RecursiveDeref( dd, bReached ); |
| bReached = NULL; |
| pPars->iFrame = nIters; |
| break; |
| } |
| } |
| if ( i < Saig_ManPoNum(p) ) |
| break; |
| // get the new states |
| bCurrent = Cudd_bddAnd( dd, bNext, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); |
| Vec_PtrPush( vOnionRings, bCurrent ); Cudd_Ref( bCurrent ); |
| // minimize the new states with the reached states |
| // bCurrent = Cudd_bddConstrain( dd, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); |
| // Cudd_RecursiveDeref( dd, bTemp ); |
| // add to the reached states |
| bReached = Cudd_bddOr( dd, bTemp = bReached, bNext ); Cudd_Ref( bReached ); |
| Cudd_RecursiveDeref( dd, bTemp ); |
| Cudd_RecursiveDeref( dd, bNext ); |
| if ( pPars->fVerbose ) |
| fprintf( stdout, "Frame = %3d. BDD = %5d. ", nIters, nBddSize ); |
| if ( fInternalReorder && pPars->fReorder && nBddSize > nThreshold ) |
| { |
| if ( pPars->fVerbose ) |
| fprintf( stdout, "Reordering... Before = %5d. ", Cudd_DagSize(bReached) ); |
| Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); |
| Cudd_AutodynDisable( dd ); |
| if ( pPars->fVerbose ) |
| fprintf( stdout, "After = %5d.\r", Cudd_DagSize(bReached) ); |
| nThreshold *= 2; |
| } |
| if ( pPars->fVerbose ) |
| // fprintf( stdout, "\r" ); |
| fprintf( stdout, "\n" ); |
| |
| if ( pPars->fVerbose ) |
| { |
| double nMints = Cudd_CountMinterm(dd, bReached, Saig_ManRegNum(p) ); |
| // Extra_bddPrint( dd, bReached );printf( "\n" ); |
| fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p)) ); |
| fflush( stdout ); |
| } |
| |
| } |
| Cudd_RecursiveDeref( dd, bNext ); |
| // free the onion rings |
| Vec_PtrForEachEntry( DdNode *, vOnionRings, bTemp, i ) |
| Cudd_RecursiveDeref( dd, bTemp ); |
| Vec_PtrFree( vOnionRings ); |
| // undo the image tree |
| if ( pPars->fPartition ) |
| Bbr_bddImageTreeDelete( pTree ); |
| else |
| Bbr_bddImageTreeDelete2( pTree2 ); |
| if ( bReached == NULL ) |
| return 0; // proved reachable |
| // report the stats |
| if ( pPars->fVerbose ) |
| { |
| double nMints = Cudd_CountMinterm(dd, bReached, Saig_ManRegNum(p) ); |
| if ( nIters > pPars->nIterMax || nBddSize > 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)) ); |
| fflush( stdout ); |
| } |
| //ABC_PRB( dd, bReached ); |
| Cudd_RecursiveDeref( dd, bReached ); |
| // SPG |
| // |
| if ( fixedPoint ) { |
| if ( !pPars->fSilent ) { |
| printf( "The miter is proved unreachable after %d iterations. ", nIters ); |
| } |
| pPars->iFrame = nIters - 1; |
| return 1; |
| } |
| assert(nIters >= pPars->nIterMax || nBddSize >= pPars->nBddMax); |
| if ( !pPars->fSilent ) |
| printf( "Verified only for states reachable in %d frames. ", nIters ); |
| pPars->iFrame = nIters - 1; |
| return -1; // undecided |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Performs reachability to see if any PO can be asserted.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Aig_ManVerifyUsingBdds_int( Aig_Man_t * p, Saig_ParBbr_t * pPars ) |
| { |
| int fCheckOutputs = !pPars->fSkipOutCheck; |
| DdManager * dd; |
| DdNode ** pbParts, ** pbOutputs; |
| DdNode * bInitial, * bTemp; |
| int RetValue, i; |
| abctime clk = Abc_Clock(); |
| Vec_Ptr_t * vOnionRings; |
| |
| assert( Saig_ManRegNum(p) > 0 ); |
| |
| // compute the global BDDs of the latches |
| dd = Aig_ManComputeGlobalBdds( p, pPars->nBddMax, 1, pPars->fReorder, pPars->fVerbose ); |
| if ( dd == NULL ) |
| { |
| if ( !pPars->fSilent ) |
| printf( "The number of intermediate BDD nodes exceeded the limit (%d).\n", pPars->nBddMax ); |
| return -1; |
| } |
| if ( pPars->fVerbose ) |
| printf( "Shared BDD size is %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); |
| |
| // check the runtime limit |
| if ( pPars->TimeLimit && pPars->TimeLimit <= (Abc_Clock()-clk)/CLOCKS_PER_SEC ) |
| { |
| printf( "Reached timeout after constructing global BDDs (%d seconds).\n", pPars->TimeLimit ); |
| Cudd_Quit( dd ); |
| return -1; |
| } |
| |
| // start the onion rings |
| vOnionRings = Vec_PtrAlloc( 1000 ); |
| |
| // save outputs |
| pbOutputs = Aig_ManCreateOutputs( dd, p ); |
| |
| // create partitions |
| pbParts = Aig_ManCreatePartitions( dd, p, pPars->fReorder, pPars->fVerbose ); |
| |
| // create the initial state and the variable map |
| bInitial = Aig_ManInitStateVarMap( dd, p, pPars->fVerbose ); Cudd_Ref( bInitial ); |
| |
| // set reordering |
| if ( pPars->fReorderImage ) |
| Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); |
| |
| // check the result |
| RetValue = -1; |
| for ( i = 0; i < Saig_ManPoNum(p); i++ ) |
| { |
| if ( fCheckOutputs && !Cudd_bddLeq( dd, bInitial, Cudd_Not(pbOutputs[i]) ) ) |
| { |
| DdNode * bIntersect; |
| bIntersect = Cudd_bddIntersect( dd, bInitial, pbOutputs[i] ); Cudd_Ref( bIntersect ); |
| assert( p->pSeqModel == NULL ); |
| p->pSeqModel = Aig_ManVerifyUsingBddsCountExample( p, dd, pbParts, |
| vOnionRings, bIntersect, i, pPars->fVerbose, pPars->fSilent ); |
| Cudd_RecursiveDeref( dd, bIntersect ); |
| if ( !pPars->fSilent ) |
| Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", i, p->pName, -1 ); |
| RetValue = 0; |
| break; |
| } |
| } |
| // free the onion rings |
| Vec_PtrForEachEntry( DdNode *, vOnionRings, bTemp, i ) |
| Cudd_RecursiveDeref( dd, bTemp ); |
| Vec_PtrFree( vOnionRings ); |
| // explore reachable states |
| if ( RetValue == -1 ) |
| RetValue = Aig_ManComputeReachable( dd, p, pbParts, bInitial, pbOutputs, pPars, fCheckOutputs ); |
| |
| // cleanup |
| Cudd_RecursiveDeref( dd, bInitial ); |
| for ( i = 0; i < Saig_ManRegNum(p); i++ ) |
| Cudd_RecursiveDeref( dd, pbParts[i] ); |
| ABC_FREE( pbParts ); |
| for ( i = 0; i < Saig_ManPoNum(p); i++ ) |
| Cudd_RecursiveDeref( dd, pbOutputs[i] ); |
| ABC_FREE( pbOutputs ); |
| // if ( RetValue == -1 ) |
| Cudd_Quit( dd ); |
| // else |
| // Bbr_StopManager( dd ); |
| |
| // report the runtime |
| if ( !pPars->fSilent ) |
| { |
| ABC_PRT( "Time", Abc_Clock() - clk ); |
| fflush( stdout ); |
| } |
| return RetValue; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Performs reachability to see if any PO can be asserted.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Aig_ManVerifyUsingBdds( Aig_Man_t * pInit, Saig_ParBbr_t * pPars ) |
| { |
| Abc_Cex_t * pCexOld, * pCexNew; |
| Aig_Man_t * p; |
| Aig_Obj_t * pObj; |
| Vec_Int_t * vInputMap; |
| int i, k, Entry, iBitOld, iBitNew, RetValue; |
| // pPars->fVerbose = 1; |
| // check if there are PIs without fanout |
| Saig_ManForEachPi( pInit, pObj, i ) |
| if ( Aig_ObjRefs(pObj) == 0 ) |
| break; |
| if ( i == Saig_ManPiNum(pInit) ) |
| return Aig_ManVerifyUsingBdds_int( pInit, pPars ); |
| // create new AIG |
| p = Aig_ManDupTrim( pInit ); |
| assert( Aig_ManCiNum(p) < Aig_ManCiNum(pInit) ); |
| assert( Aig_ManRegNum(p) == Aig_ManRegNum(pInit) ); |
| RetValue = Aig_ManVerifyUsingBdds_int( p, pPars ); |
| if ( RetValue != 0 ) |
| { |
| Aig_ManStop( p ); |
| return RetValue; |
| } |
| // the problem is satisfiable - remap the pattern |
| pCexOld = p->pSeqModel; |
| assert( pCexOld != NULL ); |
| // create input map |
| vInputMap = Vec_IntAlloc( Saig_ManPiNum(pInit) ); |
| Saig_ManForEachPi( pInit, pObj, i ) |
| if ( pObj->pData != NULL ) |
| Vec_IntPush( vInputMap, Aig_ObjCioId((Aig_Obj_t *)pObj->pData) ); |
| else |
| Vec_IntPush( vInputMap, -1 ); |
| // create new pattern |
| pCexNew = Abc_CexAlloc( Saig_ManRegNum(pInit), Saig_ManPiNum(pInit), pCexOld->iFrame+1 ); |
| pCexNew->iFrame = pCexOld->iFrame; |
| pCexNew->iPo = pCexOld->iPo; |
| // copy the bit-data |
| for ( iBitOld = 0; iBitOld < pCexOld->nRegs; iBitOld++ ) |
| if ( Abc_InfoHasBit( pCexOld->pData, iBitOld ) ) |
| Abc_InfoSetBit( pCexNew->pData, iBitOld ); |
| // copy the primary input data |
| iBitNew = iBitOld; |
| for ( i = 0; i <= pCexNew->iFrame; i++ ) |
| { |
| Vec_IntForEachEntry( vInputMap, Entry, k ) |
| { |
| if ( Entry == -1 ) |
| continue; |
| if ( Abc_InfoHasBit( pCexOld->pData, iBitOld + Entry ) ) |
| Abc_InfoSetBit( pCexNew->pData, iBitNew + k ); |
| } |
| iBitOld += Saig_ManPiNum(p); |
| iBitNew += Saig_ManPiNum(pInit); |
| } |
| assert( iBitOld < iBitNew ); |
| assert( iBitOld == pCexOld->nBits ); |
| assert( iBitNew == pCexNew->nBits ); |
| Vec_IntFree( vInputMap ); |
| pInit->pSeqModel = pCexNew; |
| Aig_ManStop( p ); |
| return 0; |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |