| /**CFile**************************************************************** |
| |
| FileName [liveness.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [Liveness property checking.] |
| |
| Synopsis [Main implementation module.] |
| |
| Author [Sayak Ray] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - January 1, 2009.] |
| |
| Revision [$Id: liveness.c,v 1.00 2009/01/01 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include <stdio.h> |
| #include "base/main/main.h" |
| #include "aig/aig/aig.h" |
| #include "aig/saig/saig.h" |
| #include <string.h> |
| #include "base/main/mainInt.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| #define PROPAGATE_NAMES |
| #define MULTIPLE_LTL_FORMULA |
| #define ALLOW_SAFETY_PROPERTIES |
| |
| #define FULL_BIERE_MODE 0 |
| #define IGNORE_LIVENESS_KEEP_SAFETY_MODE 1 |
| #define IGNORE_SAFETY_KEEP_LIVENESS_MODE 2 |
| #define IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE 3 |
| #define FULL_BIERE_ONE_LOOP_MODE 4 |
| //#define DUPLICATE_CKT_DEBUG |
| |
| extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); |
| extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); |
| //char *strdup(const char *string); |
| |
| //****************************************** |
| //external functions defined in ltl_parser.c |
| //****************************************** |
| typedef struct ltlNode_t ltlNode; |
| extern ltlNode *readLtlFormula( char *formula ); |
| extern void traverseAbstractSyntaxTree( ltlNode *node ); |
| extern ltlNode *parseFormulaCreateAST( char *inputFormula ); |
| extern int isWellFormed( ltlNode *topNode ); |
| extern int checkSignalNameExistence( Abc_Ntk_t *pNtk, ltlNode *topASTNode ); |
| extern void populateBoolWithAigNodePtr( Abc_Ntk_t *pNtk, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, ltlNode *topASTNode ); |
| extern int checkAllBoolHaveAIGPointer( ltlNode *topASTNode ); |
| extern void populateAigPointerUnitGF( Aig_Man_t *pAigNew, ltlNode *topASTNode, Vec_Ptr_t *vSignal, Vec_Vec_t *vAigGFMap ); |
| extern void setAIGNodePtrOfGloballyNode( ltlNode *astNode, Aig_Obj_t *pObjLo ); |
| extern Aig_Obj_t *buildLogicFromLTLNode( Aig_Man_t *pAig, ltlNode *pLtlNode ); |
| extern Aig_Obj_t *retriveAIGPointerFromLTLNode( ltlNode *astNode ); |
| extern void traverseAbstractSyntaxTree_postFix( ltlNode *node ); |
| //********************************** |
| //external function declaration ends |
| //********************************** |
| |
| |
| /******************************************************************* |
| LAYOUT OF PI VECTOR: |
| |
| +------------------------------------------------------------------------------------------------------------------------------------+ |
| | TRUE ORIGINAL PI (n) | SAVE(PI) (1) | ORIGINAL LO (k) | SAVED(LO) (1) | SHADOW_ORIGINAL LO (k) | LIVENESS LO (l) | FAIRNESS LO (f) | |
| +------------------------------------------------------------------------------------------------------------------------------------+ |
| <------------True PI----------------->|<----------------------------LO---------------------------------------------------------------> |
| |
| LAYOUT OF PO VECTOR: |
| |
| +-----------------------------------------------------------------------------------------------------------+ |
| | SOLE PO (1) | ORIGINAL LI (k) | SAVED LI (1) | SHADOW_ORIGINAL LI (k) | LIVENESS LI (l) | FAIRNESS LI (f) | |
| +-----------------------------------------------------------------------------------------------------------+ |
| <--True PO--->|<--------------------------------------LI----------------------------------------------------> |
| |
| ********************************************************************/ |
| |
| |
| static int nodeName_starts_with( Abc_Obj_t *pNode, const char *prefix ) |
| { |
| if( strstr( Abc_ObjName( pNode ), prefix ) == Abc_ObjName( pNode ) ) |
| return 1; |
| else |
| return 0; |
| } |
| |
| void printVecPtrOfString( Vec_Ptr_t *vec ) |
| { |
| int i; |
| |
| for( i=0; i< Vec_PtrSize( vec ); i++ ) |
| { |
| printf("vec[%d] = %s\n", i, (char *)Vec_PtrEntry(vec, i) ); |
| } |
| } |
| |
| int getPoIndex( Aig_Man_t *pAig, Aig_Obj_t *pPivot ) |
| { |
| int i; |
| Aig_Obj_t *pObj; |
| |
| Saig_ManForEachPo( pAig, pObj, i ) |
| { |
| if( pObj == pPivot ) |
| return i; |
| } |
| return -1; |
| } |
| |
| char * retrieveTruePiName( Abc_Ntk_t *pNtkOld, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, Aig_Obj_t *pObjPivot ) |
| { |
| Aig_Obj_t *pObjOld, *pObj; |
| Abc_Obj_t *pNode; |
| int index; |
| |
| assert( Saig_ObjIsPi( pAigNew, pObjPivot ) ); |
| Aig_ManForEachCi( pAigNew, pObj, index ) |
| if( pObj == pObjPivot ) |
| break; |
| assert( index < Aig_ManCiNum( pAigNew ) - Aig_ManRegNum( pAigNew ) ); |
| if( index == Saig_ManPiNum( pAigNew ) - 1 ) |
| return "SAVE_BIERE"; |
| else |
| { |
| pObjOld = Aig_ManCi( pAigOld, index ); |
| pNode = Abc_NtkPi( pNtkOld, index ); |
| assert( pObjOld->pData == pObjPivot ); |
| return Abc_ObjName( pNode ); |
| } |
| } |
| |
| char * retrieveLOName( Abc_Ntk_t *pNtkOld, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, Aig_Obj_t *pObjPivot, Vec_Ptr_t *vLive, Vec_Ptr_t * vFair ) |
| { |
| Aig_Obj_t *pObjOld, *pObj; |
| Abc_Obj_t *pNode; |
| int index, oldIndex, originalLatchNum = Saig_ManRegNum(pAigOld), strMatch, i; |
| char *dummyStr = (char *)malloc( sizeof(char) * 50 ); |
| |
| assert( Saig_ObjIsLo( pAigNew, pObjPivot ) ); |
| Saig_ManForEachLo( pAigNew, pObj, index ) |
| if( pObj == pObjPivot ) |
| break; |
| if( index < originalLatchNum ) |
| { |
| oldIndex = Saig_ManPiNum( pAigOld ) + index; |
| pObjOld = Aig_ManCi( pAigOld, oldIndex ); |
| pNode = Abc_NtkCi( pNtkOld, oldIndex ); |
| assert( pObjOld->pData == pObjPivot ); |
| return Abc_ObjName( pNode ); |
| } |
| else if( index == originalLatchNum ) |
| return "SAVED_LO"; |
| else if( index > originalLatchNum && index < 2 * originalLatchNum + 1 ) |
| { |
| oldIndex = Saig_ManPiNum( pAigOld ) + index - originalLatchNum - 1; |
| pObjOld = Aig_ManCi( pAigOld, oldIndex ); |
| pNode = Abc_NtkCi( pNtkOld, oldIndex ); |
| sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "SHADOW"); |
| return dummyStr; |
| } |
| else if( index >= 2 * originalLatchNum + 1 && index < 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) ) |
| { |
| oldIndex = index - 2 * originalLatchNum - 1; |
| strMatch = 0; |
| dummyStr[0] = '\0'; |
| Saig_ManForEachPo( pAigOld, pObj, i ) |
| { |
| pNode = Abc_NtkPo( pNtkOld, i ); |
| //if( strstr( Abc_ObjName( pNode ), "assert_fair" ) != NULL ) |
| if( nodeName_starts_with( pNode, "assert_fair" ) ) |
| { |
| if( strMatch == oldIndex ) |
| { |
| sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "LIVENESS"); |
| //return dummyStr; |
| break; |
| } |
| else |
| strMatch++; |
| } |
| } |
| assert( dummyStr[0] != '\0' ); |
| return dummyStr; |
| } |
| else if( index >= 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) && index < 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ) |
| { |
| oldIndex = index - 2 * originalLatchNum - 1 - Vec_PtrSize( vLive ); |
| strMatch = 0; |
| dummyStr[0] = '\0'; |
| Saig_ManForEachPo( pAigOld, pObj, i ) |
| { |
| pNode = Abc_NtkPo( pNtkOld, i ); |
| //if( strstr( Abc_ObjName( pNode ), "assume_fair" ) != NULL ) |
| if( nodeName_starts_with( pNode, "assume_fair" ) ) |
| { |
| if( strMatch == oldIndex ) |
| { |
| sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "FAIRNESS"); |
| //return dummyStr; |
| break; |
| } |
| else |
| strMatch++; |
| } |
| } |
| assert( dummyStr[0] != '\0' ); |
| return dummyStr; |
| } |
| else |
| return "UNKNOWN"; |
| } |
| |
| Vec_Ptr_t *vecPis, *vecPiNames; |
| Vec_Ptr_t *vecLos, *vecLoNames; |
| |
| |
| int Aig_ManCiCleanupBiere( Aig_Man_t * p ) |
| { |
| int nPisOld = Aig_ManCiNum(p); |
| |
| p->nObjs[AIG_OBJ_CI] = Vec_PtrSize( p->vCis ); |
| if ( Aig_ManRegNum(p) ) |
| p->nTruePis = Aig_ManCiNum(p) - Aig_ManRegNum(p); |
| |
| return nPisOld - Aig_ManCiNum(p); |
| } |
| |
| |
| int Aig_ManCoCleanupBiere( Aig_Man_t * p ) |
| { |
| int nPosOld = Aig_ManCoNum(p); |
| |
| p->nObjs[AIG_OBJ_CO] = Vec_PtrSize( p->vCos ); |
| if ( Aig_ManRegNum(p) ) |
| p->nTruePos = Aig_ManCoNum(p) - Aig_ManRegNum(p); |
| return nPosOld - Aig_ManCoNum(p); |
| } |
| |
| Aig_Man_t * LivenessToSafetyTransformation( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p, |
| Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety ) |
| { |
| Aig_Man_t * pNew; |
| int i, nRegCount; |
| Aig_Obj_t * pObjSavePi = NULL; |
| Aig_Obj_t *pObjSavedLo = NULL, *pObjSavedLi = NULL; |
| Aig_Obj_t *pObj, *pMatch; |
| Aig_Obj_t *pObjSaveOrSaved = NULL, *pObjSaveAndNotSaved = NULL, *pObjSavedLoAndEquality; |
| Aig_Obj_t *pObjShadowLo, *pObjShadowLi, *pObjShadowLiDriver; |
| Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc; |
| Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate; |
| Aig_Obj_t *pObjSafetyPropertyOutput = NULL; |
| Aig_Obj_t *pObjOriginalSafetyPropertyOutput; |
| Aig_Obj_t *pDriverImage, *pArgument, *collectiveAssertSafety, *collectiveAssumeSafety; |
| char *nodeName; |
| int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, liveLatch = 0, fairLatch = 0; |
| |
| vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); |
| vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); |
| |
| vecLos = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); |
| vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); |
| |
| //**************************************************************** |
| // 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 |
| //**************************************************************** |
| pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) ); |
| pNew->pName = (char *)malloc( strlen( pNtk->pName ) + strlen("_l2s") + 1 ); |
| sprintf(pNew->pName, "%s_%s", pNtk->pName, "l2s"); |
| pNew->pSpec = NULL; |
| |
| //**************************************************************** |
| // Step 2: map constant nodes |
| //**************************************************************** |
| pObj = Aig_ManConst1( p ); |
| pObj->pData = Aig_ManConst1( pNew ); |
| |
| //**************************************************************** |
| // Step 3: create true PIs |
| //**************************************************************** |
| Saig_ManForEachPi( p, pObj, i ) |
| { |
| piCopied++; |
| pObj->pData = Aig_ObjCreateCi(pNew); |
| Vec_PtrPush( vecPis, pObj->pData ); |
| nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) )); |
| Vec_PtrPush( vecPiNames, nodeName ); |
| } |
| |
| //**************************************************************** |
| // Step 4: create the special Pi corresponding to SAVE |
| //**************************************************************** |
| if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) |
| { |
| pObjSavePi = Aig_ObjCreateCi( pNew ); |
| nodeName = "SAVE_BIERE", |
| Vec_PtrPush( vecPiNames, nodeName ); |
| } |
| |
| //**************************************************************** |
| // Step 5: create register outputs |
| //**************************************************************** |
| Saig_ManForEachLo( p, pObj, i ) |
| { |
| loCopied++; |
| pObj->pData = Aig_ObjCreateCi(pNew); |
| Vec_PtrPush( vecLos, pObj->pData ); |
| nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) )); |
| Vec_PtrPush( vecLoNames, nodeName ); |
| } |
| |
| //**************************************************************** |
| // Step 6: create "saved" register output |
| //**************************************************************** |
| if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) |
| { |
| loCreated++; |
| pObjSavedLo = Aig_ObjCreateCi( pNew ); |
| Vec_PtrPush( vecLos, pObjSavedLo ); |
| nodeName = "SAVED_LO"; |
| Vec_PtrPush( vecLoNames, nodeName ); |
| } |
| |
| //**************************************************************** |
| // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi |
| //**************************************************************** |
| if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) |
| { |
| pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo ); |
| pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) ); |
| } |
| |
| //******************************************************************** |
| // Step 8: create internal nodes |
| //******************************************************************** |
| Aig_ManForEachNode( p, pObj, i ) |
| { |
| pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); |
| } |
| |
| |
| //******************************************************************** |
| // Step 8.x : create PO for each safety assertions |
| // NOTE : Here the output is purposely inverted as it will be thrown to |
| // dprove |
| //******************************************************************** |
| if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) |
| { |
| if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 ) |
| { |
| pObjAndAcc = Aig_ManConst1( pNew ); |
| Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) |
| { |
| pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); |
| pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); |
| } |
| pObjOriginalSafetyPropertyOutput = Aig_ObjCreateCo( pNew, Aig_Not(pObjAndAcc) ); |
| } |
| else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 ) |
| { |
| pObjAndAcc = Aig_ManConst1( pNew ); |
| Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) |
| { |
| pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); |
| pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); |
| } |
| collectiveAssertSafety = pObjAndAcc; |
| |
| pObjAndAcc = Aig_ManConst1( pNew ); |
| Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i ) |
| { |
| pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); |
| pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); |
| } |
| collectiveAssumeSafety = pObjAndAcc; |
| pObjOriginalSafetyPropertyOutput = Aig_ObjCreateCo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) ); |
| } |
| else |
| { |
| printf("WARNING!! No safety property is found, a new (negated) constant 1 output is created\n"); |
| pObjOriginalSafetyPropertyOutput = Aig_ObjCreateCo( pNew, Aig_Not( Aig_ManConst1(pNew) ) ); |
| } |
| } |
| |
| //******************************************************************** |
| // Step 9: create the safety property output gate for the liveness properties |
| // discuss with Sat/Alan for an alternative implementation |
| //******************************************************************** |
| if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) |
| { |
| pObjSafetyPropertyOutput = Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); |
| } |
| |
| // create register inputs for the original registers |
| nRegCount = 0; |
| |
| Saig_ManForEachLo( p, pObj, i ) |
| { |
| pMatch = Saig_ObjLoToLi( p, pObj ); |
| Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) ); |
| nRegCount++; |
| liCopied++; |
| } |
| |
| // create register input corresponding to the register "saved" |
| if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) |
| { |
| #ifndef DUPLICATE_CKT_DEBUG |
| pObjSavedLi = Aig_ObjCreateCo( pNew, pObjSaveOrSaved ); |
| nRegCount++; |
| liCreated++; |
| |
| //Changed on October 13, 2009 |
| //pObjAndAcc = NULL; |
| pObjAndAcc = Aig_ManConst1( pNew ); |
| |
| // create the family of shadow registers, then create the cascade of Xnor and And gates for the comparator |
| Saig_ManForEachLo( p, pObj, i ) |
| { |
| pObjShadowLo = Aig_ObjCreateCi( pNew ); |
| |
| #ifdef PROPAGATE_NAMES |
| Vec_PtrPush( vecLos, pObjShadowLo ); |
| nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ) ) + 10 ); |
| sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "SHADOW" ); |
| |
| Vec_PtrPush( vecLoNames, nodeName ); |
| #endif |
| |
| pObjShadowLiDriver = Aig_Mux( pNew, pObjSaveAndNotSaved, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); |
| pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver ); |
| nRegCount++; |
| loCreated++; liCreated++; |
| |
| pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); |
| pObjXnor = Aig_Not( pObjXor ); |
| |
| pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAcc ); |
| } |
| |
| // create the AND gate whose output will be the signal "looped" |
| pObjSavedLoAndEquality = Aig_And( pNew, pObjSavedLo, pObjAndAcc ); |
| |
| // create the master AND gate and corresponding AND and OR logic for the liveness properties |
| pObjAndAcc = Aig_ManConst1( pNew ); |
| if( vLive == NULL || Vec_PtrSize( vLive ) == 0 ) |
| { |
| printf("Circuit without any liveness property\n"); |
| } |
| else |
| { |
| Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i ) |
| { |
| liveLatch++; |
| pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); |
| pObjShadowLo = Aig_ObjCreateCi( pNew ); |
| |
| #ifdef PROPAGATE_NAMES |
| Vec_PtrPush( vecLos, pObjShadowLo ); |
| nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); |
| sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "LIVENESS" ); |
| Vec_PtrPush( vecLoNames, nodeName ); |
| #endif |
| |
| pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) ); |
| pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver ); |
| nRegCount++; |
| loCreated++; liCreated++; |
| |
| pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc ); |
| } |
| } |
| |
| pObjLive = pObjAndAcc; |
| |
| pObjAndAcc = Aig_ManConst1( pNew ); |
| if( vFair == NULL || Vec_PtrSize( vFair ) == 0 ) |
| printf("Circuit without any fairness property\n"); |
| else |
| { |
| Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i ) |
| { |
| fairLatch++; |
| pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); |
| pObjShadowLo = Aig_ObjCreateCi( pNew ); |
| |
| #ifdef PROPAGATE_NAMES |
| Vec_PtrPush( vecLos, pObjShadowLo ); |
| nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); |
| sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "FAIRNESS" ); |
| Vec_PtrPush( vecLoNames, nodeName ); |
| #endif |
| |
| pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) ); |
| pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver ); |
| nRegCount++; |
| loCreated++; liCreated++; |
| |
| pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc ); |
| } |
| } |
| |
| pObjFair = pObjAndAcc; |
| |
| //pObjSafetyGate = Aig_Exor( pNew, Aig_Not(Aig_ManConst1( pNew )), Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ) ); |
| //Following is the actual Biere translation |
| pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ); |
| |
| Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate ); |
| #endif |
| } |
| |
| Aig_ManSetRegNum( pNew, nRegCount ); |
| |
| Aig_ManCiCleanupBiere( pNew ); |
| Aig_ManCoCleanupBiere( pNew ); |
| |
| Aig_ManCleanup( pNew ); |
| |
| assert( Aig_ManCheck( pNew ) ); |
| |
| if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) |
| { |
| assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vCos, Saig_ManPoNum(pNew)+Aig_ObjCioId(pObjSavedLo)-Saig_ManPiNum(p)-1) == pObjSavedLi); |
| assert( Saig_ManPiNum( p ) + 1 == Saig_ManPiNum( pNew ) ); |
| assert( Saig_ManRegNum( pNew ) == Saig_ManRegNum( p ) * 2 + 1 + liveLatch + fairLatch ); |
| } |
| |
| return pNew; |
| } |
| |
| |
| |
| |
| |
| Aig_Man_t * LivenessToSafetyTransformationAbs( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p, Vec_Int_t *vFlops, |
| Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety ) |
| { |
| Aig_Man_t * pNew; |
| int i, nRegCount, iEntry; |
| Aig_Obj_t * pObjSavePi = NULL; |
| Aig_Obj_t *pObjSavedLi = NULL, *pObjSavedLo = NULL; |
| Aig_Obj_t *pObj, *pMatch; |
| Aig_Obj_t *pObjSavedLoAndEquality, *pObjSaveOrSaved = NULL, *pObjSaveAndNotSaved = NULL; |
| Aig_Obj_t *pObjShadowLo, *pObjShadowLi, *pObjShadowLiDriver; |
| Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc; |
| Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate; |
| Aig_Obj_t *pObjSafetyPropertyOutput = NULL; |
| Aig_Obj_t *pDriverImage, *pArgument, *collectiveAssertSafety, *collectiveAssumeSafety; |
| char *nodeName; |
| int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, liveLatch = 0, fairLatch = 0;//, piVecIndex = 0; |
| |
| vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); |
| vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); |
| |
| vecLos = Vec_PtrAlloc( Saig_ManRegNum( p ) + Vec_IntSize( vFlops ) + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); |
| vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p ) + Vec_IntSize( vFlops ) + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); |
| |
| //**************************************************************** |
| // 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 |
| //**************************************************************** |
| pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) ); |
| pNew->pName = (char *)malloc( strlen( pNtk->pName ) + strlen("_l2s") + 1 ); |
| sprintf(pNew->pName, "%s_%s", pNtk->pName, "l2s"); |
| pNew->pSpec = NULL; |
| |
| //**************************************************************** |
| // Step 2: map constant nodes |
| //**************************************************************** |
| pObj = Aig_ManConst1( p ); |
| pObj->pData = Aig_ManConst1( pNew ); |
| |
| //**************************************************************** |
| // Step 3: create true PIs |
| //**************************************************************** |
| Saig_ManForEachPi( p, pObj, i ) |
| { |
| piCopied++; |
| pObj->pData = Aig_ObjCreateCi(pNew); |
| Vec_PtrPush( vecPis, pObj->pData ); |
| nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) )); |
| Vec_PtrPush( vecPiNames, nodeName ); |
| } |
| |
| //**************************************************************** |
| // Step 4: create the special Pi corresponding to SAVE |
| //**************************************************************** |
| if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) |
| { |
| pObjSavePi = Aig_ObjCreateCi( pNew ); |
| nodeName = "SAVE_BIERE", |
| Vec_PtrPush( vecPiNames, nodeName ); |
| } |
| |
| //**************************************************************** |
| // Step 5: create register outputs |
| //**************************************************************** |
| Saig_ManForEachLo( p, pObj, i ) |
| { |
| loCopied++; |
| pObj->pData = Aig_ObjCreateCi(pNew); |
| Vec_PtrPush( vecLos, pObj->pData ); |
| nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) )); |
| Vec_PtrPush( vecLoNames, nodeName ); |
| } |
| |
| //**************************************************************** |
| // Step 6: create "saved" register output |
| //**************************************************************** |
| if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) |
| { |
| loCreated++; |
| pObjSavedLo = Aig_ObjCreateCi( pNew ); |
| Vec_PtrPush( vecLos, pObjSavedLo ); |
| nodeName = "SAVED_LO"; |
| Vec_PtrPush( vecLoNames, nodeName ); |
| } |
| |
| //**************************************************************** |
| // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi |
| //**************************************************************** |
| if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) |
| { |
| pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo ); |
| pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) ); |
| } |
| |
| //******************************************************************** |
| // Step 8: create internal nodes |
| //******************************************************************** |
| Aig_ManForEachNode( p, pObj, i ) |
| { |
| pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); |
| } |
| |
| |
| //******************************************************************** |
| // Step 8.x : create PO for each safety assertions |
| // NOTE : Here the output is purposely inverted as it will be thrown to |
| // dprove |
| //******************************************************************** |
| if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) |
| { |
| if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 ) |
| { |
| pObjAndAcc = Aig_ManConst1( pNew ); |
| Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) |
| { |
| pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); |
| pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); |
| } |
| Aig_ObjCreateCo( pNew, Aig_Not(pObjAndAcc) ); |
| } |
| else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 ) |
| { |
| pObjAndAcc = Aig_ManConst1( pNew ); |
| Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) |
| { |
| pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); |
| pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); |
| } |
| collectiveAssertSafety = pObjAndAcc; |
| |
| pObjAndAcc = Aig_ManConst1( pNew ); |
| Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i ) |
| { |
| pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); |
| pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); |
| } |
| collectiveAssumeSafety = pObjAndAcc; |
| Aig_ObjCreateCo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) ); |
| } |
| else |
| { |
| printf("WARNING!! No safety property is found, a new (negated) constant 1 output is created\n"); |
| Aig_ObjCreateCo( pNew, Aig_Not( Aig_ManConst1(pNew) ) ); |
| } |
| } |
| |
| //******************************************************************** |
| // Step 9: create the safety property output gate for the liveness properties |
| // discuss with Sat/Alan for an alternative implementation |
| //******************************************************************** |
| if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) |
| { |
| pObjSafetyPropertyOutput = Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); |
| } |
| |
| // create register inputs for the original registers |
| nRegCount = 0; |
| |
| Saig_ManForEachLo( p, pObj, i ) |
| { |
| pMatch = Saig_ObjLoToLi( p, pObj ); |
| Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) ); |
| nRegCount++; |
| liCopied++; |
| } |
| |
| // create register input corresponding to the register "saved" |
| if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) |
| { |
| #ifndef DUPLICATE_CKT_DEBUG |
| pObjSavedLi = Aig_ObjCreateCo( pNew, pObjSaveOrSaved ); |
| nRegCount++; |
| liCreated++; |
| |
| //Changed on October 13, 2009 |
| //pObjAndAcc = NULL; |
| pObjAndAcc = Aig_ManConst1( pNew ); |
| |
| // create the family of shadow registers, then create the cascade of Xnor and And gates for the comparator |
| //Saig_ManForEachLo( p, pObj, i ) |
| Saig_ManForEachLo( p, pObj, i ) |
| { |
| printf("Flop[%d] = %s\n", i, Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ) ); |
| } |
| Vec_IntForEachEntry( vFlops, iEntry, i ) |
| { |
| pObjShadowLo = Aig_ObjCreateCi( pNew ); |
| pObj = Aig_ManLo( p, iEntry ); |
| |
| #ifdef PROPAGATE_NAMES |
| Vec_PtrPush( vecLos, pObjShadowLo ); |
| nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + iEntry ) ) ) + 10 ); |
| sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + iEntry ) ), "SHADOW" ); |
| printf("Flop copied [%d] = %s\n", iEntry, nodeName ); |
| Vec_PtrPush( vecLoNames, nodeName ); |
| #endif |
| |
| pObjShadowLiDriver = Aig_Mux( pNew, pObjSaveAndNotSaved, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); |
| pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver ); |
| nRegCount++; |
| loCreated++; liCreated++; |
| |
| pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); |
| pObjXnor = Aig_Not( pObjXor ); |
| |
| pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAcc ); |
| } |
| |
| // create the AND gate whose output will be the signal "looped" |
| pObjSavedLoAndEquality = Aig_And( pNew, pObjSavedLo, pObjAndAcc ); |
| |
| // create the master AND gate and corresponding AND and OR logic for the liveness properties |
| pObjAndAcc = Aig_ManConst1( pNew ); |
| if( vLive == NULL || Vec_PtrSize( vLive ) == 0 ) |
| { |
| printf("Circuit without any liveness property\n"); |
| } |
| else |
| { |
| Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i ) |
| { |
| liveLatch++; |
| pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); |
| pObjShadowLo = Aig_ObjCreateCi( pNew ); |
| |
| #ifdef PROPAGATE_NAMES |
| Vec_PtrPush( vecLos, pObjShadowLo ); |
| nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); |
| sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "LIVENESS" ); |
| Vec_PtrPush( vecLoNames, nodeName ); |
| #endif |
| |
| pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) ); |
| pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver ); |
| nRegCount++; |
| loCreated++; liCreated++; |
| |
| pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc ); |
| } |
| } |
| |
| pObjLive = pObjAndAcc; |
| |
| pObjAndAcc = Aig_ManConst1( pNew ); |
| if( vFair == NULL || Vec_PtrSize( vFair ) == 0 ) |
| printf("Circuit without any fairness property\n"); |
| else |
| { |
| Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i ) |
| { |
| fairLatch++; |
| pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); |
| pObjShadowLo = Aig_ObjCreateCi( pNew ); |
| |
| #ifdef PROPAGATE_NAMES |
| Vec_PtrPush( vecLos, pObjShadowLo ); |
| nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); |
| sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "FAIRNESS" ); |
| Vec_PtrPush( vecLoNames, nodeName ); |
| #endif |
| |
| pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) ); |
| pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver ); |
| nRegCount++; |
| loCreated++; liCreated++; |
| |
| pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc ); |
| } |
| } |
| |
| pObjFair = pObjAndAcc; |
| |
| //pObjSafetyGate = Aig_Exor( pNew, Aig_Not(Aig_ManConst1( pNew )), Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ) ); |
| //Following is the actual Biere translation |
| pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ); |
| |
| Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate ); |
| #endif |
| } |
| |
| Aig_ManSetRegNum( pNew, nRegCount ); |
| |
| Aig_ManCiCleanupBiere( pNew ); |
| Aig_ManCoCleanupBiere( pNew ); |
| |
| Aig_ManCleanup( pNew ); |
| |
| assert( Aig_ManCheck( pNew ) ); |
| |
| if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) |
| { |
| assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vCos, Saig_ManPoNum(pNew)+Aig_ObjCioId(pObjSavedLo)-Saig_ManPiNum(p)-1) == pObjSavedLi); |
| assert( Saig_ManPiNum( p ) + 1 == Saig_ManPiNum( pNew ) ); |
| assert( Saig_ManRegNum( pNew ) == Saig_ManRegNum( p ) + Vec_IntSize( vFlops ) + 1 + liveLatch + fairLatch ); |
| } |
| |
| return pNew; |
| } |
| |
| |
| |
| Aig_Man_t * LivenessToSafetyTransformationOneStepLoop( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p, |
| Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety ) |
| { |
| Aig_Man_t * pNew; |
| int i, nRegCount; |
| Aig_Obj_t * pObjSavePi = NULL; |
| Aig_Obj_t *pObj, *pMatch; |
| Aig_Obj_t *pObjSavedLoAndEquality; |
| Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc, *pObjAndAccDummy; |
| Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate; |
| Aig_Obj_t *pObjSafetyPropertyOutput = NULL; |
| Aig_Obj_t *pDriverImage; |
| Aig_Obj_t *pObjCorrespondingLi; |
| Aig_Obj_t *pArgument; |
| Aig_Obj_t *collectiveAssertSafety, *collectiveAssumeSafety; |
| |
| char *nodeName; |
| int piCopied = 0, liCopied = 0, loCopied = 0;//, liCreated = 0, loCreated = 0, piVecIndex = 0; |
| |
| if( Aig_ManRegNum( p ) == 0 ) |
| { |
| printf("The input AIG contains no register, returning the original AIG as it is\n"); |
| return p; |
| } |
| |
| vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); |
| vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); |
| |
| vecLos = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); |
| vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); |
| |
| //**************************************************************** |
| // 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 |
| //**************************************************************** |
| pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) ); |
| pNew->pName = Abc_UtilStrsav( "live2safe" ); |
| pNew->pSpec = NULL; |
| |
| //**************************************************************** |
| // Step 2: map constant nodes |
| //**************************************************************** |
| pObj = Aig_ManConst1( p ); |
| pObj->pData = Aig_ManConst1( pNew ); |
| |
| //**************************************************************** |
| // Step 3: create true PIs |
| //**************************************************************** |
| Saig_ManForEachPi( p, pObj, i ) |
| { |
| piCopied++; |
| pObj->pData = Aig_ObjCreateCi(pNew); |
| Vec_PtrPush( vecPis, pObj->pData ); |
| nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) )); |
| Vec_PtrPush( vecPiNames, nodeName ); |
| } |
| |
| //**************************************************************** |
| // Step 4: create the special Pi corresponding to SAVE |
| //**************************************************************** |
| if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE ) |
| { |
| pObjSavePi = Aig_ObjCreateCi( pNew ); |
| nodeName = "SAVE_BIERE", |
| Vec_PtrPush( vecPiNames, nodeName ); |
| } |
| |
| //**************************************************************** |
| // Step 5: create register outputs |
| //**************************************************************** |
| Saig_ManForEachLo( p, pObj, i ) |
| { |
| loCopied++; |
| pObj->pData = Aig_ObjCreateCi(pNew); |
| Vec_PtrPush( vecLos, pObj->pData ); |
| nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) )); |
| Vec_PtrPush( vecLoNames, nodeName ); |
| } |
| |
| //**************************************************************** |
| // Step 6: create "saved" register output |
| //**************************************************************** |
| |
| #if 0 |
| loCreated++; |
| pObjSavedLo = Aig_ObjCreateCi( pNew ); |
| Vec_PtrPush( vecLos, pObjSavedLo ); |
| nodeName = "SAVED_LO"; |
| Vec_PtrPush( vecLoNames, nodeName ); |
| #endif |
| |
| //**************************************************************** |
| // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi |
| //**************************************************************** |
| #if 0 |
| pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo ); |
| pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) ); |
| #endif |
| |
| //******************************************************************** |
| // Step 8: create internal nodes |
| //******************************************************************** |
| Aig_ManForEachNode( p, pObj, i ) |
| { |
| pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); |
| } |
| |
| #if 0 |
| //******************************************************************** |
| // Step 8.x : create PO for each safety assertions |
| //******************************************************************** |
| Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) |
| { |
| pObj->pData = Aig_ObjCreateCo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) ); |
| } |
| #endif |
| |
| if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) |
| { |
| if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 ) |
| { |
| pObjAndAcc = NULL; |
| Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) |
| { |
| //pObj->pData = Aig_ObjCreateCo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) ); |
| pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); |
| if( pObjAndAcc == NULL ) |
| pObjAndAcc = pArgument; |
| else |
| { |
| pObjAndAccDummy = pObjAndAcc; |
| pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAccDummy ); |
| } |
| } |
| Aig_ObjCreateCo( pNew, Aig_Not(pObjAndAcc) ); |
| } |
| else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 ) |
| { |
| pObjAndAcc = NULL; |
| Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) |
| { |
| //pObj->pData = Aig_ObjCreateCo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) ); |
| pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); |
| if( pObjAndAcc == NULL ) |
| pObjAndAcc = pArgument; |
| else |
| { |
| pObjAndAccDummy = pObjAndAcc; |
| pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAccDummy ); |
| } |
| } |
| collectiveAssertSafety = pObjAndAcc; |
| pObjAndAcc = NULL; |
| Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i ) |
| { |
| //pObj->pData = Aig_ObjCreateCo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) ); |
| pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); |
| if( pObjAndAcc == NULL ) |
| pObjAndAcc = pArgument; |
| else |
| { |
| pObjAndAccDummy = pObjAndAcc; |
| pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAccDummy ); |
| } |
| } |
| collectiveAssumeSafety = pObjAndAcc; |
| Aig_ObjCreateCo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) ); |
| } |
| else |
| printf("No safety property is specified, hence no safety gate is created\n"); |
| } |
| |
| //******************************************************************** |
| // Step 9: create the safety property output gate |
| // create the safety property output gate, this will be the sole true PO |
| // of the whole circuit, discuss with Sat/Alan for an alternative implementation |
| //******************************************************************** |
| |
| if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE ) |
| { |
| pObjSafetyPropertyOutput = Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); |
| } |
| |
| // create register inputs for the original registers |
| nRegCount = 0; |
| |
| Saig_ManForEachLo( p, pObj, i ) |
| { |
| pMatch = Saig_ObjLoToLi( p, pObj ); |
| //Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pMatch) ); |
| Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) ); |
| nRegCount++; |
| liCopied++; |
| } |
| |
| #if 0 |
| // create register input corresponding to the register "saved" |
| pObjSavedLi = Aig_ObjCreateCo( pNew, pObjSaveOrSaved ); |
| nRegCount++; |
| liCreated++;7 |
| #endif |
| |
| pObjAndAcc = NULL; |
| |
| //**************************************************************************************************** |
| //For detection of loop of length 1 we do not need any shadow register, we only need equality detector |
| //between Lo_j and Li_j and then a cascade of AND gates |
| //**************************************************************************************************** |
| |
| if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE ) |
| { |
| Saig_ManForEachLo( p, pObj, i ) |
| { |
| pObjCorrespondingLi = Saig_ObjLoToLi( p, pObj ); |
| |
| pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0( pObjCorrespondingLi )->pData, Aig_ObjFaninC0( pObjCorrespondingLi ) ) ); |
| pObjXnor = Aig_Not( pObjXor ); |
| |
| if( pObjAndAcc == NULL ) |
| pObjAndAcc = pObjXnor; |
| else |
| { |
| pObjAndAccDummy = pObjAndAcc; |
| pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAccDummy ); |
| } |
| } |
| |
| // create the AND gate whose output will be the signal "looped" |
| pObjSavedLoAndEquality = Aig_And( pNew, pObjSavePi, pObjAndAcc ); |
| |
| // create the master AND gate and corresponding AND and OR logic for the liveness properties |
| pObjAndAcc = NULL; |
| if( vLive == NULL || Vec_PtrSize( vLive ) == 0 ) |
| printf("Circuit without any liveness property\n"); |
| else |
| { |
| Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i ) |
| { |
| pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); |
| if( pObjAndAcc == NULL ) |
| pObjAndAcc = pDriverImage; |
| else |
| { |
| pObjAndAccDummy = pObjAndAcc; |
| pObjAndAcc = Aig_And( pNew, pDriverImage, pObjAndAccDummy ); |
| } |
| } |
| } |
| |
| if( pObjAndAcc != NULL ) |
| pObjLive = pObjAndAcc; |
| else |
| pObjLive = Aig_ManConst1( pNew ); |
| |
| // create the master AND gate and corresponding AND and OR logic for the fairness properties |
| pObjAndAcc = NULL; |
| if( vFair == NULL || Vec_PtrSize( vFair ) == 0 ) |
| printf("Circuit without any fairness property\n"); |
| else |
| { |
| Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i ) |
| { |
| pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj)); |
| if( pObjAndAcc == NULL ) |
| pObjAndAcc = pDriverImage; |
| else |
| { |
| pObjAndAccDummy = pObjAndAcc; |
| pObjAndAcc = Aig_And( pNew, pDriverImage, pObjAndAccDummy ); |
| } |
| } |
| } |
| |
| if( pObjAndAcc != NULL ) |
| pObjFair = pObjAndAcc; |
| else |
| pObjFair = Aig_ManConst1( pNew ); |
| |
| pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ); |
| |
| Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate ); |
| } |
| |
| Aig_ManSetRegNum( pNew, nRegCount ); |
| |
| //printf("\nSaig_ManPiNum = %d, Reg Num = %d, before everything, before Pi cleanup\n", Vec_PtrSize( pNew->vPis ), pNew->nRegs ); |
| |
| Aig_ManCiCleanupBiere( pNew ); |
| Aig_ManCoCleanupBiere( pNew ); |
| |
| Aig_ManCleanup( pNew ); |
| |
| assert( Aig_ManCheck( pNew ) ); |
| |
| return pNew; |
| } |
| |
| |
| |
| Vec_Ptr_t * populateLivenessVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) |
| { |
| Abc_Obj_t * pNode; |
| int i, liveCounter = 0; |
| Vec_Ptr_t * vLive; |
| |
| vLive = Vec_PtrAlloc( 100 ); |
| Abc_NtkForEachPo( pNtk, pNode, i ) |
| //if( strstr( Abc_ObjName( pNode ), "assert_fair") != NULL ) |
| if( nodeName_starts_with( pNode, "assert_fair" ) ) |
| { |
| Vec_PtrPush( vLive, Aig_ManCo( pAig, i ) ); |
| liveCounter++; |
| } |
| printf("Number of liveness property found = %d\n", liveCounter); |
| return vLive; |
| } |
| |
| Vec_Ptr_t * populateFairnessVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) |
| { |
| Abc_Obj_t * pNode; |
| int i, fairCounter = 0; |
| Vec_Ptr_t * vFair; |
| |
| vFair = Vec_PtrAlloc( 100 ); |
| Abc_NtkForEachPo( pNtk, pNode, i ) |
| //if( strstr( Abc_ObjName( pNode ), "assume_fair") != NULL ) |
| if( nodeName_starts_with( pNode, "assume_fair" ) ) |
| { |
| Vec_PtrPush( vFair, Aig_ManCo( pAig, i ) ); |
| fairCounter++; |
| } |
| printf("Number of fairness property found = %d\n", fairCounter); |
| return vFair; |
| } |
| |
| Vec_Ptr_t * populateSafetyAssertionVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) |
| { |
| Abc_Obj_t * pNode; |
| int i, assertSafetyCounter = 0; |
| Vec_Ptr_t * vAssertSafety; |
| |
| vAssertSafety = Vec_PtrAlloc( 100 ); |
| Abc_NtkForEachPo( pNtk, pNode, i ) |
| //if( strstr( Abc_ObjName( pNode ), "Assert") != NULL ) |
| if( nodeName_starts_with( pNode, "assert_safety" ) || nodeName_starts_with( pNode, "Assert" )) |
| { |
| Vec_PtrPush( vAssertSafety, Aig_ManCo( pAig, i ) ); |
| assertSafetyCounter++; |
| } |
| printf("Number of safety property found = %d\n", assertSafetyCounter); |
| return vAssertSafety; |
| } |
| |
| Vec_Ptr_t * populateSafetyAssumptionVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig ) |
| { |
| Abc_Obj_t * pNode; |
| int i, assumeSafetyCounter = 0; |
| Vec_Ptr_t * vAssumeSafety; |
| |
| vAssumeSafety = Vec_PtrAlloc( 100 ); |
| Abc_NtkForEachPo( pNtk, pNode, i ) |
| //if( strstr( Abc_ObjName( pNode ), "Assert") != NULL ) |
| if( nodeName_starts_with( pNode, "assume_safety" ) || nodeName_starts_with( pNode, "Assume" )) |
| { |
| Vec_PtrPush( vAssumeSafety, Aig_ManCo( pAig, i ) ); |
| assumeSafetyCounter++; |
| } |
| printf("Number of assume_safety property found = %d\n", assumeSafetyCounter); |
| return vAssumeSafety; |
| } |
| |
| void updateNewNetworkNameManager( Abc_Ntk_t *pNtk, Aig_Man_t *pAig, Vec_Ptr_t *vPiNames, Vec_Ptr_t *vLoNames ) |
| { |
| Aig_Obj_t *pObj; |
| Abc_Obj_t *pNode; |
| int i, ntkObjId; |
| |
| pNtk->pManName = Nm_ManCreate( Abc_NtkCiNum( pNtk ) ); |
| |
| if( vPiNames ) |
| { |
| Saig_ManForEachPi( pAig, pObj, i ) |
| { |
| ntkObjId = Abc_NtkCi( pNtk, i )->Id; |
| //printf("Pi %d, Saved Name = %s, id = %d\n", i, Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), Vec_PtrEntry(vPiNames, i), NULL ), ntkObjId); |
| Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vPiNames, i), NULL ); |
| } |
| } |
| if( vLoNames ) |
| { |
| Saig_ManForEachLo( pAig, pObj, i ) |
| { |
| ntkObjId = Abc_NtkCi( pNtk, Saig_ManPiNum( pAig ) + i )->Id; |
| //printf("Lo %d, Saved name = %s, id = %d\n", i, Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), Vec_PtrEntry(vLoNames, i), NULL ), ntkObjId); |
| Nm_ManStoreIdName( pNtk->pManName, ntkObjId, Aig_ObjType(pObj), (char *)Vec_PtrEntry(vLoNames, i), NULL ); |
| } |
| } |
| |
| Abc_NtkForEachPo(pNtk, pNode, i) |
| { |
| Abc_ObjAssignName(pNode, "assert_safety_", Abc_ObjName(pNode) ); |
| } |
| |
| // assign latch input names |
| Abc_NtkForEachLatch(pNtk, pNode, i) |
| if ( Nm_ManFindNameById(pNtk->pManName, Abc_ObjFanin0(pNode)->Id) == NULL ) |
| Abc_ObjAssignName( Abc_ObjFanin0(pNode), Abc_ObjName(Abc_ObjFanin0(pNode)), NULL ); |
| } |
| |
| |
| int Abc_CommandAbcLivenessToSafety( Abc_Frame_t * pAbc, int argc, char ** argv ) |
| { |
| FILE * pOut, * pErr; |
| Abc_Ntk_t * pNtk, * pNtkTemp, *pNtkNew, *pNtkOld; |
| Aig_Man_t * pAig, *pAigNew = NULL; |
| int c; |
| Vec_Ptr_t * vLive, * vFair, *vAssertSafety, *vAssumeSafety; |
| int directive = -1; |
| |
| pNtk = Abc_FrameReadNtk(pAbc); |
| pOut = Abc_FrameReadOut(pAbc); |
| pErr = Abc_FrameReadErr(pAbc); |
| |
| if( argc == 1 ) |
| { |
| assert( directive == -1 ); |
| directive = FULL_BIERE_MODE; |
| } |
| else |
| { |
| Extra_UtilGetoptReset(); |
| while ( ( c = Extra_UtilGetopt( argc, argv, "1slh" ) ) != EOF ) |
| { |
| switch( c ) |
| { |
| case '1': |
| if( directive == -1 ) |
| directive = FULL_BIERE_ONE_LOOP_MODE; |
| else |
| { |
| assert( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE || directive == IGNORE_SAFETY_KEEP_LIVENESS_MODE ); |
| if( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) |
| directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; |
| else |
| directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE; |
| } |
| break; |
| case 's': |
| if( directive == -1 ) |
| directive = IGNORE_SAFETY_KEEP_LIVENESS_MODE; |
| else |
| { |
| if( directive != FULL_BIERE_ONE_LOOP_MODE ) |
| goto usage; |
| assert(directive == FULL_BIERE_ONE_LOOP_MODE); |
| directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE; |
| } |
| break; |
| case 'l': |
| if( directive == -1 ) |
| directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; |
| else |
| { |
| if( directive != FULL_BIERE_ONE_LOOP_MODE ) |
| goto usage; |
| assert(directive == FULL_BIERE_ONE_LOOP_MODE); |
| directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; |
| } |
| break; |
| case 'h': |
| goto usage; |
| default: |
| goto usage; |
| } |
| } |
| } |
| |
| if ( pNtk == NULL ) |
| { |
| fprintf( pErr, "Empty network.\n" ); |
| return 1; |
| } |
| if( !Abc_NtkIsStrash( pNtk ) ) |
| { |
| printf("The input network was not strashed, strashing....\n"); |
| pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); |
| pNtkOld = pNtkTemp; |
| pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); |
| vLive = populateLivenessVector( pNtk, pAig ); |
| vFair = populateFairnessVector( pNtk, pAig ); |
| vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); |
| vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); |
| } |
| else |
| { |
| pAig = Abc_NtkToDar( pNtk, 0, 1 ); |
| pNtkOld = pNtk; |
| vLive = populateLivenessVector( pNtk, pAig ); |
| vFair = populateFairnessVector( pNtk, pAig ); |
| vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); |
| vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); |
| } |
| |
| switch( directive ) |
| { |
| case FULL_BIERE_MODE: |
| //if( Vec_PtrSize(vLive) == 0 && Vec_PtrSize(vAssertSafety) == 0 ) |
| //{ |
| // printf("Input circuit has NO safety and NO liveness property, original network is not disturbed\n"); |
| // return 1; |
| //} |
| //else |
| //{ |
| pAigNew = LivenessToSafetyTransformation( FULL_BIERE_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); |
| if( Aig_ManRegNum(pAigNew) != 0 ) |
| printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n"); |
| break; |
| //} |
| case FULL_BIERE_ONE_LOOP_MODE: |
| //if( Vec_PtrSize(vLive) == 0 && Vec_PtrSize(vAssertSafety) == 0 ) |
| //{ |
| // printf("Input circuit has NO safety and NO liveness property, original network is not disturbed\n"); |
| // return 1; |
| //} |
| //else |
| //{ |
| pAigNew = LivenessToSafetyTransformationOneStepLoop( FULL_BIERE_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); |
| if( Aig_ManRegNum(pAigNew) != 0 ) |
| printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n"); |
| break; |
| //} |
| case IGNORE_LIVENESS_KEEP_SAFETY_MODE: |
| //if( Vec_PtrSize(vAssertSafety) == 0 ) |
| //{ |
| // printf("Input circuit has NO safety property, original network is not disturbed\n"); |
| // return 1; |
| //} |
| //else |
| //{ |
| pAigNew = LivenessToSafetyTransformation( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); |
| if( Aig_ManRegNum(pAigNew) != 0 ) |
| printf("A new circuit is produced with\n\t1 PO - only for safety property; liveness properties are ignored, if any.\n\tno additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n"); |
| break; |
| //} |
| case IGNORE_SAFETY_KEEP_LIVENESS_MODE: |
| //if( Vec_PtrSize(vLive) == 0 ) |
| //{ |
| // printf("Input circuit has NO liveness property, original network is not disturbed\n"); |
| // return 1; |
| //} |
| //else |
| //{ |
| pAigNew = LivenessToSafetyTransformation( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); |
| if( Aig_ManRegNum(pAigNew) != 0 ) |
| printf("A new circuit is produced with\n\t1 PO - only for liveness property; safety properties are ignored, if any.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n"); |
| break; |
| //} |
| case IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE: |
| //if( Vec_PtrSize(vLive) == 0 ) |
| //{ |
| // printf("Input circuit has NO liveness property, original network is not disturbed\n"); |
| // return 1; |
| //} |
| //else |
| //{ |
| pAigNew = LivenessToSafetyTransformationOneStepLoop( IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); |
| if( Aig_ManRegNum(pAigNew) != 0 ) |
| printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nShadow registers are not created\n"); |
| break; |
| //} |
| } |
| |
| #if 0 |
| if( argc == 1 ) |
| { |
| pAigNew = LivenessToSafetyTransformation( FULL_BIERE_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); |
| if( Aig_ManRegNum(pAigNew) != 0 ) |
| printf("New circuit is produced considering all safety, liveness and fairness outputs.\nBiere's logic is created\n"); |
| } |
| else |
| { |
| Extra_UtilGetoptReset(); |
| c = Extra_UtilGetopt( argc, argv, "1lsh" ); |
| if( c == '1' ) |
| { |
| if ( pNtk == NULL ) |
| { |
| fprintf( pErr, "Empty network.\n" ); |
| return 1; |
| } |
| if( !Abc_NtkIsStrash( pNtk ) ) |
| { |
| printf("The input network was not strashed, strashing....\n"); |
| pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); |
| pNtkOld = pNtkTemp; |
| pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); |
| vLive = populateLivenessVector( pNtk, pAig ); |
| vFair = populateFairnessVector( pNtk, pAig ); |
| vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); |
| vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); |
| } |
| else |
| { |
| pAig = Abc_NtkToDar( pNtk, 0, 1 ); |
| pNtkOld = pNtk; |
| vLive = populateLivenessVector( pNtk, pAig ); |
| vFair = populateFairnessVector( pNtk, pAig ); |
| vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); |
| vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); |
| } |
| pAigNew = LivenessToSafetyTransformationOneStepLoop( pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); |
| } |
| else if( c == 'l' ) |
| { |
| if ( pNtk == NULL ) |
| { |
| fprintf( pErr, "Empty network.\n" ); |
| return 1; |
| } |
| if( !Abc_NtkIsStrash( pNtk ) ) |
| { |
| printf("The input network was not strashed, strashing....\n"); |
| pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); |
| pNtkOld = pNtkTemp; |
| pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); |
| vLive = populateLivenessVector( pNtk, pAig ); |
| vFair = populateFairnessVector( pNtk, pAig ); |
| vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); |
| vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); |
| } |
| else |
| { |
| pAig = Abc_NtkToDar( pNtk, 0, 1 ); |
| pNtkOld = pNtk; |
| vLive = populateLivenessVector( pNtk, pAig ); |
| vFair = populateFairnessVector( pNtk, pAig ); |
| vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); |
| vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); |
| } |
| pAigNew = LivenessToSafetyTransformation( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); |
| if( Aig_ManRegNum(pAigNew) != 0 ) |
| printf("New circuit is produced ignoring liveness outputs!\nOnly safety outputs are kept.\nBiere's logic is not created\n"); |
| } |
| else if( c == 's' ) |
| { |
| if ( pNtk == NULL ) |
| { |
| fprintf( pErr, "Empty network.\n" ); |
| return 1; |
| } |
| |
| if( !Abc_NtkIsStrash( pNtk ) ) |
| { |
| printf("The input network was not strashed, strashing....\n"); |
| pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); |
| pNtkOld = pNtkTemp; |
| pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); |
| vLive = populateLivenessVector( pNtk, pAig ); |
| vFair = populateFairnessVector( pNtk, pAig ); |
| vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); |
| vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); |
| } |
| else |
| { |
| pAig = Abc_NtkToDar( pNtk, 0, 1 ); |
| pNtkOld = pNtk; |
| vLive = populateLivenessVector( pNtk, pAig ); |
| vFair = populateFairnessVector( pNtk, pAig ); |
| vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); |
| vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); |
| } |
| pAigNew = LivenessToSafetyTransformation( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); |
| if( Aig_ManRegNum(pAigNew) != 0 ) |
| printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nBiere's logic is created\n"); |
| } |
| else if( c == 'h' ) |
| goto usage; |
| else |
| goto usage; |
| } |
| #endif |
| |
| #if 0 |
| Aig_ManPrintStats( pAigNew ); |
| printf("\nDetail statistics*************************************\n"); |
| printf("Number of true primary inputs = %d\n", Saig_ManPiNum( pAigNew )); |
| printf("Number of true primary outputs = %d\n", Saig_ManPoNum( pAigNew )); |
| printf("Number of true latch outputs = %d\n", Saig_ManCiNum( pAigNew ) - Saig_ManPiNum( pAigNew )); |
| printf("Number of true latch inputs = %d\n", Saig_ManCoNum( pAigNew ) - Saig_ManPoNum( pAigNew )); |
| printf("Numer of registers = %d\n", Saig_ManRegNum( pAigNew ) ); |
| printf("\n*******************************************************\n"); |
| #endif |
| |
| pNtkNew = Abc_NtkFromAigPhase( pAigNew ); |
| pNtkNew->pName = Abc_UtilStrsav( pAigNew->pName ); |
| |
| if ( !Abc_NtkCheck( pNtkNew ) ) |
| fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" ); |
| |
| updateNewNetworkNameManager( pNtkNew, pAigNew, vecPiNames, vecLoNames ); |
| Abc_FrameSetCurrentNetwork( pAbc, pNtkNew ); |
| |
| #if 0 |
| #ifndef DUPLICATE_CKT_DEBUG |
| Saig_ManForEachPi( pAigNew, pObj, i ) |
| assert( strcmp( (char *)Vec_PtrEntry(vecPiNames, i), retrieveTruePiName( pNtk, pAig, pAigNew, pObj ) ) == 0 ); |
| //printf("Name of %d-th Pi = %s, %s\n", i, retrieveTruePiName( pNtk, pAig, pAigNew, pObj ), (char *)Vec_PtrEntry(vecPiNames, i) ); |
| |
| Saig_ManForEachLo( pAigNew, pObj, i ) |
| assert( strcmp( (char *)Vec_PtrEntry(vecLoNames, i), retrieveLOName( pNtk, pAig, pAigNew, pObj, vLive, vFair ) ) == 0 ); |
| #endif |
| #endif |
| |
| return 0; |
| |
| usage: |
| fprintf( stdout, "usage: l2s [-1lsh]\n" ); |
| fprintf( stdout, "\t performs Armin Biere's live-to-safe transformation\n" ); |
| fprintf( stdout, "\t-1 : no shadow logic, presume all loops are self loops\n"); |
| fprintf( stdout, "\t-l : ignore liveness and fairness outputs\n"); |
| fprintf( stdout, "\t-s : ignore safety assertions and assumptions\n"); |
| fprintf( stdout, "\t-h : print command usage\n"); |
| return 1; |
| } |
| |
| Vec_Int_t * prepareFlopVector( Aig_Man_t * pAig, int vectorLength ) |
| { |
| Vec_Int_t *vFlops; |
| int i; |
| |
| vFlops = Vec_IntAlloc( vectorLength ); |
| |
| for( i=0; i<vectorLength; i++ ) |
| Vec_IntPush( vFlops, i ); |
| |
| #if 0 |
| Vec_IntPush( vFlops, 19 ); |
| Vec_IntPush( vFlops, 20 ); |
| Vec_IntPush( vFlops, 23 ); |
| Vec_IntPush( vFlops, 24 ); |
| //Vec_IntPush( vFlops, 2 ); |
| //Vec_IntPush( vFlops, 3 ); |
| //Vec_IntPush( vFlops, 4 ); |
| //Vec_IntPush( vFlops, 5 ); |
| //Vec_IntPush( vFlops, 8 ); |
| //Vec_IntPush( vFlops, 9 ); |
| //Vec_IntPush( vFlops, 10 ); |
| //Vec_IntPush( vFlops, 11 ); |
| //Vec_IntPush( vFlops, 0 ); |
| //Vec_IntPush( vFlops, 0 ); |
| #endif |
| |
| return vFlops; |
| } |
| |
| int Abc_CommandAbcLivenessToSafetyAbstraction( Abc_Frame_t * pAbc, int argc, char ** argv ) |
| { |
| FILE * pOut, * pErr; |
| Abc_Ntk_t * pNtk, * pNtkTemp, *pNtkNew, *pNtkOld; |
| Aig_Man_t * pAig, *pAigNew = NULL; |
| int c; |
| Vec_Ptr_t * vLive, * vFair, *vAssertSafety, *vAssumeSafety; |
| int directive = -1; |
| Vec_Int_t * vFlops; |
| |
| pNtk = Abc_FrameReadNtk(pAbc); |
| pOut = Abc_FrameReadOut(pAbc); |
| pErr = Abc_FrameReadErr(pAbc); |
| |
| if( argc == 1 ) |
| { |
| assert( directive == -1 ); |
| directive = FULL_BIERE_MODE; |
| } |
| else |
| { |
| Extra_UtilGetoptReset(); |
| while ( ( c = Extra_UtilGetopt( argc, argv, "1slh" ) ) != EOF ) |
| { |
| switch( c ) |
| { |
| case '1': |
| if( directive == -1 ) |
| directive = FULL_BIERE_ONE_LOOP_MODE; |
| else |
| { |
| assert( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE || directive == IGNORE_SAFETY_KEEP_LIVENESS_MODE ); |
| if( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) |
| directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; |
| else |
| directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE; |
| } |
| break; |
| case 's': |
| if( directive == -1 ) |
| directive = IGNORE_SAFETY_KEEP_LIVENESS_MODE; |
| else |
| { |
| if( directive != FULL_BIERE_ONE_LOOP_MODE ) |
| goto usage; |
| assert(directive == FULL_BIERE_ONE_LOOP_MODE); |
| directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE; |
| } |
| break; |
| case 'l': |
| if( directive == -1 ) |
| directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; |
| else |
| { |
| if( directive != FULL_BIERE_ONE_LOOP_MODE ) |
| goto usage; |
| assert(directive == FULL_BIERE_ONE_LOOP_MODE); |
| directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; |
| } |
| break; |
| case 'h': |
| goto usage; |
| default: |
| goto usage; |
| } |
| } |
| } |
| |
| if ( pNtk == NULL ) |
| { |
| fprintf( pErr, "Empty network.\n" ); |
| return 1; |
| } |
| if( !Abc_NtkIsStrash( pNtk ) ) |
| { |
| printf("The input network was not strashed, strashing....\n"); |
| pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); |
| pNtkOld = pNtkTemp; |
| pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); |
| vLive = populateLivenessVector( pNtk, pAig ); |
| vFair = populateFairnessVector( pNtk, pAig ); |
| vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); |
| vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); |
| } |
| else |
| { |
| pAig = Abc_NtkToDar( pNtk, 0, 1 ); |
| pNtkOld = pNtk; |
| vLive = populateLivenessVector( pNtk, pAig ); |
| vFair = populateFairnessVector( pNtk, pAig ); |
| vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); |
| vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); |
| } |
| |
| vFlops = prepareFlopVector( pAig, Aig_ManRegNum(pAig)%2 == 0? Aig_ManRegNum(pAig)/2 : (Aig_ManRegNum(pAig)-1)/2); |
| |
| //vFlops = prepareFlopVector( pAig, 100 ); |
| |
| switch( directive ) |
| { |
| case FULL_BIERE_MODE: |
| //if( Vec_PtrSize(vLive) == 0 && Vec_PtrSize(vAssertSafety) == 0 ) |
| //{ |
| // printf("Input circuit has NO safety and NO liveness property, original network is not disturbed\n"); |
| // return 1; |
| //} |
| //else |
| //{ |
| pAigNew = LivenessToSafetyTransformationAbs( FULL_BIERE_MODE, pNtk, pAig, vFlops, vLive, vFair, vAssertSafety, vAssumeSafety ); |
| if( Aig_ManRegNum(pAigNew) != 0 ) |
| printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n"); |
| break; |
| //} |
| case FULL_BIERE_ONE_LOOP_MODE: |
| //if( Vec_PtrSize(vLive) == 0 && Vec_PtrSize(vAssertSafety) == 0 ) |
| //{ |
| // printf("Input circuit has NO safety and NO liveness property, original network is not disturbed\n"); |
| // return 1; |
| //} |
| //else |
| //{ |
| pAigNew = LivenessToSafetyTransformationOneStepLoop( FULL_BIERE_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); |
| if( Aig_ManRegNum(pAigNew) != 0 ) |
| printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n"); |
| break; |
| //} |
| case IGNORE_LIVENESS_KEEP_SAFETY_MODE: |
| //if( Vec_PtrSize(vAssertSafety) == 0 ) |
| //{ |
| // printf("Input circuit has NO safety property, original network is not disturbed\n"); |
| // return 1; |
| //} |
| //else |
| //{ |
| pAigNew = LivenessToSafetyTransformationAbs( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vFlops, vLive, vFair, vAssertSafety, vAssumeSafety ); |
| if( Aig_ManRegNum(pAigNew) != 0 ) |
| printf("A new circuit is produced with\n\t1 PO - only for safety property; liveness properties are ignored, if any.\n\tno additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n"); |
| break; |
| //} |
| case IGNORE_SAFETY_KEEP_LIVENESS_MODE: |
| //if( Vec_PtrSize(vLive) == 0 ) |
| //{ |
| // printf("Input circuit has NO liveness property, original network is not disturbed\n"); |
| // return 1; |
| //} |
| //else |
| //{ |
| pAigNew = LivenessToSafetyTransformationAbs( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vFlops, vLive, vFair, vAssertSafety, vAssumeSafety ); |
| if( Aig_ManRegNum(pAigNew) != 0 ) |
| printf("A new circuit is produced with\n\t1 PO - only for liveness property; safety properties are ignored, if any.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n"); |
| break; |
| //} |
| case IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE: |
| //if( Vec_PtrSize(vLive) == 0 ) |
| //{ |
| // printf("Input circuit has NO liveness property, original network is not disturbed\n"); |
| // return 1; |
| //} |
| //else |
| //{ |
| pAigNew = LivenessToSafetyTransformationOneStepLoop( IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); |
| if( Aig_ManRegNum(pAigNew) != 0 ) |
| printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nShadow registers are not created\n"); |
| break; |
| //} |
| } |
| |
| pNtkNew = Abc_NtkFromAigPhase( pAigNew ); |
| pNtkNew->pName = Abc_UtilStrsav( pAigNew->pName ); |
| |
| if ( !Abc_NtkCheck( pNtkNew ) ) |
| fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" ); |
| |
| updateNewNetworkNameManager( pNtkNew, pAigNew, vecPiNames,vecLoNames ); |
| Abc_FrameSetCurrentNetwork( pAbc, pNtkNew ); |
| |
| #if 0 |
| #ifndef DUPLICATE_CKT_DEBUG |
| Saig_ManForEachPi( pAigNew, pObj, i ) |
| assert( strcmp( (char *)Vec_PtrEntry(vecPiNames, i), retrieveTruePiName( pNtk, pAig, pAigNew, pObj ) ) == 0 ); |
| //printf("Name of %d-th Pi = %s, %s\n", i, retrieveTruePiName( pNtk, pAig, pAigNew, pObj ), (char *)Vec_PtrEntry(vecPiNames, i) ); |
| |
| Saig_ManForEachLo( pAigNew, pObj, i ) |
| assert( strcmp( (char *)Vec_PtrEntry(vecLoNames, i), retrieveLOName( pNtk, pAig, pAigNew, pObj, vLive, vFair ) ) == 0 ); |
| #endif |
| #endif |
| |
| return 0; |
| |
| usage: |
| fprintf( stdout, "usage: l2s [-1lsh]\n" ); |
| fprintf( stdout, "\t performs Armin Biere's live-to-safe transformation\n" ); |
| fprintf( stdout, "\t-1 : no shadow logic, presume all loops are self loops\n"); |
| fprintf( stdout, "\t-l : ignore liveness and fairness outputs\n"); |
| fprintf( stdout, "\t-s : ignore safety assertions and assumptions\n"); |
| fprintf( stdout, "\t-h : print command usage\n"); |
| return 1; |
| } |
| |
| Aig_Man_t * LivenessToSafetyTransformationWithLTL( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p, |
| Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety, |
| int *numLtlProcessed, Vec_Ptr_t *ltlBuffer ) |
| { |
| Aig_Man_t * pNew; |
| int i, ii, iii, nRegCount; |
| Aig_Obj_t * pObjSavePi = NULL; |
| Aig_Obj_t *pObjSavedLo = NULL, *pObjSavedLi = NULL; |
| Aig_Obj_t *pObj, *pMatch; |
| Aig_Obj_t *pObjSaveOrSaved = NULL, *pObjSaveAndNotSaved = NULL, *pObjSavedLoAndEquality; |
| Aig_Obj_t *pObjShadowLo, *pObjShadowLi, *pObjShadowLiDriver; |
| Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc; |
| Aig_Obj_t *pObjLive, *pObjSafetyGate; |
| Aig_Obj_t *pObjSafetyPropertyOutput; |
| Aig_Obj_t *pObjOriginalSafetyPropertyOutput; |
| Aig_Obj_t *pDriverImage, *pArgument, *collectiveAssertSafety, *collectiveAssumeSafety; |
| Aig_Obj_t *pNegatedSafetyConjunction = NULL; |
| Aig_Obj_t *pObjSafetyAndLiveToSafety; |
| char *nodeName, *pFormula; |
| int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, liveLatch = 0;//, piVecIndex = 0, fairLatch = 0; |
| Vec_Ptr_t *vSignal, *vTopASTNodeArray = NULL; |
| ltlNode *pEnrtyGLOBALLY; |
| ltlNode *topNodeOfAST, *tempTopASTNode; |
| Vec_Vec_t *vAigGFMap; |
| Vec_Ptr_t *vSignalMemory, *vGFFlopMemory, *vPoForLtlProps = NULL; |
| Vec_Ptr_t *vecInputLtlFormulae; |
| |
| vecPis = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); |
| vecPiNames = Vec_PtrAlloc( Saig_ManPiNum( p ) + 1); |
| |
| vecLos = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); |
| vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p )*2 + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) ); |
| |
| //**************************************************************** |
| //step0: Parsing the LTL formula |
| //**************************************************************** |
| //Vec_PtrForEachEntry( char *, pNtk->vLtlProperties, pFormula, i ) |
| // printf("\ninput LTL formula [%d] = %s\n", i, pFormula ); |
| |
| |
| #ifdef MULTIPLE_LTL_FORMULA |
| |
| |
| //*************************************************************************** |
| //Reading input LTL formulae from Ntk data-structure and creating |
| //AST for them, Steps involved: |
| // parsing -> AST creation -> well-formedness check -> signal name check |
| //*************************************************************************** |
| |
| //resetting numLtlProcessed |
| *numLtlProcessed = 0; |
| |
| if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) |
| { |
| //if( ltlBuffer ) |
| vecInputLtlFormulae = ltlBuffer; |
| //vecInputLtlFormulae = pNtk->vLtlProperties; |
| if( vecInputLtlFormulae ) |
| { |
| vTopASTNodeArray = Vec_PtrAlloc( Vec_PtrSize( vecInputLtlFormulae ) ); |
| printf("\n"); |
| Vec_PtrForEachEntry( char *, vecInputLtlFormulae, pFormula, i ) |
| { |
| tempTopASTNode = parseFormulaCreateAST( pFormula ); |
| //traverseAbstractSyntaxTree_postFix( tempTopASTNode ); |
| if( tempTopASTNode ) |
| { |
| printf("Formula %d: AST is created, ", i+1); |
| if( isWellFormed( tempTopASTNode ) ) |
| printf("Well-formedness check PASSED, "); |
| else |
| { |
| printf("Well-formedness check FAILED!!\n"); |
| printf("AST will be ignored for formula %d, no extra logic will be added for this formula\n", i+1 ); |
| //do memory management to free the created AST |
| continue; |
| } |
| if( checkSignalNameExistence( pNtk, tempTopASTNode ) ) |
| printf("Signal check PASSED\n"); |
| else |
| { |
| printf("Signal check FAILED!!"); |
| printf("AST will be ignored for formula %d, no extra logic will be added for this formula\n", i+1 ); |
| //do memory management to free the created AST |
| continue; |
| } |
| Vec_PtrPush( vTopASTNodeArray, tempTopASTNode ); |
| (*numLtlProcessed)++; |
| } |
| else |
| printf("\nNo AST has been created for formula %d, no extra logic will be added\n", i+1 ); |
| } |
| } |
| printf("\n"); |
| if( Vec_PtrSize( vTopASTNodeArray ) == 0 ) |
| { |
| //printf("\nNo AST has been created for any formula; hence the circuit is left untouched\n"); |
| printf("\nCurrently aborting, need to take care when Vec_PtrSize( vTopASTNodeArray ) == 0\n"); |
| exit(0); |
| } |
| } |
| |
| //**************************************************************** |
| // 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 |
| //**************************************************************** |
| pNew = Aig_ManStart( 2 * Aig_ManObjNumMax(p) ); |
| pNew->pName = (char *)malloc( strlen( pNtk->pName ) + strlen("_l3s") + 1 ); |
| sprintf(pNew->pName, "%s_%s", pNtk->pName, "l3s"); |
| pNew->pSpec = NULL; |
| |
| //**************************************************************** |
| // Step 2: map constant nodes |
| //**************************************************************** |
| pObj = Aig_ManConst1( p ); |
| pObj->pData = Aig_ManConst1( pNew ); |
| |
| //**************************************************************** |
| // Step 3: create true PIs |
| //**************************************************************** |
| Saig_ManForEachPi( p, pObj, i ) |
| { |
| piCopied++; |
| pObj->pData = Aig_ObjCreateCi(pNew); |
| Vec_PtrPush( vecPis, pObj->pData ); |
| nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkPi( pNtk, i ) )); |
| Vec_PtrPush( vecPiNames, nodeName ); |
| } |
| |
| //**************************************************************** |
| // Step 4: create the special Pi corresponding to SAVE |
| //**************************************************************** |
| if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) |
| { |
| pObjSavePi = Aig_ObjCreateCi( pNew ); |
| nodeName = "SAVE_BIERE", |
| Vec_PtrPush( vecPiNames, nodeName ); |
| } |
| |
| //**************************************************************** |
| // Step 5: create register outputs |
| //**************************************************************** |
| Saig_ManForEachLo( p, pObj, i ) |
| { |
| loCopied++; |
| pObj->pData = Aig_ObjCreateCi(pNew); |
| Vec_PtrPush( vecLos, pObj->pData ); |
| nodeName = Abc_UtilStrsav(Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) )); |
| Vec_PtrPush( vecLoNames, nodeName ); |
| } |
| |
| //**************************************************************** |
| // Step 6: create "saved" register output |
| //**************************************************************** |
| if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) |
| { |
| loCreated++; |
| pObjSavedLo = Aig_ObjCreateCi( pNew ); |
| Vec_PtrPush( vecLos, pObjSavedLo ); |
| nodeName = "SAVED_LO"; |
| Vec_PtrPush( vecLoNames, nodeName ); |
| } |
| |
| //**************************************************************** |
| // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi |
| //**************************************************************** |
| if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) |
| { |
| pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo ); |
| pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) ); |
| } |
| |
| //******************************************************************** |
| // Step 8: create internal nodes |
| //******************************************************************** |
| Aig_ManForEachNode( p, pObj, i ) |
| { |
| pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); |
| } |
| |
| |
| //******************************************************************** |
| // Step 8.x : create PO for each safety assertions |
| // NOTE : Here the output is purposely inverted as it will be thrown to |
| // dprove |
| //******************************************************************** |
| assert( pNegatedSafetyConjunction == NULL ); |
| if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE) |
| { |
| if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 ) |
| { |
| pObjAndAcc = Aig_ManConst1( pNew ); |
| Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) |
| { |
| pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); |
| pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); |
| } |
| pNegatedSafetyConjunction = Aig_Not(pObjAndAcc); |
| if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) |
| pObjOriginalSafetyPropertyOutput = Aig_ObjCreateCo( pNew, Aig_Not(pObjAndAcc) ); |
| } |
| else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 ) |
| { |
| pObjAndAcc = Aig_ManConst1( pNew ); |
| Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i ) |
| { |
| pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); |
| pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); |
| } |
| collectiveAssertSafety = pObjAndAcc; |
| |
| pObjAndAcc = Aig_ManConst1( pNew ); |
| Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i ) |
| { |
| pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ); |
| pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc ); |
| } |
| collectiveAssumeSafety = pObjAndAcc; |
| pNegatedSafetyConjunction = Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ); |
| if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) |
| pObjOriginalSafetyPropertyOutput = Aig_ObjCreateCo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) ); |
| } |
| else |
| { |
| printf("WARNING!! No safety property is found, a new (negated) constant 1 output is created\n"); |
| pNegatedSafetyConjunction = Aig_Not( Aig_ManConst1(pNew) ); |
| if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) |
| pObjOriginalSafetyPropertyOutput = Aig_ObjCreateCo( pNew, Aig_Not( Aig_ManConst1(pNew) ) ); |
| } |
| } |
| assert( pNegatedSafetyConjunction != NULL ); |
| |
| //******************************************************************** |
| // Step 9: create the safety property output gate for the liveness properties |
| // discuss with Sat/Alan for an alternative implementation |
| //******************************************************************** |
| if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) |
| { |
| vPoForLtlProps = Vec_PtrAlloc( Vec_PtrSize( vTopASTNodeArray ) ); |
| if( Vec_PtrSize( vTopASTNodeArray ) ) |
| { |
| //no effective AST for any input LTL property |
| //must do something graceful |
| } |
| for( i=0; i<Vec_PtrSize( vTopASTNodeArray ); i++ ) |
| { |
| pObjSafetyPropertyOutput = Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); |
| Vec_PtrPush( vPoForLtlProps, pObjSafetyPropertyOutput ); |
| } |
| } |
| |
| //************************************************************************************* |
| // Step 10: Placeholder PO's were created for Liveness property outputs in the |
| // last step. FYI, # of new liveness property outputs = # of LTL properties in the circuit |
| // It is time for creation of loop LI's and other stuff |
| // Now creating register inputs for the original flops |
| //************************************************************************************* |
| nRegCount = 0; |
| |
| Saig_ManForEachLo( p, pObj, i ) |
| { |
| pMatch = Saig_ObjLoToLi( p, pObj ); |
| Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) ); |
| nRegCount++; |
| liCopied++; |
| } |
| |
| //************************************************************************************* |
| // Step 11: create register input corresponding to the register "saved" |
| //************************************************************************************* |
| if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) |
| { |
| #ifndef DUPLICATE_CKT_DEBUG |
| pObjSavedLi = Aig_ObjCreateCo( pNew, pObjSaveOrSaved ); |
| nRegCount++; |
| liCreated++; |
| |
| pObjAndAcc = Aig_ManConst1( pNew ); |
| |
| //************************************************************************************* |
| // Step 11: create the family of shadow registers, then create the cascade of Xnor |
| // and And gates for the comparator |
| //************************************************************************************* |
| Saig_ManForEachLo( p, pObj, i ) |
| { |
| //printf("\nKEMON RENDY = %s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i )) ); |
| //top|route0_target0_queue_with_credit0_queue0 |
| //top|route0_master0_queue2 |
| // if( strcmp( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "top|route0_queue1_num[0]" ) == 0 |
| // || strcmp( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "top|route0_queue1_num[1]" ) == 0 || strcmp( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "top|route0_queue1_num[2]" ) == 0 ) |
| { |
| pObjShadowLo = Aig_ObjCreateCi( pNew ); |
| |
| #ifdef PROPAGATE_NAMES |
| Vec_PtrPush( vecLos, pObjShadowLo ); |
| nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ) ) + 10 ); |
| sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "SHADOW" ); |
| |
| Vec_PtrPush( vecLoNames, nodeName ); |
| #endif |
| |
| pObjShadowLiDriver = Aig_Mux( pNew, pObjSaveAndNotSaved, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); |
| pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver ); |
| nRegCount++; |
| loCreated++; liCreated++; |
| |
| pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, pObjShadowLo ); |
| pObjXnor = Aig_Not( pObjXor ); |
| |
| pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAcc ); |
| } |
| } |
| |
| // create the AND gate whose output will be the signal "looped" |
| pObjSavedLoAndEquality = Aig_And( pNew, pObjSavedLo, pObjAndAcc ); |
| |
| // create the master AND gate and corresponding AND and OR logic for the liveness properties |
| |
| //************************************************************************************* |
| // Step 11: logic for LTL properties:- (looped & ~theta) where theta is the input ltl |
| // property |
| // Description of some data-structure: |
| //------------------------------------------------------------------------------------- |
| // Name | Type | Purpose |
| //------------------------------------------------------------------------------------- |
| // vSignalMemory | Vec_Ptr_t * | A vector across all ASTs of the LTL properties |
| // | | It remembers if OR+Latch for GF node has already been |
| // | | created for a particular signal. |
| // | | |
| // vGFFlopMemory | Vec_Ptr_t * | A vector across all ASTs of the LTL properties |
| // | | remembers if OR+Latch of a GF node has already been created |
| // | | |
| // vSignal | Vec_Ptr_t * | vector for each AST; contains pointers from GF nodes |
| // | | to AIG signals |
| // | | |
| // vAigGFMap | Vec_Vec_t * | vAigGFMap[ index ] = vector of GF nodes pointing to |
| // | | the same AIG node; "index" is the index of that |
| // | | AIG node in the vector vSignal |
| //************************************************************************************* |
| |
| vSignalMemory = Vec_PtrAlloc(10); |
| vGFFlopMemory = Vec_PtrAlloc(10); |
| |
| Vec_PtrForEachEntry( ltlNode *, vTopASTNodeArray, topNodeOfAST, iii ) |
| { |
| vSignal = Vec_PtrAlloc( 10 ); |
| vAigGFMap = Vec_VecAlloc( 10 ); |
| |
| //************************************************************************************* |
| //Step 11a: for the current AST, find out the leaf level Boolean signal pointers from |
| // the NEW aig. |
| //************************************************************************************* |
| populateBoolWithAigNodePtr( pNtk, p, pNew, topNodeOfAST ); |
| assert( checkAllBoolHaveAIGPointer( topNodeOfAST ) ); |
| |
| //************************************************************************************* |
| //Step 11b: for each GF node, compute the pointer in AIG that it should point to |
| // In particular, if the subtree below GF is some Boolean crown (including the case |
| // of simple negation, create new logic and populate the AIG pointer in GF node |
| // accordingly |
| //************************************************************************************* |
| populateAigPointerUnitGF( pNew, topNodeOfAST, vSignal, vAigGFMap ); |
| |
| //************************************************************************************* |
| //Step 11c: everything below GF are computed. Now, it is time to create logic for individual |
| // GF nodes (i.e. the OR gate and the latch and the Boolean crown of the AST |
| //************************************************************************************* |
| Vec_PtrForEachEntry( Aig_Obj_t *, vSignal, pObj, i ) |
| { |
| //********************************************************* |
| // Step 11c.1: if the OR+Latch of the particular signal is |
| // not already created, create it. It may have already been |
| // created from another property, so check it before creation |
| //********************************************************* |
| if( Vec_PtrFind( vSignalMemory, pObj ) == -1 ) |
| { |
| liveLatch++; |
| |
| pDriverImage = pObj; |
| pObjShadowLo = Aig_ObjCreateCi( pNew ); |
| pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) ); |
| pObjShadowLi = Aig_ObjCreateCo( pNew, pObjShadowLiDriver ); |
| |
| nRegCount++; |
| loCreated++; liCreated++; |
| |
| Vec_PtrPush( vSignalMemory, pObj ); |
| Vec_PtrPush( vGFFlopMemory, pObjShadowLo ); |
| |
| #if 1 |
| #ifdef PROPAGATE_NAMES |
| Vec_PtrPush( vecLos, pObjShadowLo ); |
| //nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); |
| //sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "LIVENESS" ); |
| nodeName = (char *)malloc( 20 ); |
| sprintf( nodeName, "n%d__%s", Aig_ObjId(pObjShadowLo), "GF_flop" ); |
| Vec_PtrPush( vecLoNames, nodeName ); |
| #endif |
| #endif |
| } |
| else |
| pObjShadowLo = (Aig_Obj_t *)Vec_PtrEntry( vGFFlopMemory, Vec_PtrFind( vSignalMemory, pObj ) ); |
| |
| Vec_VecForEachEntryLevel( ltlNode *, vAigGFMap, pEnrtyGLOBALLY, ii, i ) |
| setAIGNodePtrOfGloballyNode( pEnrtyGLOBALLY, pObjShadowLo); |
| |
| |
| //#ifdef PROPAGATE_NAMES |
| // Vec_PtrPush( vecLos, pObjShadowLo ); |
| // nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ) ) + 12 ); |
| // sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkPo( pNtk, getPoIndex( p, pObj ) ) ), "LIVENESS" ); |
| // Vec_PtrPush( vecLoNames, nodeName ); |
| //#endif |
| |
| } |
| |
| //********************************************************* |
| //Step 11c.2: creating the Boolean crown |
| //********************************************************* |
| buildLogicFromLTLNode( pNew, topNodeOfAST ); |
| |
| //********************************************************* |
| //Step 11c.3: creating logic for (looped & ~theta) and patching |
| // it with the proper PO |
| //Note: if ALLOW_SAFETY_PROPERTIES is defined then the final AND |
| //gate is a conjunction of safety & liveness, i.e. SAFETY & (looped => theta) |
| //since ABC convention demands a NOT gate at the end, the property logic |
| //becomes !( SAFETY & (looped => theta) ) = !SAFETY + (looped & !theta) |
| //********************************************************* |
| pObjLive = retriveAIGPointerFromLTLNode( topNodeOfAST ); |
| pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_Not(pObjLive) ); |
| #ifdef ALLOW_SAFETY_PROPERTIES |
| printf("liveness output is conjoined with safety assertions\n"); |
| pObjSafetyAndLiveToSafety = Aig_Or( pNew, pObjSafetyGate, pNegatedSafetyConjunction ); |
| pObjSafetyPropertyOutput = (Aig_Obj_t *)Vec_PtrEntry( vPoForLtlProps, iii ); |
| Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyAndLiveToSafety ); |
| #else |
| pObjSafetyPropertyOutput = Vec_PtrEntry( vPoForLtlProps, iii ); |
| Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate ); |
| #endif |
| //refreshing vSignal and vAigGFMap arrays |
| Vec_PtrFree( vSignal ); |
| Vec_VecFree( vAigGFMap ); |
| } |
| |
| #endif |
| } |
| #endif |
| |
| Aig_ManSetRegNum( pNew, nRegCount ); |
| |
| Aig_ManCiCleanupBiere( pNew ); |
| Aig_ManCoCleanupBiere( pNew ); |
| |
| Aig_ManCleanup( pNew ); |
| |
| assert( Aig_ManCheck( pNew ) ); |
| |
| if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE ) |
| { |
| assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vCos, Saig_ManPoNum(pNew)+Aig_ObjCioId(pObjSavedLo)-Saig_ManPiNum(p)-1) == pObjSavedLi); |
| assert( Saig_ManPiNum( p ) + 1 == Saig_ManPiNum( pNew ) ); |
| //assert( Saig_ManRegNum( pNew ) == Saig_ManRegNum( p ) * 2 + 1 + liveLatch + fairLatch ); |
| } |
| |
| |
| return pNew; |
| } |
| |
| int Abc_CommandAbcLivenessToSafetyWithLTL( Abc_Frame_t * pAbc, int argc, char ** argv ) |
| { |
| FILE * pOut, * pErr; |
| Abc_Ntk_t * pNtk, * pNtkTemp, *pNtkNew, *pNtkOld; |
| Aig_Man_t * pAig, *pAigNew = NULL; |
| int c; |
| Vec_Ptr_t * vLive, * vFair, *vAssertSafety, *vAssumeSafety; |
| int directive = -1; |
| // char *ltfFormulaString = NULL; |
| int numOfLtlPropOutput;//, LTL_FLAG = 0; |
| Vec_Ptr_t *ltlBuffer; |
| |
| pNtk = Abc_FrameReadNtk(pAbc); |
| pOut = Abc_FrameReadOut(pAbc); |
| pErr = Abc_FrameReadErr(pAbc); |
| |
| if( argc == 1 ) |
| { |
| assert( directive == -1 ); |
| directive = FULL_BIERE_MODE; |
| } |
| else |
| { |
| Extra_UtilGetoptReset(); |
| while ( ( c = Extra_UtilGetopt( argc, argv, "1slhf" ) ) != EOF ) |
| { |
| switch( c ) |
| { |
| case '1': |
| if( directive == -1 ) |
| directive = FULL_BIERE_ONE_LOOP_MODE; |
| else |
| { |
| assert( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE || directive == IGNORE_SAFETY_KEEP_LIVENESS_MODE ); |
| if( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE ) |
| directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; |
| else |
| directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE; |
| } |
| break; |
| case 's': |
| if( directive == -1 ) |
| directive = IGNORE_SAFETY_KEEP_LIVENESS_MODE; |
| else |
| { |
| if( directive != FULL_BIERE_ONE_LOOP_MODE ) |
| goto usage; |
| assert(directive == FULL_BIERE_ONE_LOOP_MODE); |
| directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE; |
| } |
| break; |
| case 'l': |
| if( directive == -1 ) |
| directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; |
| else |
| { |
| if( directive != FULL_BIERE_ONE_LOOP_MODE ) |
| goto usage; |
| assert(directive == FULL_BIERE_ONE_LOOP_MODE); |
| directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE; |
| } |
| break; |
| case 'f': |
| //assert( argc >= 3 ); |
| //vecLtlFormula = Vec_PtrAlloc( argc - 2 ); |
| //if( argc >= 3 ) |
| //{ |
| // for( t=3; t<=argc; t++ ) |
| // { |
| // printf("argv[%d] = %s\n", t-1, argv[t-1]); |
| // Vec_PtrPush( vecLtlFormula, argv[t-1] ); |
| // } |
| //} |
| //printf("argv[argc] = %s\n", argv[argc-1]); |
| //ltfFormulaString = argv[2]; |
| |
| //LTL_FLAG = 1; |
| printf("\nILLEGAL FLAG: aborting....\n"); |
| exit(0); |
| break; |
| case 'h': |
| goto usage; |
| default: |
| goto usage; |
| } |
| } |
| } |
| |
| if ( pNtk == NULL ) |
| { |
| fprintf( pErr, "Empty network.\n" ); |
| return 1; |
| } |
| if( !Abc_NtkIsStrash( pNtk ) ) |
| { |
| printf("The input network was not strashed, strashing....\n"); |
| pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); |
| pNtkOld = pNtkTemp; |
| pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); |
| vLive = populateLivenessVector( pNtk, pAig ); |
| vFair = populateFairnessVector( pNtk, pAig ); |
| vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); |
| vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); |
| } |
| else |
| { |
| pAig = Abc_NtkToDar( pNtk, 0, 1 ); |
| pNtkOld = pNtk; |
| vLive = populateLivenessVector( pNtk, pAig ); |
| vFair = populateFairnessVector( pNtk, pAig ); |
| vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); |
| vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); |
| } |
| |
| if( pAbc->vLTLProperties_global != NULL ) |
| ltlBuffer = pAbc->vLTLProperties_global; |
| else |
| ltlBuffer = NULL; |
| |
| switch( directive ) |
| { |
| case FULL_BIERE_MODE: |
| pAigNew = LivenessToSafetyTransformationWithLTL( FULL_BIERE_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety, &numOfLtlPropOutput, ltlBuffer ); |
| if( Aig_ManRegNum(pAigNew) != 0 ) |
| printf("A new circuit is produced with\n\t%d POs - one for safety and %d for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n", numOfLtlPropOutput+1, numOfLtlPropOutput); |
| break; |
| |
| case FULL_BIERE_ONE_LOOP_MODE: |
| pAigNew = LivenessToSafetyTransformationOneStepLoop( FULL_BIERE_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); |
| if( Aig_ManRegNum(pAigNew) != 0 ) |
| printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n"); |
| break; |
| |
| case IGNORE_LIVENESS_KEEP_SAFETY_MODE: |
| pAigNew = LivenessToSafetyTransformationWithLTL( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety, &numOfLtlPropOutput, ltlBuffer ); |
| assert( numOfLtlPropOutput == 0 ); |
| if( Aig_ManRegNum(pAigNew) != 0 ) |
| printf("A new circuit is produced with\n\t1 PO - only for safety property; liveness properties are ignored, if any.\n\tno additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n"); |
| break; |
| |
| case IGNORE_SAFETY_KEEP_LIVENESS_MODE: |
| pAigNew = LivenessToSafetyTransformationWithLTL( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety, &numOfLtlPropOutput, ltlBuffer ); |
| if( Aig_ManRegNum(pAigNew) != 0 ) |
| printf("A new circuit is produced with\n\t%d PO - only for liveness property; safety properties are ignored, if any.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n", numOfLtlPropOutput); |
| break; |
| |
| case IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE: |
| pAigNew = LivenessToSafetyTransformationOneStepLoop( IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); |
| if( Aig_ManRegNum(pAigNew) != 0 ) |
| printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nShadow registers are not created\n"); |
| break; |
| } |
| |
| #if 0 |
| if( argc == 1 ) |
| { |
| pAigNew = LivenessToSafetyTransformation( FULL_BIERE_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); |
| if( Aig_ManRegNum(pAigNew) != 0 ) |
| printf("New circuit is produced considering all safety, liveness and fairness outputs.\nBiere's logic is created\n"); |
| } |
| else |
| { |
| Extra_UtilGetoptReset(); |
| c = Extra_UtilGetopt( argc, argv, "1lsh" ); |
| if( c == '1' ) |
| { |
| if ( pNtk == NULL ) |
| { |
| fprintf( pErr, "Empty network.\n" ); |
| return 1; |
| } |
| if( !Abc_NtkIsStrash( pNtk ) ) |
| { |
| printf("The input network was not strashed, strashing....\n"); |
| pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); |
| pNtkOld = pNtkTemp; |
| pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); |
| vLive = populateLivenessVector( pNtk, pAig ); |
| vFair = populateFairnessVector( pNtk, pAig ); |
| vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); |
| vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); |
| } |
| else |
| { |
| pAig = Abc_NtkToDar( pNtk, 0, 1 ); |
| pNtkOld = pNtk; |
| vLive = populateLivenessVector( pNtk, pAig ); |
| vFair = populateFairnessVector( pNtk, pAig ); |
| vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); |
| vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); |
| } |
| pAigNew = LivenessToSafetyTransformationOneStepLoop( pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); |
| } |
| else if( c == 'l' ) |
| { |
| if ( pNtk == NULL ) |
| { |
| fprintf( pErr, "Empty network.\n" ); |
| return 1; |
| } |
| if( !Abc_NtkIsStrash( pNtk ) ) |
| { |
| printf("The input network was not strashed, strashing....\n"); |
| pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); |
| pNtkOld = pNtkTemp; |
| pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); |
| vLive = populateLivenessVector( pNtk, pAig ); |
| vFair = populateFairnessVector( pNtk, pAig ); |
| vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); |
| vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); |
| } |
| else |
| { |
| pAig = Abc_NtkToDar( pNtk, 0, 1 ); |
| pNtkOld = pNtk; |
| vLive = populateLivenessVector( pNtk, pAig ); |
| vFair = populateFairnessVector( pNtk, pAig ); |
| vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); |
| vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); |
| } |
| pAigNew = LivenessToSafetyTransformation( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); |
| if( Aig_ManRegNum(pAigNew) != 0 ) |
| printf("New circuit is produced ignoring liveness outputs!\nOnly safety outputs are kept.\nBiere's logic is not created\n"); |
| } |
| else if( c == 's' ) |
| { |
| if ( pNtk == NULL ) |
| { |
| fprintf( pErr, "Empty network.\n" ); |
| return 1; |
| } |
| |
| if( !Abc_NtkIsStrash( pNtk ) ) |
| { |
| printf("The input network was not strashed, strashing....\n"); |
| pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); |
| pNtkOld = pNtkTemp; |
| pAig = Abc_NtkToDar( pNtkTemp, 0, 1 ); |
| vLive = populateLivenessVector( pNtk, pAig ); |
| vFair = populateFairnessVector( pNtk, pAig ); |
| vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); |
| vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); |
| } |
| else |
| { |
| pAig = Abc_NtkToDar( pNtk, 0, 1 ); |
| pNtkOld = pNtk; |
| vLive = populateLivenessVector( pNtk, pAig ); |
| vFair = populateFairnessVector( pNtk, pAig ); |
| vAssertSafety = populateSafetyAssertionVector( pNtk, pAig ); |
| vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig ); |
| } |
| pAigNew = LivenessToSafetyTransformation( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety ); |
| if( Aig_ManRegNum(pAigNew) != 0 ) |
| printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nBiere's logic is created\n"); |
| } |
| else if( c == 'h' ) |
| goto usage; |
| else |
| goto usage; |
| } |
| #endif |
| |
| #if 0 |
| Aig_ManPrintStats( pAigNew ); |
| printf("\nDetail statistics*************************************\n"); |
| printf("Number of true primary inputs = %d\n", Saig_ManPiNum( pAigNew )); |
| printf("Number of true primary outputs = %d\n", Saig_ManPoNum( pAigNew )); |
| printf("Number of true latch outputs = %d\n", Saig_ManCiNum( pAigNew ) - Saig_ManPiNum( pAigNew )); |
| printf("Number of true latch inputs = %d\n", Saig_ManCoNum( pAigNew ) - Saig_ManPoNum( pAigNew )); |
| printf("Numer of registers = %d\n", Saig_ManRegNum( pAigNew ) ); |
| printf("\n*******************************************************\n"); |
| #endif |
| |
| pNtkNew = Abc_NtkFromAigPhase( pAigNew ); |
| pNtkNew->pName = Abc_UtilStrsav( pAigNew->pName ); |
| |
| if ( !Abc_NtkCheck( pNtkNew ) ) |
| fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" ); |
| |
| updateNewNetworkNameManager( pNtkNew, pAigNew, vecPiNames, vecLoNames ); |
| Abc_FrameSetCurrentNetwork( pAbc, pNtkNew ); |
| |
| #if 0 |
| #ifndef DUPLICATE_CKT_DEBUG |
| Saig_ManForEachPi( pAigNew, pObj, i ) |
| assert( strcmp( (char *)Vec_PtrEntry(vecPiNames, i), retrieveTruePiName( pNtk, pAig, pAigNew, pObj ) ) == 0 ); |
| //printf("Name of %d-th Pi = %s, %s\n", i, retrieveTruePiName( pNtk, pAig, pAigNew, pObj ), (char *)Vec_PtrEntry(vecPiNames, i) ); |
| |
| Saig_ManForEachLo( pAigNew, pObj, i ) |
| assert( strcmp( (char *)Vec_PtrEntry(vecLoNames, i), retrieveLOName( pNtk, pAig, pAigNew, pObj, vLive, vFair ) ) == 0 ); |
| #endif |
| #endif |
| |
| return 0; |
| |
| usage: |
| fprintf( stdout, "usage: l3s [-1lsh]\n" ); |
| fprintf( stdout, "\t performs Armin Biere's live-to-safe transformation\n" ); |
| fprintf( stdout, "\t-1 : no shadow logic, presume all loops are self loops\n"); |
| fprintf( stdout, "\t-l : ignore liveness and fairness outputs\n"); |
| fprintf( stdout, "\t-s : ignore safety assertions and assumptions\n"); |
| fprintf( stdout, "\t-h : print command usage\n"); |
| return 1; |
| } |
| |
| |
| ABC_NAMESPACE_IMPL_END |