summaryrefslogtreecommitdiffstats
path: root/src/proof/live/liveness_sim.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/proof/live/liveness_sim.c')
-rw-r--r--src/proof/live/liveness_sim.c848
1 files changed, 848 insertions, 0 deletions
diff --git a/src/proof/live/liveness_sim.c b/src/proof/live/liveness_sim.c
new file mode 100644
index 00000000..50153e50
--- /dev/null
+++ b/src/proof/live/liveness_sim.c
@@ -0,0 +1,848 @@
+/**CFile****************************************************************
+
+ FileName [liveness_sim.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_sim.c,v 1.00 2009/01/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include "src/base/main/main.h"
+#include "src/aig/aig/aig.h"
+#include "src/aig/saig/saig.h"
+#include <string.h>
+
+ABC_NAMESPACE_IMPL_START
+
+
+#define PROPAGATE_NAMES
+//#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);
+
+
+/*******************************************************************
+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 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) );
+ }
+}
+
+static 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;
+}
+
+static 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_ManForEachPi( pAigNew, pObj, index )
+ if( pObj == pObjPivot )
+ break;
+ assert( index < Aig_ManPiNum( pAigNew ) - Aig_ManRegNum( pAigNew ) );
+ if( index == Saig_ManPiNum( pAigNew ) - 1 )
+ return "SAVE_BIERE";
+ else
+ {
+ pObjOld = Aig_ManPi( pAigOld, index );
+ pNode = Abc_NtkPi( pNtkOld, index );
+ assert( pObjOld->pData == pObjPivot );
+ return Abc_ObjName( pNode );
+ }
+}
+
+static 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_ManPi( 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_ManPi( 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;
+ Saig_ManForEachPo( pAigOld, pObj, i )
+ {
+ pNode = Abc_NtkPo( pNtkOld, i );
+ if( strstr( Abc_ObjName( pNode ), "assert_fair" ) != NULL )
+ {
+ if( strMatch == oldIndex )
+ {
+ sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "LIVENESS");
+ return dummyStr;
+ }
+ else
+ strMatch++;
+ }
+ }
+ }
+ 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;
+ Saig_ManForEachPo( pAigOld, pObj, i )
+ {
+ pNode = Abc_NtkPo( pNtkOld, i );
+ if( strstr( Abc_ObjName( pNode ), "assume_fair" ) != NULL )
+ {
+ if( strMatch == oldIndex )
+ {
+ sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "FAIRNESS");
+ return dummyStr;
+ }
+ else
+ strMatch++;
+ }
+ }
+ }
+ else
+ return "UNKNOWN";
+}
+
+extern Vec_Ptr_t *vecPis, *vecPiNames;
+extern Vec_Ptr_t *vecLos, *vecLoNames;
+
+
+static int Aig_ManPiCleanupBiere( Aig_Man_t * p )
+{
+ int k = 0, nPisOld = Aig_ManPiNum(p);
+
+ p->nObjs[AIG_OBJ_PI] = Vec_PtrSize( p->vPis );
+ if ( Aig_ManRegNum(p) )
+ p->nTruePis = Aig_ManPiNum(p) - Aig_ManRegNum(p);
+
+ return nPisOld - Aig_ManPiNum(p);
+}
+
+
+static int Aig_ManPoCleanupBiere( Aig_Man_t * p )
+{
+ int k = 0, nPosOld = Aig_ManPoNum(p);
+
+ p->nObjs[AIG_OBJ_PO] = Vec_PtrSize( p->vPos );
+ if ( Aig_ManRegNum(p) )
+ p->nTruePos = Aig_ManPoNum(p) - Aig_ManRegNum(p);
+ return nPosOld - Aig_ManPoNum(p);
+}
+
+static Aig_Man_t * LivenessToSafetyTransformationSim( Abc_Ntk_t * pNtk, Aig_Man_t * p, Vec_Ptr_t *vLive, Vec_Ptr_t *vFair )
+{
+ Aig_Man_t * pNew;
+ int i, nRegCount;
+ Aig_Obj_t * pObjSavePi;
+ Aig_Obj_t *pObjSavedLo, *pObjSavedLi;
+ Aig_Obj_t *pObj, *pMatch;
+ Aig_Obj_t *pObjSaveOrSaved, *pObjSavedLoAndEquality;
+ Aig_Obj_t *pObjShadowLo, *pObjShadowLi, *pObjShadowLiDriver;
+ Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc, *pObjAndAccDummy;
+ Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate;
+ Aig_Obj_t *pObjSafetyPropertyOutput;
+ Aig_Obj_t *pDriverImage;
+ char *nodeName;
+ int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, piVecIndex = 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 ) );
+
+#ifdef DUPLICATE_CKT_DEBUG
+ printf("\nCode is compiled in DEBUG mode, the input-output behavior will be the same as the original circuit\n");
+ printf("Press any key to continue...");
+ scanf("%c", &c);
+#endif
+
+ //****************************************************************
+ // 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_ObjCreatePi(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
+ //****************************************************************
+#ifndef DUPLICATE_CKT_DEBUG
+ pObjSavePi = Aig_ObjCreatePi( pNew );
+ nodeName = Abc_UtilStrsav("SAVE_BIERE"),
+ Vec_PtrPush( vecPiNames, nodeName );
+#endif
+
+ //****************************************************************
+ // Step 5: create register outputs
+ //****************************************************************
+ Saig_ManForEachLo( p, pObj, i )
+ {
+ loCopied++;
+ pObj->pData = Aig_ObjCreatePi(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
+ //****************************************************************
+#ifndef DUPLICATE_CKT_DEBUG
+ loCreated++;
+ pObjSavedLo = Aig_ObjCreatePi( pNew );
+ Vec_PtrPush( vecLos, pObjSavedLo );
+ nodeName = Abc_UtilStrsav("SAVED_LO");
+ Vec_PtrPush( vecLoNames, nodeName );
+#endif
+
+ //****************************************************************
+ // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi
+ //****************************************************************
+#ifndef DUPLICATE_CKT_DEBUG
+ 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) );
+ }
+
+ //********************************************************************
+ // 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
+ //********************************************************************
+#ifndef DUPLICATE_CKT_DEBUG
+ pObjSafetyPropertyOutput = Aig_ObjCreatePo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData );
+#endif
+
+ //********************************************************************
+ // DEBUG: To recreate the same circuit, at least from the input and output
+ // behavior, we need to copy the original PO
+ //********************************************************************
+#ifdef DUPLICATE_CKT_DEBUG
+ Saig_ManForEachPo( p, pObj, i )
+ {
+ Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) );
+ }
+#endif
+
+ // create register inputs for the original registers
+ nRegCount = 0;
+
+ Saig_ManForEachLo( p, pObj, i )
+ {
+ pMatch = Saig_ObjLoToLi( p, pObj );
+ //Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pMatch) );
+ Aig_ObjCreatePo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) );
+ nRegCount++;
+ liCopied++;
+ }
+
+ // create register input corresponding to the register "saved"
+#ifndef DUPLICATE_CKT_DEBUG
+ pObjSavedLi = Aig_ObjCreatePo( pNew, pObjSaveOrSaved );
+ nRegCount++;
+ liCreated++;
+
+ pObjAndAcc = NULL;
+
+ // 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_ObjCreatePi( 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, pObjSavePi, (Aig_Obj_t *)pObj->pData, pObjShadowLo );
+ pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver );
+ nRegCount++;
+ loCreated++; liCreated++;
+
+ pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, pObjShadowLo );
+ 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, pObjSavedLo, 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("\nCircuit without any liveness property\n");
+ else
+ {
+ Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i )
+ {
+ //assert( Aig_ObjIsNode( Aig_ObjChild0( pObj ) ) );
+ //Aig_ObjPrint( pNew, pObj );
+ liveLatch++;
+ pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj));
+ pObjShadowLo = Aig_ObjCreatePi( 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, Aig_Mux(pNew, pObjSavePi, Aig_Not(Aig_ManConst1(pNew)), pObjShadowLo),
+ Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) );
+ pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver );
+ nRegCount++;
+ loCreated++; liCreated++;
+
+ if( pObjAndAcc == NULL )
+ pObjAndAcc = pObjShadowLo;
+ else
+ {
+ pObjAndAccDummy = pObjAndAcc;
+ pObjAndAcc = Aig_And( pNew, pObjShadowLo, 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("\nCircuit without any fairness property\n");
+ else
+ {
+ Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i )
+ {
+ fairLatch++;
+ //assert( Aig_ObjIsNode( Aig_ObjChild0( pObj ) ) );
+ pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj));
+ pObjShadowLo = Aig_ObjCreatePi( 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, Aig_Mux(pNew, pObjSavePi, Aig_Not(Aig_ManConst1(pNew)), pObjShadowLo),
+ Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) );
+ pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver );
+ nRegCount++;
+ loCreated++; liCreated++;
+
+ if( pObjAndAcc == NULL )
+ pObjAndAcc = pObjShadowLo;
+ else
+ {
+ pObjAndAccDummy = pObjAndAcc;
+ pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAccDummy );
+ }
+ }
+ }
+
+ if( pObjAndAcc != NULL )
+ pObjFair = pObjAndAcc;
+ else
+ pObjFair = Aig_ManConst1( pNew );
+
+ //pObjSafetyGate = Aig_Exor( pNew, Aig_Not(Aig_ManConst1( pNew )), Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ) );
+ pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) );
+
+ Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate );
+#endif
+
+ Aig_ManSetRegNum( pNew, nRegCount );
+
+ Aig_ManPiCleanupBiere( pNew );
+ Aig_ManPoCleanupBiere( pNew );
+
+ Aig_ManCleanup( pNew );
+ assert( Aig_ManCheck( pNew ) );
+
+#ifndef DUPLICATE_CKT_DEBUG
+ assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vPos, Saig_ManPoNum(pNew)+Aig_ObjPioNum(pObjSavedLo)-Saig_ManPiNum(p)-1) == pObjSavedLi);
+ assert( Saig_ManPoNum( pNew ) == 1 );
+ assert( Saig_ManPiNum( p ) + 1 == Saig_ManPiNum( pNew ) );
+ assert( Saig_ManRegNum( pNew ) == Saig_ManRegNum( p ) * 2 + 1 + liveLatch + fairLatch );
+#endif
+
+ return pNew;
+}
+
+
+static Aig_Man_t * LivenessToSafetyTransformationOneStepLoopSim( Abc_Ntk_t * pNtk, Aig_Man_t * p, Vec_Ptr_t *vLive, Vec_Ptr_t *vFair )
+{
+ Aig_Man_t * pNew;
+ int i, nRegCount;
+ Aig_Obj_t * pObjSavePi;
+ 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;
+ Aig_Obj_t *pDriverImage;
+ Aig_Obj_t *pObjCorrespondingLi;
+
+
+ char *nodeName;
+ int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, piVecIndex = 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 = 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_ObjCreatePi(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
+ //****************************************************************
+ pObjSavePi = Aig_ObjCreatePi( pNew );
+ nodeName = "SAVE_BIERE",
+ Vec_PtrPush( vecPiNames, nodeName );
+
+ //****************************************************************
+ // Step 5: create register outputs
+ //****************************************************************
+ Saig_ManForEachLo( p, pObj, i )
+ {
+ loCopied++;
+ pObj->pData = Aig_ObjCreatePi(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_ObjCreatePi( 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) );
+ }
+
+ //********************************************************************
+ // 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
+ //********************************************************************
+
+ pObjSafetyPropertyOutput = Aig_ObjCreatePo( 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_ObjCreatePo( pNew, Aig_ObjChild0Copy(pMatch) );
+ Aig_ObjCreatePo( 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_ObjCreatePo( pNew, pObjSaveOrSaved );
+ nRegCount++;
+ liCreated++;
+#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
+ //****************************************************************************************************
+
+ 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("\nCircuit 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("\nCircuit 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_ManPiCleanupBiere( pNew );
+ Aig_ManPoCleanupBiere( pNew );
+
+ Aig_ManCleanup( pNew );
+
+ assert( Aig_ManCheck( pNew ) );
+
+ return pNew;
+}
+
+
+
+static 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 )
+ {
+ Vec_PtrPush( vLive, Aig_ManPo( pAig, i ) );
+ liveCounter++;
+ }
+ printf("\nNumber of liveness property found = %d\n", liveCounter);
+ return vLive;
+}
+
+static 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 )
+ {
+ Vec_PtrPush( vFair, Aig_ManPo( pAig, i ) );
+ fairCounter++;
+ }
+ printf("\nNumber of fairness property found = %d\n", fairCounter);
+ return vFair;
+}
+
+static void updateNewNetworkNameManager( Abc_Ntk_t *pNtk, Aig_Man_t *pAig, Vec_Ptr_t *vPiNames, Vec_Ptr_t *vLoNames )
+{
+ Aig_Obj_t *pObj;
+ int i, ntkObjId;
+
+ pNtk->pManName = Nm_ManCreate( Abc_NtkCiNum( pNtk ) );
+
+ 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 );
+ }
+ 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 );
+ }
+}
+
+
+int Abc_CommandAbcLivenessToSafetySim( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ FILE * pOut, * pErr;
+ Abc_Ntk_t * pNtk, * pNtkTemp, *pNtkNew, *pNtkOld;
+ Aig_Man_t * pAig, *pAigNew;
+ int c;
+ Vec_Ptr_t * vLive, * vFair;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if( !Abc_NtkIsStrash( pNtk ) )
+ {
+ printf("\nThe 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 );
+ }
+ else
+ {
+ pAig = Abc_NtkToDar( pNtk, 0, 1 );
+ pNtkOld = pNtk;
+ vLive = populateLivenessVector( pNtk, pAig );
+ vFair = populateFairnessVector( pNtk, pAig );
+ }
+
+#if 0
+ Aig_ManPrintStats( pAig );
+ printf("\nDetail statistics*************************************\n");
+ printf("Number of true primary inputs = %d\n", Saig_ManPiNum( pAig ));
+ printf("Number of true primary outputs = %d\n", Saig_ManPoNum( pAig ));
+ printf("Number of true latch outputs = %d\n", Saig_ManCiNum( pAig ) - Saig_ManPiNum( pAig ));
+ printf("Number of true latch inputs = %d\n", Saig_ManCoNum( pAig ) - Saig_ManPoNum( pAig ));
+ printf("Numer of registers = %d\n", Saig_ManRegNum( pAig ) );
+ printf("\n*******************************************************\n");
+#endif
+
+ c = Extra_UtilGetopt( argc, argv, "1" );
+ if( c == '1' )
+ pAigNew = LivenessToSafetyTransformationOneStepLoopSim( pNtk, pAig, vLive, vFair );
+ else
+ pAigNew = LivenessToSafetyTransformationSim( pNtk, pAig, vLive, vFair );
+
+#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 );
+
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" );
+
+ updateNewNetworkNameManager( pNtkNew, pAigNew, vecPiNames,vecLoNames );
+ Abc_FrameSetCurrentNetwork( pAbc, pNtkNew );
+
+ //Saig_ManForEachPi( pAigNew, pObj, i )
+ // printf("Name of %d-th Pi = %s\n", i, retrieveTruePiName( pNtk, pAig, pAigNew, pObj ) );
+
+ //Saig_ManForEachLo( pAigNew, pObj, i )
+ // printf("Name of %d-th Lo = %s\n", i, retrieveLOName( pNtk, pAig, pAigNew, pObj, vLive, vFair ) );
+
+ //printVecPtrOfString( vecPiNames );
+ //printVecPtrOfString( vecLoNames );
+
+#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;
+
+}
+ABC_NAMESPACE_IMPL_END
+