blob: 7686ec03b16fe381d7ead3240c62358cdc1bb83d [file] [log] [blame]
/**CFile****************************************************************
FileName [pdrMan.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Property driven reachability.]
Synopsis [Manager procedures.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 20, 2010.]
Revision [$Id: pdrMan.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "pdrInt.h"
#include "sat/bmc/bmc.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Structural analysis.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Pdr_ManDeriveFlopPriorities3( Gia_Man_t * p, int fMuxCtrls )
{
int fDiscount = 0;
Vec_Wec_t * vLevels;
Vec_Int_t * vRes, * vLevel, * vCosts;
Gia_Obj_t * pObj, * pCtrl, * pData0, * pData1;
int i, k, Entry, MaxEntry = 0;
Gia_ManCreateRefs(p);
// discount references
if ( fDiscount )
{
Gia_ManForEachAnd( p, pObj, i )
{
if ( !Gia_ObjIsMuxType(pObj) )
continue;
pCtrl = Gia_Regular(Gia_ObjRecognizeMux(pObj, &pData1, &pData0));
pData0 = Gia_Regular(pData0);
pData1 = Gia_Regular(pData1);
p->pRefs[Gia_ObjId(p, pCtrl)]--;
if ( pData0 == pData1 )
p->pRefs[Gia_ObjId(p, pData0)]--;
}
}
// create flop costs
vCosts = Vec_IntAlloc( Gia_ManRegNum(p) );
Gia_ManForEachRo( p, pObj, i )
{
Vec_IntPush( vCosts, Gia_ObjRefNum(p, pObj) );
MaxEntry = Abc_MaxInt( MaxEntry, Gia_ObjRefNum(p, pObj) );
//printf( "%d(%d) ", i, Gia_ObjRefNum(p, pObj) );
}
//printf( "\n" );
MaxEntry++;
// add costs due to MUX inputs
if ( fMuxCtrls )
{
int fVerbose = 0;
Vec_Bit_t * vCtrls = Vec_BitStart( Gia_ManObjNum(p) );
Vec_Bit_t * vDatas = Vec_BitStart( Gia_ManObjNum(p) );
Gia_Obj_t * pCtrl, * pData1, * pData0;
int nCtrls = 0, nDatas = 0, nBoth = 0;
Gia_ManForEachAnd( p, pObj, i )
{
if ( !Gia_ObjIsMuxType(pObj) )
continue;
pCtrl = Gia_ObjRecognizeMux( pObj, &pData1, &pData0 );
pCtrl = Gia_Regular(pCtrl);
pData1 = Gia_Regular(pData1);
pData0 = Gia_Regular(pData0);
Vec_BitWriteEntry( vCtrls, Gia_ObjId(p, pCtrl), 1 );
Vec_BitWriteEntry( vDatas, Gia_ObjId(p, pData1), 1 );
Vec_BitWriteEntry( vDatas, Gia_ObjId(p, pData0), 1 );
}
Gia_ManForEachRo( p, pObj, i )
if ( Vec_BitEntry(vCtrls, Gia_ObjId(p, pObj)) )
Vec_IntAddToEntry( vCosts, i, MaxEntry );
//else if ( Vec_BitEntry(vDatas, Gia_ObjId(p, pObj)) )
// Vec_IntAddToEntry( vCosts, i, MaxEntry );
MaxEntry = 2*MaxEntry + 1;
// print out
if ( fVerbose )
{
Gia_ManForEachRo( p, pObj, i )
{
if ( Vec_BitEntry(vCtrls, Gia_ObjId(p, pObj)) )
nCtrls++;
if ( Vec_BitEntry(vDatas, Gia_ObjId(p, pObj)) )
nDatas++;
if ( Vec_BitEntry(vCtrls, Gia_ObjId(p, pObj)) && Vec_BitEntry(vDatas, Gia_ObjId(p, pObj)) )
nBoth++;
}
printf( "%10s : Flops = %5d. Ctrls = %5d. Datas = %5d. Both = %5d.\n", Gia_ManName(p), Gia_ManRegNum(p), nCtrls, nDatas, nBoth );
}
Vec_BitFree( vCtrls );
Vec_BitFree( vDatas );
}
// create levelized structure
vLevels = Vec_WecStart( MaxEntry );
Vec_IntForEachEntry( vCosts, Entry, i )
Vec_WecPush( vLevels, Entry, i );
// collect in this order
MaxEntry = 0;
vRes = Vec_IntStart( Gia_ManRegNum(p) );
Vec_WecForEachLevel( vLevels, vLevel, i )
Vec_IntForEachEntry( vLevel, Entry, k )
Vec_IntWriteEntry( vRes, Entry, MaxEntry++ );
//printf( "%d ", Gia_ObjRefNum(p, Gia_ManCi(p, Gia_ManPiNum(p)+Entry)) );
//printf( "\n" );
assert( MaxEntry == Gia_ManRegNum(p) );
Vec_WecFree( vLevels );
Vec_IntFree( vCosts );
ABC_FREE( p->pRefs );
//Vec_IntPrint( vRes );
return vRes;
}
/**Function*************************************************************
Synopsis [Structural analysis.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Pdr_ManDeriveFlopPriorities2( Gia_Man_t * p, int fMuxCtrls )
{
int fDiscount = 0;
Vec_Int_t * vRes = NULL;
Gia_Obj_t * pObj, * pCtrl, * pData0, * pData1;
int MaxEntry = 0;
int i, * pPerm;
// create flop costs
Vec_Int_t * vCosts = Vec_IntStart( Gia_ManRegNum(p) );
Gia_ManCreateRefs(p);
// discount references
if ( fDiscount )
{
Gia_ManForEachAnd( p, pObj, i )
{
if ( !Gia_ObjIsMuxType(pObj) )
continue;
pCtrl = Gia_Regular(Gia_ObjRecognizeMux(pObj, &pData1, &pData0));
pData0 = Gia_Regular(pData0);
pData1 = Gia_Regular(pData1);
p->pRefs[Gia_ObjId(p, pCtrl)]--;
if ( pData0 == pData1 )
p->pRefs[Gia_ObjId(p, pData0)]--;
}
}
Gia_ManForEachRo( p, pObj, i )
{
Vec_IntWriteEntry( vCosts, i, Gia_ObjRefNum(p, pObj) );
MaxEntry = Abc_MaxInt( MaxEntry, Gia_ObjRefNum(p, pObj) );
}
MaxEntry++;
ABC_FREE( p->pRefs );
// add costs due to MUX inputs
if ( fMuxCtrls )
{
int fVerbose = 0;
Vec_Bit_t * vCtrls = Vec_BitStart( Gia_ManObjNum(p) );
Vec_Bit_t * vDatas = Vec_BitStart( Gia_ManObjNum(p) );
Gia_Obj_t * pCtrl, * pData1, * pData0;
int nCtrls = 0, nDatas = 0, nBoth = 0;
Gia_ManForEachAnd( p, pObj, i )
{
if ( !Gia_ObjIsMuxType(pObj) )
continue;
pCtrl = Gia_ObjRecognizeMux( pObj, &pData1, &pData0 );
pCtrl = Gia_Regular(pCtrl);
pData1 = Gia_Regular(pData1);
pData0 = Gia_Regular(pData0);
Vec_BitWriteEntry( vCtrls, Gia_ObjId(p, pCtrl), 1 );
Vec_BitWriteEntry( vDatas, Gia_ObjId(p, pData1), 1 );
Vec_BitWriteEntry( vDatas, Gia_ObjId(p, pData0), 1 );
}
Gia_ManForEachRo( p, pObj, i )
if ( Vec_BitEntry(vCtrls, Gia_ObjId(p, pObj)) )
Vec_IntAddToEntry( vCosts, i, MaxEntry );
//else if ( Vec_BitEntry(vDatas, Gia_ObjId(p, pObj)) )
// Vec_IntAddToEntry( vCosts, i, MaxEntry );
// print out
if ( fVerbose )
{
Gia_ManForEachRo( p, pObj, i )
{
if ( Vec_BitEntry(vCtrls, Gia_ObjId(p, pObj)) )
nCtrls++;
if ( Vec_BitEntry(vDatas, Gia_ObjId(p, pObj)) )
nDatas++;
if ( Vec_BitEntry(vCtrls, Gia_ObjId(p, pObj)) && Vec_BitEntry(vDatas, Gia_ObjId(p, pObj)) )
nBoth++;
}
printf( "%10s : Flops = %5d. Ctrls = %5d. Datas = %5d. Both = %5d.\n", Gia_ManName(p), Gia_ManRegNum(p), nCtrls, nDatas, nBoth );
}
Vec_BitFree( vCtrls );
Vec_BitFree( vDatas );
}
// create ordering based on costs
pPerm = Abc_MergeSortCost( Vec_IntArray(vCosts), Vec_IntSize(vCosts) );
vRes = Vec_IntAllocArray( pPerm, Vec_IntSize(vCosts) );
Vec_IntFree( vCosts );
vCosts = Vec_IntInvert( vRes, -1 );
Vec_IntFree( vRes );
//Vec_IntPrint( vCosts );
return vCosts;
}
/**Function*************************************************************
Synopsis [Creates manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Pdr_Man_t * Pdr_ManStart( Aig_Man_t * pAig, Pdr_Par_t * pPars, Vec_Int_t * vPrioInit )
{
Pdr_Man_t * p;
p = ABC_CALLOC( Pdr_Man_t, 1 );
p->pPars = pPars;
p->pAig = pAig;
p->pGia = (pPars->fFlopPrio || p->pPars->fNewXSim || p->pPars->fUseAbs) ? Gia_ManFromAigSimple(pAig) : NULL;
p->vSolvers = Vec_PtrAlloc( 0 );
p->vClauses = Vec_VecAlloc( 0 );
p->pQueue = NULL;
p->pOrder = ABC_ALLOC( int, Aig_ManRegNum(pAig) );
p->vActVars = Vec_IntAlloc( 256 );
if ( !p->pPars->fMonoCnf )
p->vVLits = Vec_WecStart( 1+Abc_MaxInt(1, Aig_ManLevels(pAig)) );
// internal use
p->nPrioShift = Abc_Base2Log(Aig_ManRegNum(pAig));
if ( vPrioInit )
p->vPrio = vPrioInit;
else if ( pPars->fFlopPrio )
p->vPrio = Pdr_ManDeriveFlopPriorities2(p->pGia, 1);
// else if ( p->pPars->fNewXSim )
// p->vPrio = Vec_IntStartNatural( Aig_ManRegNum(pAig) );
else
p->vPrio = Vec_IntStart( Aig_ManRegNum(pAig) );
p->vLits = Vec_IntAlloc( 100 ); // array of literals
p->vCiObjs = Vec_IntAlloc( 100 ); // cone leaves
p->vCoObjs = Vec_IntAlloc( 100 ); // cone roots
p->vCiVals = Vec_IntAlloc( 100 ); // cone leaf values
p->vCoVals = Vec_IntAlloc( 100 ); // cone root values
p->vNodes = Vec_IntAlloc( 100 ); // cone nodes
p->vUndo = Vec_IntAlloc( 100 ); // cone undos
p->vVisits = Vec_IntAlloc( 100 ); // intermediate
p->vCi2Rem = Vec_IntAlloc( 100 ); // CIs to be removed
p->vRes = Vec_IntAlloc( 100 ); // final result
p->pCnfMan = Cnf_ManStart();
// ternary simulation
p->pTxs3 = pPars->fNewXSim ? Txs3_ManStart( p, pAig, p->vPrio ) : NULL;
// additional AIG data-members
if ( pAig->pFanData == NULL )
Aig_ManFanoutStart( pAig );
if ( pAig->pTerSimData == NULL )
pAig->pTerSimData = ABC_CALLOC( unsigned, 1 + (Aig_ManObjNumMax(pAig) / 16) );
// time spent on each outputs
if ( pPars->nTimeOutOne )
{
int i;
p->pTime4Outs = ABC_ALLOC( abctime, Saig_ManPoNum(pAig) );
for ( i = 0; i < Saig_ManPoNum(pAig); i++ )
p->pTime4Outs[i] = pPars->nTimeOutOne * CLOCKS_PER_SEC / 1000 + 1;
}
if ( pPars->fSolveAll )
{
p->vCexes = Vec_PtrStart( Saig_ManPoNum(p->pAig) );
p->pPars->vOutMap = Vec_IntAlloc( Saig_ManPoNum(pAig) );
Vec_IntFill( p->pPars->vOutMap, Saig_ManPoNum(pAig), -2 );
}
return p;
}
/**Function*************************************************************
Synopsis [Frees manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_ManStop( Pdr_Man_t * p )
{
Pdr_Set_t * pCla;
sat_solver * pSat;
int i, k;
Gia_ManStopP( &p->pGia );
Aig_ManCleanMarkAB( p->pAig );
if ( p->pPars->fVerbose )
{
Abc_Print( 1, "Block =%5d Oblig =%6d Clause =%6d Call =%6d (sat=%.1f%%) Cex =%4d Start =%4d\n",
p->nBlocks, p->nObligs, p->nCubes, p->nCalls, 100.0 * p->nCallsS / p->nCalls, p->nCexesTotal, p->nStarts );
ABC_PRTP( "SAT solving", p->tSat, p->tTotal );
ABC_PRTP( " unsat ", p->tSatUnsat, p->tTotal );
ABC_PRTP( " sat ", p->tSatSat, p->tTotal );
ABC_PRTP( "Generalize ", p->tGeneral, p->tTotal );
ABC_PRTP( "Push clause", p->tPush, p->tTotal );
ABC_PRTP( "Ternary sim", p->tTsim, p->tTotal );
ABC_PRTP( "Containment", p->tContain, p->tTotal );
ABC_PRTP( "CNF compute", p->tCnf, p->tTotal );
ABC_PRTP( "Refinement ", p->tAbs, p->tTotal );
ABC_PRTP( "TOTAL ", p->tTotal, p->tTotal );
fflush( stdout );
}
// Abc_Print( 1, "SS =%6d. SU =%6d. US =%6d. UU =%6d.\n", p->nCasesSS, p->nCasesSU, p->nCasesUS, p->nCasesUU );
Vec_PtrForEachEntry( sat_solver *, p->vSolvers, pSat, i )
sat_solver_delete( pSat );
Vec_PtrFree( p->vSolvers );
Vec_VecForEachEntry( Pdr_Set_t *, p->vClauses, pCla, i, k )
Pdr_SetDeref( pCla );
Vec_VecFree( p->vClauses );
Pdr_QueueStop( p );
ABC_FREE( p->pOrder );
Vec_IntFree( p->vActVars );
// static CNF
Cnf_DataFree( p->pCnf1 );
Vec_IntFreeP( &p->vVar2Reg );
// dynamic CNF
Cnf_DataFree( p->pCnf2 );
if ( p->pvId2Vars )
for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ )
ABC_FREE( p->pvId2Vars[i].pArray );
ABC_FREE( p->pvId2Vars );
// Vec_VecFreeP( (Vec_Vec_t **)&p->vVar2Ids );
for ( i = 0; i < Vec_PtrSize(&p->vVar2Ids); i++ )
Vec_IntFree( (Vec_Int_t *)Vec_PtrEntry(&p->vVar2Ids, i) );
ABC_FREE( p->vVar2Ids.pArray );
Vec_WecFreeP( &p->vVLits );
// CNF manager
Cnf_ManStop( p->pCnfMan );
Vec_IntFreeP( &p->vAbsFlops );
Vec_IntFreeP( &p->vMapFf2Ppi );
Vec_IntFreeP( &p->vMapPpi2Ff );
// terminary simulation
if ( p->pPars->fNewXSim )
Txs3_ManStop( p->pTxs3 );
// internal use
Vec_IntFreeP( &p->vPrio ); // priority flops
Vec_IntFree( p->vLits ); // array of literals
Vec_IntFree( p->vCiObjs ); // cone leaves
Vec_IntFree( p->vCoObjs ); // cone roots
Vec_IntFree( p->vCiVals ); // cone leaf values
Vec_IntFree( p->vCoVals ); // cone root values
Vec_IntFree( p->vNodes ); // cone nodes
Vec_IntFree( p->vUndo ); // cone undos
Vec_IntFree( p->vVisits ); // intermediate
Vec_IntFree( p->vCi2Rem ); // CIs to be removed
Vec_IntFree( p->vRes ); // final result
Vec_PtrFreeP( &p->vInfCubes );
ABC_FREE( p->pTime4Outs );
if ( p->vCexes )
Vec_PtrFreeFree( p->vCexes );
// additional AIG data-members
if ( p->pAig->pFanData != NULL )
Aig_ManFanoutStop( p->pAig );
if ( p->pAig->pTerSimData != NULL )
ABC_FREE( p->pAig->pTerSimData );
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis [Derives counter-example.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Cex_t * Pdr_ManDeriveCex( Pdr_Man_t * p )
{
Abc_Cex_t * pCex;
Pdr_Obl_t * pObl;
int i, f, Lit, nFrames = 0;
// count the number of frames
for ( pObl = p->pQueue; pObl; pObl = pObl->pNext )
nFrames++;
// create the counter-example
pCex = Abc_CexAlloc( Aig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), nFrames );
pCex->iPo = p->iOutCur;
pCex->iFrame = nFrames-1;
for ( pObl = p->pQueue, f = 0; pObl; pObl = pObl->pNext, f++ )
for ( i = pObl->pState->nLits; i < pObl->pState->nTotal; i++ )
{
Lit = pObl->pState->Lits[i];
if ( Abc_LitIsCompl(Lit) )
continue;
if ( Abc_Lit2Var(Lit) >= pCex->nPis ) // allows PPI literals to be thrown away
continue;
assert( Abc_Lit2Var(Lit) < pCex->nPis );
Abc_InfoSetBit( pCex->pData, pCex->nRegs + f * pCex->nPis + Abc_Lit2Var(Lit) );
}
assert( f == nFrames );
if ( !Saig_ManVerifyCex(p->pAig, pCex) )
printf( "CEX for output %d is not valid.\n", p->iOutCur );
return pCex;
}
/**Function*************************************************************
Synopsis [Derives counter-example when abstraction is used.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Cex_t * Pdr_ManDeriveCexAbs( Pdr_Man_t * p )
{
extern Gia_Man_t * Gia_ManDupAbs( Gia_Man_t * p, Vec_Int_t * vMapPpi2Ff, Vec_Int_t * vMapFf2Ppi );
Gia_Man_t * pAbs;
Abc_Cex_t * pCex, * pCexCare;
Pdr_Obl_t * pObl;
int i, f, Lit, Flop, nFrames = 0;
int nPis = Saig_ManPiNum(p->pAig);
int nFfRefined = 0;
if ( !p->pPars->fUseAbs || !p->vMapPpi2Ff )
return Pdr_ManDeriveCex(p);
// restore previous map
Vec_IntForEachEntry( p->vMapPpi2Ff, Flop, i )
{
assert( Vec_IntEntry( p->vMapFf2Ppi, Flop ) == i );
Vec_IntWriteEntry( p->vMapFf2Ppi, Flop, -1 );
}
Vec_IntClear( p->vMapPpi2Ff );
// count the number of frames
for ( pObl = p->pQueue; pObl; pObl = pObl->pNext )
{
for ( i = pObl->pState->nLits; i < pObl->pState->nTotal; i++ )
{
Lit = pObl->pState->Lits[i];
if ( Abc_Lit2Var(Lit) < nPis ) // PI literal
continue;
Flop = Abc_Lit2Var(Lit) - nPis;
if ( Vec_IntEntry(p->vMapFf2Ppi, Flop) >= 0 ) // already used PPI literal
continue;
Vec_IntWriteEntry( p->vMapFf2Ppi, Flop, Vec_IntSize(p->vMapPpi2Ff) );
Vec_IntPush( p->vMapPpi2Ff, Flop );
}
nFrames++;
}
if ( Vec_IntSize(p->vMapPpi2Ff) == 0 ) // no PPIs -- this is a real CEX
return Pdr_ManDeriveCex(p);
if ( p->pPars->fUseSimpleRef )
{
// rely on ternary simulation to perform refinement
Vec_IntForEachEntry( p->vMapPpi2Ff, Flop, i )
{
assert( Vec_IntEntry(p->vAbsFlops, Flop) == 0 );
Vec_IntWriteEntry( p->vAbsFlops, Flop, 1 );
nFfRefined++;
}
}
else
{
// create the counter-example
pCex = Abc_CexAlloc( Aig_ManRegNum(p->pAig) - Vec_IntSize(p->vMapPpi2Ff), Saig_ManPiNum(p->pAig) + Vec_IntSize(p->vMapPpi2Ff), nFrames );
pCex->iPo = p->iOutCur;
pCex->iFrame = nFrames-1;
for ( pObl = p->pQueue, f = 0; pObl; pObl = pObl->pNext, f++ )
for ( i = pObl->pState->nLits; i < pObl->pState->nTotal; i++ )
{
Lit = pObl->pState->Lits[i];
if ( Abc_LitIsCompl(Lit) )
continue;
if ( Abc_Lit2Var(Lit) < nPis ) // PI literal
Abc_InfoSetBit( pCex->pData, pCex->nRegs + f * pCex->nPis + Abc_Lit2Var(Lit) );
else
{
int iPPI = nPis + Vec_IntEntry(p->vMapFf2Ppi, Abc_Lit2Var(Lit) - nPis);
assert( iPPI < pCex->nPis );
Abc_InfoSetBit( pCex->pData, pCex->nRegs + f * pCex->nPis + iPPI );
}
}
assert( f == nFrames );
// perform CEX minimization
pAbs = Gia_ManDupAbs( p->pGia, p->vMapPpi2Ff, p->vMapFf2Ppi );
pCexCare = Bmc_CexCareMinimizeAig( pAbs, nPis, pCex, 1, 0, 0 );
Gia_ManStop( pAbs );
assert( pCexCare->nPis == pCex->nPis );
Abc_CexFree( pCex );
// detect care PPIs
for ( f = 0; f < nFrames; f++ )
{
for ( i = nPis; i < pCexCare->nPis; i++ )
if ( Abc_InfoHasBit(pCexCare->pData, pCexCare->nRegs + pCexCare->nPis * f + i) )
{
if ( Vec_IntEntry(p->vAbsFlops, Vec_IntEntry(p->vMapPpi2Ff, i-nPis)) == 0 ) // currently abstracted
Vec_IntWriteEntry( p->vAbsFlops, Vec_IntEntry(p->vMapPpi2Ff, i-nPis), 1 ), nFfRefined++;
}
}
Abc_CexFree( pCexCare );
if ( nFfRefined == 0 ) // no refinement -- this is a real CEX
return Pdr_ManDeriveCex(p);
}
//printf( "CEX-based refinement refined %d flops.\n", nFfRefined );
p->nCexesTotal++;
p->nCexes++;
return NULL;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END