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