blob: 8b054b578125a0bf7cc1717cbc75f1bbf0b41932 [file] [log] [blame]
/**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 "base/main/main.h"
#include "aig/aig/aig.h"
#include "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_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 );
}
}
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_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;
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";
return NULL;
}
extern Vec_Ptr_t *vecPis, *vecPiNames;
extern Vec_Ptr_t *vecLos, *vecLoNames;
static 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);
}
static 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);
}
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, 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_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
//****************************************************************
#ifndef DUPLICATE_CKT_DEBUG
pObjSavePi = Aig_ObjCreateCi( 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_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
//****************************************************************
#ifndef DUPLICATE_CKT_DEBUG
loCreated++;
pObjSavedLo = Aig_ObjCreateCi( 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_ObjCreateCo( 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_ObjCreateCo( 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_ObjCreateCo( pNew, Aig_ObjChild0Copy(pMatch) );
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"
#ifndef DUPLICATE_CKT_DEBUG
pObjSavedLi = Aig_ObjCreateCo( 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_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, pObjSavePi, (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 );
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_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, Aig_Mux(pNew, pObjSavePi, Aig_Not(Aig_ManConst1(pNew)), pObjShadowLo),
Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) );
pObjShadowLi = Aig_ObjCreateCo( 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_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, Aig_Mux(pNew, pObjSavePi, Aig_Not(Aig_ManConst1(pNew)), pObjShadowLo),
Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) );
pObjShadowLi = Aig_ObjCreateCo( 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_ManCiCleanupBiere( pNew );
Aig_ManCoCleanupBiere( pNew );
Aig_ManCleanup( pNew );
assert( Aig_ManCheck( pNew ) );
#ifndef DUPLICATE_CKT_DEBUG
assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vCos, Saig_ManPoNum(pNew)+Aig_ObjCioId(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_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
//****************************************************************
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) );
}
//********************************************************************
// 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_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++;
#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->vCis ), pNew->nRegs );
Aig_ManCiCleanupBiere( pNew );
Aig_ManCoCleanupBiere( 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_ManCo( 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_ManCo( 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