diff options
Diffstat (limited to 'src/base/wlc/wlcAbs2.c')
-rw-r--r-- | src/base/wlc/wlcAbs2.c | 298 |
1 files changed, 256 insertions, 42 deletions
diff --git a/src/base/wlc/wlcAbs2.c b/src/base/wlc/wlcAbs2.c index f5a7b46d..9bccdf62 100644 --- a/src/base/wlc/wlcAbs2.c +++ b/src/base/wlc/wlcAbs2.c @@ -19,6 +19,9 @@ ***********************************************************************/ #include "wlc.h" +#include "proof/pdr/pdr.h" +#include "aig/gia/giaAig.h" +#include "sat/bmc/bmc.h" ABC_NAMESPACE_IMPL_START @@ -26,56 +29,31 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -typedef struct Wabs_Par_t_ Wabs_Par_t; -struct Wabs_Par_t_ -{ - Wlc_Ntk_t * pNtk; - Wlc_Par_t * pPars; - Vec_Bit_t * vLeaves; -}; - //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Wlc_ManSetDefaultParams( Wlc_Par_t * pPars ) -{ - memset( pPars, 0, sizeof(Wlc_Par_t) ); - pPars->nBitsAdd = ABC_INFINITY; // adder bit-width - pPars->nBitsMul = ABC_INFINITY; // multiplier bit-widht - pPars->nBitsMux = ABC_INFINITY; // MUX bit-width - pPars->nBitsFlop = ABC_INFINITY; // flop bit-width - pPars->fVerbose = 0; // verbose output` -} - -/**Function************************************************************* - - Synopsis [Mark operators that meet the criteria.] + Synopsis [Mark operators that meet the abstraction criteria.] - Description [] + Description [This procedure returns the array of objects (vLeaves) that + should be abstracted because of their high bit-width. It uses input array (vUnmark) + to not abstract those objects that have been refined in the previous rounds.] SideEffects [] SeeAlso [] ***********************************************************************/ -Vec_Bit_t * Wlc_NtkAbsMarkOpers( Wlc_Ntk_t * p, Wlc_Par_t * pPars ) +static Vec_Bit_t * Wlc_NtkAbsMarkOpers( Wlc_Ntk_t * p, Wlc_Par_t * pPars, Vec_Bit_t * vUnmark, int fVerbose ) { Vec_Bit_t * vLeaves = Vec_BitStart( Wlc_NtkObjNumMax(p) ); Wlc_Obj_t * pObj; int i, Count[4] = {0}; Wlc_NtkForEachObj( p, pObj, i ) { + if ( vUnmark && Vec_BitEntry(vUnmark, i) ) // not allow this object to be abstracted away + continue; if ( pObj->Type == WLC_OBJ_ARI_ADD || pObj->Type == WLC_OBJ_ARI_SUB || pObj->Type == WLC_OBJ_ARI_MINUS ) { if ( Wlc_ObjRange(pObj) >= pPars->nBitsAdd ) @@ -101,7 +79,8 @@ Vec_Bit_t * Wlc_NtkAbsMarkOpers( Wlc_Ntk_t * p, Wlc_Par_t * pPars ) continue; } } - printf( "Abstraction engine marked %d adds/subs, %d muls/divs, %d muxes, and %d flops to be abstracted away.\n", Count[0], Count[1], Count[2], Count[3] ); + if ( fVerbose ) + printf( "Abstraction engine marked %d adds/subs, %d muls/divs, %d muxes, and %d flops to be abstracted away.\n", Count[0], Count[1], Count[2], Count[3] ); return vLeaves; } @@ -109,14 +88,17 @@ Vec_Bit_t * Wlc_NtkAbsMarkOpers( Wlc_Ntk_t * p, Wlc_Par_t * pPars ) Synopsis [Marks nodes to be included in the abstracted network.] - Description [] + Description [Marks all objects that will be included in the abstracted model. + Stops at the objects (vLeaves) that are abstracted away. Returns three arrays: + a subset of original PIs (vPisOld), a subset of pseudo-PIs (vPisNew) and the + set of flops present as flops in the abstracted network.] SideEffects [] SeeAlso [] ***********************************************************************/ -void Wlc_NtkAbsMarkNodes_rec( Wlc_Ntk_t * p, Wlc_Obj_t * pObj, Vec_Bit_t * vLeaves, Vec_Int_t * vPisOld, Vec_Int_t * vPisNew, Vec_Int_t * vFlops ) +static void Wlc_NtkAbsMarkNodes_rec( Wlc_Ntk_t * p, Wlc_Obj_t * pObj, Vec_Bit_t * vLeaves, Vec_Int_t * vPisOld, Vec_Int_t * vPisNew, Vec_Int_t * vFlops ) { int i, iFanin; if ( pObj->Mark ) @@ -139,8 +121,7 @@ void Wlc_NtkAbsMarkNodes_rec( Wlc_Ntk_t * p, Wlc_Obj_t * pObj, Vec_Bit_t * vLeav Wlc_ObjForEachFanin( pObj, iFanin, i ) Wlc_NtkAbsMarkNodes_rec( p, Wlc_NtkObj(p, iFanin), vLeaves, vPisOld, vPisNew, vFlops ); } - -void Wlc_NtkAbsMarkNodes( Wlc_Ntk_t * p, Vec_Bit_t * vLeaves, Vec_Int_t * vPisOld, Vec_Int_t * vPisNew, Vec_Int_t * vFlops ) +static void Wlc_NtkAbsMarkNodes( Wlc_Ntk_t * p, Vec_Bit_t * vLeaves, Vec_Int_t * vPisOld, Vec_Int_t * vPisNew, Vec_Int_t * vFlops ) { Wlc_Obj_t * pObj; int i, Count = 0; @@ -162,31 +143,264 @@ void Wlc_NtkAbsMarkNodes( Wlc_Ntk_t * p, Vec_Bit_t * vLeaves, Vec_Int_t * vPisOl /**Function************************************************************* - Synopsis [Derive abstraction based on the parameter values.] + Synopsis [Derive word-level abstracted model based on the parameter values.] - Description [] + Description [Retuns the word-level abstracted network and the set of pseudo-PIs + (vPisNew), which were created during abstraction. If the abstraction is + satisfiable, some of the pseudo-PIs will be un-abstracted. These pseudo-PIs + and their MFFC cones will be listed in the array (vUnmark), which will + force the abstraction to not stop at these pseudo-PIs in the future.] SideEffects [] SeeAlso [] ***********************************************************************/ -Wlc_Ntk_t * Wlc_NtkAbs( Wlc_Ntk_t * p, Wlc_Par_t * pPars ) +static Wlc_Ntk_t * Wlc_NtkAbs( Wlc_Ntk_t * p, Wlc_Par_t * pPars, Vec_Bit_t * vUnmark, Vec_Int_t ** pvPisNew, int fVerbose ) { Wlc_Ntk_t * pNtkNew = NULL; Vec_Int_t * vPisOld = Vec_IntAlloc( 100 ); Vec_Int_t * vPisNew = Vec_IntAlloc( 100 ); Vec_Int_t * vFlops = Vec_IntAlloc( 100 ); - Vec_Bit_t * vLeaves = Wlc_NtkAbsMarkOpers( p, pPars ); + Vec_Bit_t * vLeaves = Wlc_NtkAbsMarkOpers( p, pPars, vUnmark, fVerbose ); Wlc_NtkAbsMarkNodes( p, vLeaves, vPisOld, vPisNew, vFlops ); Vec_BitFree( vLeaves ); pNtkNew = Wlc_NtkDupDfsAbs( p, vPisOld, vPisNew, vFlops ); Vec_IntFree( vPisOld ); - Vec_IntFree( vPisNew ); Vec_IntFree( vFlops ); + if ( pvPisNew ) + *pvPisNew = vPisNew; + else + Vec_IntFree( vPisNew ); return pNtkNew; } +/**Function************************************************************* + + Synopsis [Find what objects need to be un-abstracted.] + + Description [Returns a subset of pseudo-PIs (vPisNew), which will be + prevented from being abstracted in the future rounds of abstraction. + The AIG manager (pGia) is a bit-level view of the abstracted model. + The counter-example (pCex) is used to find waht PPIs to refine.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Vec_Int_t * Wlc_NtkAbsRefinement( Wlc_Ntk_t * p, Gia_Man_t * pGia, Abc_Cex_t * pCex, Vec_Int_t * vPisNew ) +{ + Vec_Int_t * vRefine = Vec_IntAlloc( 100 ); + Abc_Cex_t * pCexCare; + Wlc_Obj_t * pObj; + // count the number of bit-level PPIs and map them into word-level objects they were derived from + int f, i, b, nRealPis, nPpiBits = 0; + Vec_Int_t * vMap = Vec_IntStartFull( pCex->nPis ); + Wlc_NtkForEachObjVec( vPisNew, p, pObj, i ) + for ( b = 0; b < Wlc_ObjRange(pObj); b++ ) + Vec_IntWriteEntry( vMap, nPpiBits++, Wlc_ObjId(p, pObj) ); + // since PPIs are ordered last, the previous bits are real PIs + nRealPis = pCex->nPis - nPpiBits; + // find the care-set + pCexCare = Bmc_CexCareMinimizeAig( pGia, nRealPis, pCex, 1, 0, 0 ); + assert( pCexCare->nPis == pCex->nPis ); + // detect care PPIs + for ( f = 0; f <= pCexCare->iFrame; f++ ) + for ( i = nRealPis; i < pCexCare->nPis; i++ ) + if ( Abc_InfoHasBit(pCexCare->pData, pCexCare->nRegs + pCexCare->nPis * f + i) ) + Vec_IntPushUniqueOrder( vRefine, Vec_IntEntry(vMap, i-nRealPis) ); + Abc_CexFree( pCexCare ); + Vec_IntFree( vMap ); + if ( Vec_IntSize(vRefine) == 0 )// real CEX + Vec_IntFreeP( &vRefine ); + return vRefine; +} + +/**Function************************************************************* + + Synopsis [Mark MFFC cones of the un-abstracted objects.] + + Description [The MFFC cones of the objects in vRefine are traversed + and all their nodes are marked in vUnmark.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Wlc_NtkNodeDeref_rec( Wlc_Ntk_t * p, Wlc_Obj_t * pNode, Vec_Bit_t * vUnmark ) +{ + int i, Fanin, Counter = 1; + if ( Wlc_ObjIsCi(pNode) ) + return 0; + Vec_BitWriteEntry( vUnmark, Wlc_ObjId(p, pNode), 1 ); + Wlc_ObjForEachFanin( pNode, Fanin, i ) + { + Vec_IntAddToEntry( &p->vRefs, Fanin, -1 ); + if ( Vec_IntEntry(&p->vRefs, Fanin) == 0 ) + Counter += Wlc_NtkNodeDeref_rec( p, Wlc_NtkObj(p, Fanin), vUnmark ); + } + return Counter; +} +static int Wlc_NtkNodeRef_rec( Wlc_Ntk_t * p, Wlc_Obj_t * pNode ) +{ + int i, Fanin, Counter = 1; + if ( Wlc_ObjIsCi(pNode) ) + return 0; + Wlc_ObjForEachFanin( pNode, Fanin, i ) + { + if ( Vec_IntEntry(&p->vRefs, Fanin) == 0 ) + Counter += Wlc_NtkNodeRef_rec( p, Wlc_NtkObj(p, Fanin) ); + Vec_IntAddToEntry( &p->vRefs, Fanin, 1 ); + } + return Counter; +} +static int Wlc_NtkMarkMffc( Wlc_Ntk_t * p, Wlc_Obj_t * pNode, Vec_Bit_t * vUnmark ) +{ + int Count1, Count2; + // if this is a flop output, compute MFFC of the corresponding flop input + while ( Wlc_ObjIsCi(pNode) ) + { + Vec_BitWriteEntry( vUnmark, Wlc_ObjId(p, pNode), 1 ); + pNode = Wlc_ObjFo2Fi(p, pNode); + } + assert( !Wlc_ObjIsCi(pNode) ); + // dereference the node (and set the bits in vUnmark) + Count1 = Wlc_NtkNodeDeref_rec( p, pNode, vUnmark ); + // reference it back + Count2 = Wlc_NtkNodeRef_rec( p, pNode ); + assert( Count1 == Count2 ); + return Count1; +} +static int Wlc_NtkRemoveFromAbstraction( Wlc_Ntk_t * p, Vec_Int_t * vRefine, Vec_Bit_t * vUnmark ) +{ + Wlc_Obj_t * pObj; int i, nNodes = 0; + if ( Vec_IntSize(&p->vRefs) == 0 ) + Wlc_NtkSetRefs( p ); + Wlc_NtkForEachObjVec( vRefine, p, pObj, i ) + nNodes += Wlc_NtkMarkMffc( p, pObj, vUnmark ); + return nNodes; +} + +/**Function************************************************************* + + Synopsis [Performs abstraction.] + + Description [Derives initial abstraction based on user-specified + parameter values, which tell what is the smallest bit-width of a + primitive that is being abstracted away. Currently only add/sub, + mul/div, mux, and flop are supported with individual parameters. + The second step is to refine the initial abstraction until the + point when the property is proved.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Wlc_NtkAbsCore2( Wlc_Ntk_t * p, Wlc_Par_t * pPars ) +{ + abctime clk = Abc_Clock(); + int nIters, nNodes, nDcFlops, RetValue = -1; + // start the bitmap to mark objects that cannot be abstracted because of refinement + // currently, this bitmap is empty because abstraction begins without refinement + Vec_Bit_t * vUnmark = Vec_BitStart( Wlc_NtkObjNumMax(p) ); + // set up parameters to run PDR + Pdr_Par_t PdrPars, * pPdrPars = &PdrPars; + Pdr_ManSetDefaultParams( pPdrPars ); + pPdrPars->fUseAbs = 1; // use 'pdr -t' (on-the-fly abstraction) + pPdrPars->fCtgs = 1; // use 'pdr -nc' (improved generalization) + pPdrPars->fSkipDown = 0; // use 'pdr -nc' (improved generalization) + //pPdrPars->nRestLimit = 500; // reset queue or proof-obligations when it gets larger than this + pPdrPars->fVerbose = pPars->fPdrVerbose; + // perform refinement iterations + for ( nIters = 1; nIters < pPars->nIterMax; nIters++ ) + { + Aig_Man_t * pAig; + Abc_Cex_t * pCex; + Vec_Int_t * vPisNew, * vRefine; + Gia_Man_t * pGia, * pTemp; + Wlc_Ntk_t * pAbs; + + if ( pPars->fVerbose ) + printf( "\nIteration %d:\n", nIters ); + + // get abstracted GIA and the set of pseudo-PIs (vPisNew) + pAbs = Wlc_NtkAbs( p, pPars, vUnmark, &vPisNew, pPars->fVerbose ); + pGia = Wlc_NtkBitBlast( pAbs, NULL, -1, 0, 0, 0, 0 ); + + // if the abstraction has flops with DC-init state, + // new PIs were introduced by bit-blasting at the end of the PI list + // here we move these variables to be *before* PPIs, because + // PPIs are supposed to be at the end of the PI list for refinement + nDcFlops = Wlc_NtkDcFlopNum(pAbs); + if ( nDcFlops > 0 ) // DC-init flops are present + { + pGia = Gia_ManPermuteInputs( pTemp = pGia, Wlc_NtkCountObjBits(p, vPisNew), nDcFlops ); + Gia_ManStop( pTemp ); + } + // if the word-level outputs have to be XORs, this is a place to do it + if ( pPars->fXorOutput ) + { + pGia = Gia_ManTransformMiter2( pTemp = pGia ); + Gia_ManStop( pTemp ); + } + if ( pPars->fVerbose ) + { + printf( "Derived abstraction with %d objects and %d PPIs. Bit-blasted AIG stats are:\n", Wlc_NtkObjNum(pAbs), Vec_IntSize(vPisNew) ); + Gia_ManPrintStats( pGia, NULL ); + } + Wlc_NtkFree( pAbs ); + + // try to prove abstracted GIA by converting it to AIG and calling PDR + pAig = Gia_ManToAigSimple( pGia ); + RetValue = Pdr_ManSolve( pAig, pPdrPars ); + pCex = pAig->pSeqModel; pAig->pSeqModel = NULL; + Aig_ManStop( pAig ); + + // consider outcomes + if ( pCex == NULL ) + { + assert( RetValue ); // proved or undecided + Gia_ManStop( pGia ); + Vec_IntFree( vPisNew ); + break; + } + + // perform refinement + vRefine = Wlc_NtkAbsRefinement( p, pGia, pCex, vPisNew ); + Gia_ManStop( pGia ); + Vec_IntFree( vPisNew ); + if ( vRefine == NULL ) // real CEX + { + Abc_CexFree( pCex ); // return CEX in the future + break; + } + + // update the set of objects to be un-abstracted + nNodes = Wlc_NtkRemoveFromAbstraction( p, vRefine, vUnmark ); + if ( pPars->fVerbose ) + printf( "Refinement of CEX in frame %d came up with %d un-abstacted PPIs, whose MFFCs include %d objects.\n", pCex->iFrame, Vec_IntSize(vRefine), nNodes ); + Vec_IntFree( vRefine ); + Abc_CexFree( pCex ); + } + Vec_BitFree( vUnmark ); + // report the result + if ( pPars->fVerbose ) + printf( "\n" ); + printf( "Abstraction " ); + if ( RetValue == 0 ) + printf( "resulted in a real CEX" ); + else if ( RetValue == 1 ) + printf( "is successfully proved" ); + else + printf( "timed out" ); + printf( " after %d iterations. ", nIters ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return RetValue; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// |