blob: 1e517e7de1a5ccb71d426281b7ba547c6fd8b009 [file] [log] [blame]
/**CFile****************************************************************
FileName [fraCore.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [New FRAIG package.]
Synopsis []
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 30, 2007.]
Revision [$Id: fraCore.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
***********************************************************************/
#include "fra.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
/*
Speculating reduction in the sequential case leads to an interesting
situation when a counter-ex may not refine any classes. This happens
for non-constant equivalence classes. In such cases the representative
of the class (proved by simulation to be non-constant) may be reduced
to a constant during the speculative reduction. The fraig-representative
of this representative node is a constant node, even though this is a
non-constant class. Experiments have shown that this situation happens
very often at the beginning of the refinement iteration when there are
many spurious candidate equivalence classes (especially if heavy-duty
simulatation of BMC was node used at the beginning). As a result, the
SAT solver run may return a counter-ex that distinguishes the given
representative node from the constant-1 node but this counter-ex
does not distinguish the nodes in the non-costant class... This is why
there is no check of refinement after a counter-ex in the sequential case.
*/
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Reports the status of the miter.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Fra_FraigMiterStatus( Aig_Man_t * p )
{
Aig_Obj_t * pObj, * pChild;
int i, CountConst0 = 0, CountNonConst0 = 0, CountUndecided = 0;
if ( p->pData )
return 0;
Aig_ManForEachPoSeq( p, pObj, i )
{
pChild = Aig_ObjChild0(pObj);
// check if the output is constant 0
if ( pChild == Aig_ManConst0(p) )
{
CountConst0++;
continue;
}
// check if the output is constant 1
if ( pChild == Aig_ManConst1(p) )
{
CountNonConst0++;
continue;
}
// check if the output is a primary input
if ( Aig_ObjIsCi(Aig_Regular(pChild)) && Aig_ObjCioId(Aig_Regular(pChild)) < p->nTruePis )
{
CountNonConst0++;
continue;
}
// check if the output can be not constant 0
if ( Aig_Regular(pChild)->fPhase != (unsigned)Aig_IsComplement(pChild) )
{
CountNonConst0++;
continue;
}
CountUndecided++;
}
/*
if ( p->pParams->fVerbose )
{
printf( "Miter has %d outputs. ", Aig_ManCoNum(p->pManAig) );
printf( "Const0 = %d. ", CountConst0 );
printf( "NonConst0 = %d. ", CountNonConst0 );
printf( "Undecided = %d. ", CountUndecided );
printf( "\n" );
}
*/
if ( CountNonConst0 )
return 0;
if ( CountUndecided )
return -1;
return 1;
}
/**Function*************************************************************
Synopsis [Reports the status of the miter.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Fra_FraigMiterAssertedOutput( Aig_Man_t * p )
{
Aig_Obj_t * pObj, * pChild;
int i;
Aig_ManForEachPoSeq( p, pObj, i )
{
pChild = Aig_ObjChild0(pObj);
// check if the output is constant 0
if ( pChild == Aig_ManConst0(p) )
continue;
// check if the output is constant 1
if ( pChild == Aig_ManConst1(p) )
return i;
// check if the output can be not constant 0
if ( Aig_Regular(pChild)->fPhase != (unsigned)Aig_IsComplement(pChild) )
return i;
}
return -1;
}
/**Function*************************************************************
Synopsis [Write speculative miter for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Fra_FraigNodeSpeculate( Fra_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pObjFraig, Aig_Obj_t * pObjReprFraig )
{
static int Counter = 0;
char FileName[20];
Aig_Man_t * pTemp;
Aig_Obj_t * pNode;
int i;
// create manager with the logic for these two nodes
pTemp = Aig_ManExtractMiter( p->pManFraig, pObjFraig, pObjReprFraig );
// dump the logic into a file
sprintf( FileName, "aig\\%03d.blif", ++Counter );
Aig_ManDumpBlif( pTemp, FileName, NULL, NULL );
printf( "Speculation cone with %d nodes was written into file \"%s\".\n", Aig_ManNodeNum(pTemp), FileName );
// clean up
Aig_ManStop( pTemp );
Aig_ManForEachObj( p->pManFraig, pNode, i )
pNode->pData = p;
}
/**Function*************************************************************
Synopsis [Verifies the generated counter-ex.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Fra_FraigVerifyCounterEx( Fra_Man_t * p, Vec_Int_t * vCex )
{
Aig_Obj_t * pObj, ** ppClass;
int i, c;
assert( Aig_ManCiNum(p->pManAig) == Vec_IntSize(vCex) );
// make sure the input pattern is not used
Aig_ManForEachObj( p->pManAig, pObj, i )
assert( !pObj->fMarkB );
// simulate the cex through the AIG
Aig_ManConst1(p->pManAig)->fMarkB = 1;
Aig_ManForEachCi( p->pManAig, pObj, i )
pObj->fMarkB = Vec_IntEntry(vCex, i);
Aig_ManForEachNode( p->pManAig, pObj, i )
pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) &
(Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj));
Aig_ManForEachCo( p->pManAig, pObj, i )
pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj);
// check if the classes hold
Vec_PtrForEachEntry( Aig_Obj_t *, p->pCla->vClasses1, pObj, i )
{
if ( pObj->fPhase != pObj->fMarkB )
printf( "The node %d is not constant under cex!\n", pObj->Id );
}
Vec_PtrForEachEntry( Aig_Obj_t **, p->pCla->vClasses, ppClass, i )
{
for ( c = 1; ppClass[c]; c++ )
if ( (ppClass[0]->fPhase ^ ppClass[c]->fPhase) != (ppClass[0]->fMarkB ^ ppClass[c]->fMarkB) )
printf( "The nodes %d and %d are not equal under cex!\n", ppClass[0]->Id, ppClass[c]->Id );
// for ( c = 0; ppClass[c]; c++ )
// if ( Fra_ObjFraig(ppClass[c],p->pPars->nFramesK) == Aig_ManConst1(p->pManFraig) )
// printf( "A member of non-constant class has a constant repr!\n" );
}
// clean the simulation pattern
Aig_ManForEachObj( p->pManAig, pObj, i )
pObj->fMarkB = 0;
}
/**Function*************************************************************
Synopsis [Performs fraiging for one node.]
Description [Returns the fraiged node.]
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Fra_FraigNode( Fra_Man_t * p, Aig_Obj_t * pObj )
{
Aig_Obj_t * pObjRepr, * pObjFraig, * pObjFraig2, * pObjReprFraig;
int RetValue;
assert( !Aig_IsComplement(pObj) );
// get representative of this class
pObjRepr = Fra_ClassObjRepr( pObj );
if ( pObjRepr == NULL || // this is a unique node
(!p->pPars->fDoSparse && pObjRepr == Aig_ManConst1(p->pManAig)) ) // this is a sparse node
return;
// get the fraiged node
pObjFraig = Fra_ObjFraig( pObj, p->pPars->nFramesK );
// get the fraiged representative
pObjReprFraig = Fra_ObjFraig( pObjRepr, p->pPars->nFramesK );
// if the fraiged nodes are the same, return
if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) )
{
p->nSatCallsSkipped++;
return;
}
assert( p->pPars->nFramesK || Aig_Regular(pObjFraig) != Aig_ManConst1(p->pManFraig) );
// if they are proved different, the c-ex will be in p->pPatWords
RetValue = Fra_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) );
if ( RetValue == 1 ) // proved equivalent
{
// if ( p->pPars->fChoicing )
// Aig_ObjCreateRepr( p->pManFraig, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) );
// the nodes proved equal
pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase );
Fra_ObjSetFraig( pObj, p->pPars->nFramesK, pObjFraig2 );
return;
}
if ( RetValue == -1 ) // failed
{
if ( p->vTimeouts == NULL )
p->vTimeouts = Vec_PtrAlloc( 100 );
Vec_PtrPush( p->vTimeouts, pObj );
if ( !p->pPars->fSpeculate )
return;
assert( 0 );
// speculate
p->nSpeculs++;
pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase );
Fra_ObjSetFraig( pObj, p->pPars->nFramesK, pObjFraig2 );
Fra_FraigNodeSpeculate( p, pObj, Aig_Regular(pObjFraig), Aig_Regular(pObjReprFraig) );
return;
}
// disprove the nodes
p->pCla->fRefinement = 1;
// if we do not include the node into those disproved, we may end up
// merging this node with another representative, for which proof has timed out
if ( p->vTimeouts )
Vec_PtrPush( p->vTimeouts, pObj );
// verify that the counter-example satisfies all the constraints
// if ( p->vCex )
// Fra_FraigVerifyCounterEx( p, p->vCex );
// simulate the counter-example and return the Fraig node
Fra_SmlResimulate( p );
if ( p->pManFraig->pData )
return;
if ( !p->pPars->nFramesK && Fra_ClassObjRepr(pObj) == pObjRepr )
printf( "Fra_FraigNode(): Error in class refinement!\n" );
assert( p->pPars->nFramesK || Fra_ClassObjRepr(pObj) != pObjRepr );
}
/**Function*************************************************************
Synopsis [Performs fraiging for the internal nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Fra_FraigSweep( Fra_Man_t * p )
{
// Bar_Progress_t * pProgress = NULL;
Aig_Obj_t * pObj, * pObjNew;
int i, Pos = 0;
int nBTracksOld;
// fraig latch outputs
Aig_ManForEachLoSeq( p->pManAig, pObj, i )
{
Fra_FraigNode( p, pObj );
if ( p->pPars->fUseImps )
Pos = Fra_ImpCheckForNode( p, p->pCla->vImps, pObj, Pos );
}
if ( p->pPars->fLatchCorr )
return;
// fraig internal nodes
// if ( !p->pPars->fDontShowBar )
// pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pManAig) );
nBTracksOld = p->pPars->nBTLimitNode;
Aig_ManForEachNode( p->pManAig, pObj, i )
{
// if ( pProgress )
// Bar_ProgressUpdate( pProgress, i, NULL );
// derive and remember the new fraig node
pObjNew = Aig_And( p->pManFraig, Fra_ObjChild0Fra(pObj,p->pPars->nFramesK), Fra_ObjChild1Fra(pObj,p->pPars->nFramesK) );
Fra_ObjSetFraig( pObj, p->pPars->nFramesK, pObjNew );
Aig_Regular(pObjNew)->pData = p;
// quit if simulation detected a counter-example for a PO
if ( p->pManFraig->pData )
continue;
// if ( Aig_SupportSize(p->pManAig,pObj) > 16 )
// continue;
// perform fraiging
if ( p->pPars->nLevelMax && (int)pObj->Level > p->pPars->nLevelMax )
p->pPars->nBTLimitNode = 5;
Fra_FraigNode( p, pObj );
if ( p->pPars->nLevelMax && (int)pObj->Level > p->pPars->nLevelMax )
p->pPars->nBTLimitNode = nBTracksOld;
// check implications
if ( p->pPars->fUseImps )
Pos = Fra_ImpCheckForNode( p, p->pCla->vImps, pObj, Pos );
}
// if ( pProgress )
// Bar_ProgressStop( pProgress );
// try to prove the outputs of the miter
p->nNodesMiter = Aig_ManNodeNum(p->pManFraig);
// Fra_MiterStatus( p->pManFraig );
// if ( p->pPars->fProve && p->pManFraig->pData == NULL )
// Fra_MiterProve( p );
// compress implications after processing all of them
if ( p->pPars->fUseImps )
Fra_ImpCompactArray( p->pCla->vImps );
}
/**Function*************************************************************
Synopsis [Performs fraiging of the AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Aig_Man_t * Fra_FraigPerform( Aig_Man_t * pManAig, Fra_Par_t * pPars )
{
Fra_Man_t * p;
Aig_Man_t * pManAigNew;
abctime clk;
if ( Aig_ManNodeNum(pManAig) == 0 )
return Aig_ManDupOrdered(pManAig);
clk = Abc_Clock();
p = Fra_ManStart( pManAig, pPars );
p->pManFraig = Fra_ManPrepareComb( p );
p->pSml = Fra_SmlStart( pManAig, 0, 1, pPars->nSimWords );
Fra_SmlSimulate( p, 0 );
// if ( p->pPars->fChoicing )
// Aig_ManReprStart( p->pManFraig, Aig_ManObjNumMax(p->pManAig) );
// collect initial states
p->nLitsBeg = Fra_ClassesCountLits( p->pCla );
p->nNodesBeg = Aig_ManNodeNum(pManAig);
p->nRegsBeg = Aig_ManRegNum(pManAig);
// perform fraig sweep
if ( p->pPars->fVerbose )
Fra_ClassesPrint( p->pCla, 1 );
Fra_FraigSweep( p );
// call back the procedure to check implications
if ( pManAig->pImpFunc )
pManAig->pImpFunc( p, pManAig->pImpData );
// no need to filter one-hot clauses because they satisfy base case by construction
// finalize the fraiged manager
Fra_ManFinalizeComb( p );
if ( p->pPars->fChoicing )
{
abctime clk2 = Abc_Clock();
Fra_ClassesCopyReprs( p->pCla, p->vTimeouts );
pManAigNew = Aig_ManDupRepr( p->pManAig, 1 );
Aig_ManReprStart( pManAigNew, Aig_ManObjNumMax(pManAigNew) );
Aig_ManTransferRepr( pManAigNew, p->pManAig );
Aig_ManMarkValidChoices( pManAigNew );
Aig_ManStop( p->pManFraig );
p->pManFraig = NULL;
p->timeTrav += Abc_Clock() - clk2;
}
else
{
Fra_ClassesCopyReprs( p->pCla, p->vTimeouts );
Aig_ManCleanup( p->pManFraig );
pManAigNew = p->pManFraig;
p->pManFraig = NULL;
}
p->timeTotal = Abc_Clock() - clk;
// collect final stats
p->nLitsEnd = Fra_ClassesCountLits( p->pCla );
p->nNodesEnd = Aig_ManNodeNum(pManAigNew);
p->nRegsEnd = Aig_ManRegNum(pManAigNew);
Fra_ManStop( p );
return pManAigNew;
}
/**Function*************************************************************
Synopsis [Performs choicing of the AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Aig_Man_t * Fra_FraigChoice( Aig_Man_t * pManAig, int nConfMax, int nLevelMax )
{
Fra_Par_t Pars, * pPars = &Pars;
Fra_ParamsDefault( pPars );
pPars->nBTLimitNode = nConfMax;
pPars->fChoicing = 1;
pPars->fDoSparse = 1;
pPars->fSpeculate = 0;
pPars->fProve = 0;
pPars->fVerbose = 0;
pPars->fDontShowBar = 1;
pPars->nLevelMax = nLevelMax;
return Fra_FraigPerform( pManAig, pPars );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Aig_Man_t * Fra_FraigEquivence( Aig_Man_t * pManAig, int nConfMax, int fProve )
{
Aig_Man_t * pFraig;
Fra_Par_t Pars, * pPars = &Pars;
Fra_ParamsDefault( pPars );
pPars->nBTLimitNode = nConfMax;
pPars->fChoicing = 0;
pPars->fDoSparse = 1;
pPars->fSpeculate = 0;
pPars->fProve = fProve;
pPars->fVerbose = 0;
pPars->fDontShowBar = 1;
pFraig = Fra_FraigPerform( pManAig, pPars );
return pFraig;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END