/**CFile**************************************************************** FileName [kLiveConstraints.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Liveness property checking.] Synopsis [Constraint analysis module for the k-Liveness algorithm invented by Koen Classen, Niklas Sorensson.] Author [Sayak Ray] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - October 31, 2012.] Revision [$Id: liveness.c,v 1.00 2009/01/01 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include "base/main/main.h" #include "aig/aig/aig.h" #include "aig/saig/saig.h" #include #include "base/main/mainInt.h" #include "proof/pdr/pdr.h" ABC_NAMESPACE_IMPL_START extern Aig_Man_t *Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); //extern Aig_Man_t *createDisjunctiveMonotoneTester(Aig_Man_t *pAig, struct aigPoIndices *aigPoIndicesArg, struct monotoneVectorsStruct *monotoneVectorArg, int *startMonotonePropPo); struct aigPoIndices { int attrPendingSignalIndex; int attrHintSingalBeginningMarker; int attrHintSingalEndMarker; int attrSafetyInvarIndex; }; struct aigPoIndices *allocAigPoIndices() { struct aigPoIndices *newAigPoIndices; newAigPoIndices = (struct aigPoIndices *)malloc(sizeof (struct aigPoIndices)); newAigPoIndices->attrPendingSignalIndex = -1; newAigPoIndices->attrHintSingalBeginningMarker = -1; newAigPoIndices->attrHintSingalEndMarker = -1; newAigPoIndices->attrSafetyInvarIndex = -1; assert( newAigPoIndices != NULL ); return newAigPoIndices; } void deallocAigPoIndices(struct aigPoIndices *toBeDeletedAigPoIndices) { assert(toBeDeletedAigPoIndices != NULL ); free(toBeDeletedAigPoIndices); } struct monotoneVectorsStruct { Vec_Int_t *attrKnownMonotone; Vec_Int_t *attrCandMonotone; Vec_Int_t *attrHintMonotone; }; struct monotoneVectorsStruct *allocPointersToMonotoneVectors() { struct monotoneVectorsStruct *newPointersToMonotoneVectors; newPointersToMonotoneVectors = (struct monotoneVectorsStruct *)malloc(sizeof (struct monotoneVectorsStruct)); newPointersToMonotoneVectors->attrKnownMonotone = NULL; newPointersToMonotoneVectors->attrCandMonotone = NULL; newPointersToMonotoneVectors->attrHintMonotone = NULL; assert( newPointersToMonotoneVectors != NULL ); return newPointersToMonotoneVectors; } void deallocPointersToMonotoneVectors(struct monotoneVectorsStruct *toBeDeleted) { assert( toBeDeleted != NULL ); free( toBeDeleted ); } Vec_Int_t *findHintOutputs(Abc_Ntk_t *pNtk) { int i, numElementPush = 0; Abc_Obj_t *pNode; Vec_Int_t *vHintPoIntdex; vHintPoIntdex = Vec_IntAlloc(0); Abc_NtkForEachPo( pNtk, pNode, i ) { if( strstr( Abc_ObjName( pNode ), "hint_" ) != NULL ) { Vec_IntPush( vHintPoIntdex, i ); numElementPush++; } } if( numElementPush == 0 ) return NULL; else return vHintPoIntdex; } int findPendingSignal(Abc_Ntk_t *pNtk) { int i, pendingSignalIndex = -1; Abc_Obj_t *pNode; Abc_NtkForEachPo( pNtk, pNode, i ) { if( strstr( Abc_ObjName( pNode ), "pendingSignal" ) != NULL ) { pendingSignalIndex = i; break; } } return pendingSignalIndex; } int checkSanityOfKnownMonotone( Vec_Int_t *vKnownMonotone, Vec_Int_t *vCandMonotone, Vec_Int_t *vHintMonotone ) { int iElem, i; Vec_IntForEachEntry( vKnownMonotone, iElem, i ) printf("%d ", iElem); printf("\n"); Vec_IntForEachEntry( vCandMonotone, iElem, i ) printf("%d ", iElem); printf("\n"); Vec_IntForEachEntry( vHintMonotone, iElem, i ) printf("%d ", iElem); printf("\n"); return 1; } Aig_Man_t *createMonotoneTester(Aig_Man_t *pAig, struct aigPoIndices *aigPoIndicesArg, struct monotoneVectorsStruct *monotoneVectorArg, int *startMonotonePropPo) { Aig_Man_t *pNewAig; int iElem, i, nRegCount, oldPoNum, poSerialNum, iElemHint; int piCopied = 0, liCopied = 0, liCreated = 0, loCopied = 0, loCreated = 0; int poCopied = 0, poCreated = 0; Aig_Obj_t *pObj, *pObjPo, *pObjDriver, *pObjDriverNew, *pObjPendingDriverNew, *pObjPendingAndNextPending; Aig_Obj_t *pPendingFlop, *pHintSignalLo, *pHintMonotoneFlop, *pObjTemp1, *pObjTemp2, *pObjKnownMonotoneAnd; Vec_Ptr_t *vHintMonotoneLocalDriverNew; Vec_Ptr_t *vHintMonotoneLocalFlopOutput; Vec_Ptr_t *vHintMonotoneLocalProp; int pendingSignalIndexLocal = aigPoIndicesArg->attrPendingSignalIndex; int hintSingalBeginningMarkerLocal = aigPoIndicesArg->attrHintSingalBeginningMarker; //int hintSingalEndMarkerLocal = aigPoIndicesArg->attrHintSingalEndMarker; Vec_Int_t *vKnownMonotoneLocal = monotoneVectorArg->attrKnownMonotone; Vec_Int_t *vCandMonotoneLocal = monotoneVectorArg->attrCandMonotone; Vec_Int_t *vHintMonotoneLocal = monotoneVectorArg->attrHintMonotone; //**************************************************************** // Step1: create the new manager // Note: The new manager is created with "2 * Aig_ManObjNumMax(p)" // nodes, but this selection is arbitrary - need to be justified //**************************************************************** pNewAig = Aig_ManStart( Aig_ManObjNumMax(pAig) ); pNewAig->pName = (char *)malloc( strlen( pAig->pName ) + strlen("_monotone") + 1 ); sprintf(pNewAig->pName, "%s_%s", pAig->pName, "_monotone"); pNewAig->pSpec = NULL; //**************************************************************** // Step 2: map constant nodes //**************************************************************** pObj = Aig_ManConst1( pAig ); pObj->pData = Aig_ManConst1( pNewAig ); //**************************************************************** // Step 3: create true PIs //**************************************************************** Saig_ManForEachPi( pAig, pObj, i ) { piCopied++; pObj->pData = Aig_ObjCreateCi(pNewAig); } //**************************************************************** // Step 5: create register outputs //**************************************************************** Saig_ManForEachLo( pAig, pObj, i ) { loCopied++; pObj->pData = Aig_ObjCreateCi(pNewAig); } //**************************************************************** // Step 6: create "D" register output for PENDING flop //**************************************************************** loCreated++; pPendingFlop = Aig_ObjCreateCi( pNewAig ); //**************************************************************** // Step 6.a: create "D" register output for HINT_MONOTONE flop //**************************************************************** vHintMonotoneLocalFlopOutput = Vec_PtrAlloc(Vec_IntSize(vHintMonotoneLocal)); Vec_IntForEachEntry( vHintMonotoneLocal, iElem, i ) { loCreated++; pHintMonotoneFlop = Aig_ObjCreateCi( pNewAig ); Vec_PtrPush( vHintMonotoneLocalFlopOutput, pHintMonotoneFlop ); } nRegCount = loCreated + loCopied; printf("\nnRegCount = %d\n", nRegCount); //******************************************************************** // Step 7: create internal nodes //******************************************************************** Aig_ManForEachNode( pAig, pObj, i ) { pObj->pData = Aig_And( pNewAig, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); } //******************************************************************** // Step 8: mapping appropriate new flop drivers //******************************************************************** pObjPo = Aig_ManCo( pAig, pendingSignalIndexLocal ); pObjDriver = Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObjPo), Aig_ObjFaninC0(pObjPo)); pObjPendingDriverNew = !Aig_IsComplement(pObjDriver)? (Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData) : Aig_Not((Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData)); pObjPendingAndNextPending = Aig_And( pNewAig, pObjPendingDriverNew, pPendingFlop ); oldPoNum = Aig_ManCoNum(pAig) - Aig_ManRegNum(pAig); pObjKnownMonotoneAnd = Aig_ManConst1( pNewAig ); #if 1 if( vKnownMonotoneLocal ) { assert( checkSanityOfKnownMonotone( vKnownMonotoneLocal, vCandMonotoneLocal, vHintMonotoneLocal ) ); Vec_IntForEachEntry( vKnownMonotoneLocal, iElemHint, i ) { iElem = (iElemHint - hintSingalBeginningMarkerLocal) + 1 + pendingSignalIndexLocal; printf("\nProcessing knownMonotone = %d\n", iElem); pObjPo = Aig_ManCo( pAig, iElem ); pObjDriver = Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObjPo), Aig_ObjFaninC0(pObjPo)); pObjDriverNew = !Aig_IsComplement(pObjDriver)? (Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData) : Aig_Not((Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData)); pHintSignalLo = (Aig_Obj_t *)Vec_PtrEntry(vHintMonotoneLocalFlopOutput, iElem - oldPoNum); pObjTemp1 = Aig_Or( pNewAig, Aig_And(pNewAig, pObjDriverNew, pHintSignalLo), Aig_And(pNewAig, Aig_Not(pObjDriverNew), Aig_Not(pHintSignalLo)) ); pObjKnownMonotoneAnd = Aig_And( pNewAig, pObjKnownMonotoneAnd, pObjTemp1 ); } pObjPendingAndNextPending = Aig_And( pNewAig, pObjPendingAndNextPending, pObjKnownMonotoneAnd ); } #endif vHintMonotoneLocalDriverNew = Vec_PtrAlloc(Vec_IntSize(vHintMonotoneLocal)); vHintMonotoneLocalProp = Vec_PtrAlloc(Vec_IntSize(vHintMonotoneLocal)); Vec_IntForEachEntry( vHintMonotoneLocal, iElem, i ) { pObjPo = Aig_ManCo( pAig, iElem ); pObjDriver = Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObjPo), Aig_ObjFaninC0(pObjPo)); pObjDriverNew = !Aig_IsComplement(pObjDriver)? (Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData) : Aig_Not((Aig_Obj_t *)(Aig_Regular(pObjDriver)->pData)); if( vKnownMonotoneLocal != NULL && Vec_IntFind( vKnownMonotoneLocal, iElem ) != -1 ) { Vec_PtrPush(vHintMonotoneLocalDriverNew, pObjDriverNew); } else { poSerialNum = Vec_IntFind( vHintMonotoneLocal, iElem ); pHintSignalLo = (Aig_Obj_t *)Vec_PtrEntry(vHintMonotoneLocalFlopOutput, poSerialNum ); pObjTemp1 = Aig_And( pNewAig, pObjPendingAndNextPending, pHintSignalLo); pObjTemp2 = Aig_Or( pNewAig, Aig_Not(pObjTemp1), pObjDriverNew ); //pObjTemp2 = Aig_Or( pNewAig, Aig_Not(pObjTemp1), Aig_ManConst1( pNewAig )); //pObjTemp2 = Aig_ManConst1( pNewAig ); Vec_PtrPush(vHintMonotoneLocalDriverNew, pObjDriverNew); Vec_PtrPush(vHintMonotoneLocalProp, pObjTemp2); } } //******************************************************************** // Step 9: create primary outputs //******************************************************************** Saig_ManForEachPo( pAig, pObj, i ) { poCopied++; pObj->pData = Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) ); } *startMonotonePropPo = i; Vec_PtrForEachEntry( Aig_Obj_t *, vHintMonotoneLocalProp, pObj, i ) { poCreated++; pObjPo = Aig_ObjCreateCo( pNewAig, pObj ); } //******************************************************************** // Step 9: create latch inputs //******************************************************************** Saig_ManForEachLi( pAig, pObj, i ) { liCopied++; Aig_ObjCreateCo( pNewAig, Aig_ObjChild0Copy(pObj) ); } //******************************************************************** // Step 9.a: create latch input for PENDING_FLOP //******************************************************************** liCreated++; Aig_ObjCreateCo( pNewAig, pObjPendingDriverNew ); //******************************************************************** // Step 9.b: create latch input for MONOTONE_FLOP //******************************************************************** Vec_PtrForEachEntry( Aig_Obj_t *, vHintMonotoneLocalDriverNew, pObj, i ) { liCreated++; Aig_ObjCreateCo( pNewAig, pObj ); } printf("\npoCopied = %d, poCreated = %d\n", poCopied, poCreated); printf("\nliCreated++ = %d\n", liCreated ); Aig_ManSetRegNum( pNewAig, nRegCount ); Aig_ManCleanup( pNewAig ); assert( Aig_ManCheck( pNewAig ) ); assert( loCopied + loCreated == liCopied + liCreated ); printf("\nSaig_ManPoNum = %d\n", Saig_ManPoNum(pNewAig)); return pNewAig; } Vec_Int_t *findNewMonotone( Aig_Man_t *pAig, struct aigPoIndices *aigPoIndicesArg, struct monotoneVectorsStruct *monotoneVectorArg ) { Aig_Man_t *pAigNew; Aig_Obj_t *pObjTargetPo; int poMarker, oldPoNum; int i, RetValue; Pdr_Par_t Pars, * pPars = &Pars; Abc_Cex_t * pCex = NULL; Vec_Int_t *vMonotoneIndex; int pendingSignalIndexLocal = aigPoIndicesArg->attrPendingSignalIndex; int hintSingalBeginningMarkerLocal = aigPoIndicesArg->attrHintSingalBeginningMarker; //int hintSingalEndMarkerLocal = aigPoIndicesArg->attrHintSingalEndMarker; //Vec_Int_t *vKnownMonotoneLocal = monotoneVectorArg->attrKnownMonotone; //Vec_Int_t *vCandMonotoneLocal = monotoneVectorArg->attrCandMonotone; //Vec_Int_t *vHintMonotoneLocal = monotoneVectorArg->attrHintMonotone; pAigNew = createMonotoneTester(pAig, aigPoIndicesArg, monotoneVectorArg, &poMarker ); oldPoNum = Aig_ManCoNum(pAig) - Aig_ManRegNum(pAig); vMonotoneIndex = Vec_IntAlloc(0); printf("\nSaig_ManPoNum(pAigNew) = %d, poMarker = %d\n", Saig_ManPoNum(pAigNew), poMarker); for( i=poMarker; ifVerbose = 0; //pPars->iOutput = i; //RetValue = Pdr_ManSolve( pAigNew, pPars, &pCex ); RetValue = Pdr_ManSolve( pAigNew, pPars ); if( RetValue == 1 ) { printf("\ni = %d, RetValue = %d : %s (Frame %d)\n", i - oldPoNum + hintSingalBeginningMarkerLocal, RetValue, "Property Proved", pCex? (pCex)->iFrame : -1 ); Vec_IntPush( vMonotoneIndex, i - (pendingSignalIndexLocal + 1) + hintSingalBeginningMarkerLocal); } Aig_ObjChild0Flip( pObjTargetPo ); } if( Vec_IntSize( vMonotoneIndex ) > 0 ) return vMonotoneIndex; else return NULL; } Vec_Int_t *findRemainingMonotoneCandidates(Vec_Int_t *vKnownMonotone, Vec_Int_t *vHintMonotone) { Vec_Int_t *vCandMonotone; int iElem, i; if( vKnownMonotone == NULL || Vec_IntSize(vKnownMonotone) <= 0 ) return vHintMonotone; vCandMonotone = Vec_IntAlloc(0); Vec_IntForEachEntry( vHintMonotone, iElem, i ) { if( Vec_IntFind( vKnownMonotone, iElem ) == -1 ) Vec_IntPush( vCandMonotone, iElem ); } return vCandMonotone; } Vec_Int_t *findMonotoneSignals( Abc_Ntk_t *pNtk ) { Aig_Man_t *pAig; Vec_Int_t *vCandidateMonotoneSignals; Vec_Int_t *vKnownMonotoneSignals; //Vec_Int_t *vKnownMonotoneSignalsNew; //Vec_Int_t *vRemainingCanMonotone; int i, iElem; int pendingSignalIndex; Abc_Ntk_t *pNtkTemp; int hintSingalBeginningMarker; int hintSingalEndMarker; struct aigPoIndices *aigPoIndicesInstance; struct monotoneVectorsStruct *monotoneVectorsInstance; /*******************************************/ //Finding the PO index of the pending signal /*******************************************/ pendingSignalIndex = findPendingSignal(pNtk); if( pendingSignalIndex == -1 ) { printf("\nNo Pending Signal Found\n"); return NULL; } else printf("Po[%d] = %s\n", pendingSignalIndex, Abc_ObjName( Abc_NtkPo(pNtk, pendingSignalIndex) ) ); /*******************************************/ //Finding the PO indices of all hint signals /*******************************************/ vCandidateMonotoneSignals = findHintOutputs(pNtk); if( vCandidateMonotoneSignals == NULL ) return NULL; else { Vec_IntForEachEntry( vCandidateMonotoneSignals, iElem, i ) printf("Po[%d] = %s\n", iElem, Abc_ObjName( Abc_NtkPo(pNtk, iElem) ) ); hintSingalBeginningMarker = Vec_IntEntry( vCandidateMonotoneSignals, 0 ); hintSingalEndMarker = Vec_IntEntry( vCandidateMonotoneSignals, Vec_IntSize(vCandidateMonotoneSignals) - 1 ); } /**********************************************/ //Allocating "struct" with necessary parameters /**********************************************/ aigPoIndicesInstance = allocAigPoIndices(); aigPoIndicesInstance->attrPendingSignalIndex = pendingSignalIndex; aigPoIndicesInstance->attrHintSingalBeginningMarker = hintSingalBeginningMarker; aigPoIndicesInstance->attrHintSingalEndMarker = hintSingalEndMarker; /****************************************************/ //Allocating "struct" with necessary monotone vectors /****************************************************/ monotoneVectorsInstance = allocPointersToMonotoneVectors(); monotoneVectorsInstance->attrCandMonotone = vCandidateMonotoneSignals; monotoneVectorsInstance->attrHintMonotone = vCandidateMonotoneSignals; /*******************************************/ //Generate AIG from Ntk /*******************************************/ if( !Abc_NtkIsStrash( pNtk ) ) { pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); } else { pAig = Abc_NtkToDar( pNtk, 0, 1 ); pNtkTemp = pNtk; } /*******************************************/ //finding LEVEL 1 monotone signals /*******************************************/ vKnownMonotoneSignals = findNewMonotone( pAig, aigPoIndicesInstance, monotoneVectorsInstance ); monotoneVectorsInstance->attrKnownMonotone = vKnownMonotoneSignals; /*******************************************/ //finding LEVEL >1 monotone signals /*******************************************/ #if 0 if( vKnownMonotoneSignals ) { printf("\nsize = %d\n", Vec_IntSize(vKnownMonotoneSignals) ); vRemainingCanMonotone = findRemainingMonotoneCandidates(vKnownMonotoneSignals, vCandidateMonotoneSignals); monotoneVectorsInstance->attrCandMonotone = vRemainingCanMonotone; vKnownMonotoneSignalsNew = findNewMonotone( pAig, aigPoIndicesInstance, monotoneVectorsInstance ); } #endif deallocAigPoIndices(aigPoIndicesInstance); deallocPointersToMonotoneVectors(monotoneVectorsInstance); return NULL; } ABC_NAMESPACE_IMPL_END