blob: 85fcfa2673294cf7827c54db3b6a187c97cd44d6 [file] [log] [blame]
/**CFile****************************************************************
FileName [cecCore.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Combinational equivalence checking.]
Synopsis [Core procedures.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: cecCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "cecInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [This procedure sets default parameters.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cec_ManSatSetDefaultParams( Cec_ParSat_t * p )
{
memset( p, 0, sizeof(Cec_ParSat_t) );
p->nBTLimit = 100; // conflict limit at a node
p->nSatVarMax = 2000; // the max number of SAT variables
p->nCallsRecycle = 200; // calls to perform before recycling SAT solver
p->fNonChrono = 1; // use non-chronological backtracling (for circuit SAT only)
p->fPolarFlip = 1; // flops polarity of variables
p->fCheckMiter = 0; // the circuit is the miter
// p->fFirstStop = 0; // stop on the first sat output
p->fLearnCls = 0; // perform clause learning
p->fVerbose = 0; // verbose stats
}
/**Function************ *************************************************
Synopsis [This procedure sets default parameters.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cec_ManSimSetDefaultParams( Cec_ParSim_t * p )
{
memset( p, 0, sizeof(Cec_ParSim_t) );
p->nWords = 31; // the number of simulation words
p->nFrames = 100; // the number of simulation frames
p->nRounds = 20; // the max number of simulation rounds
p->nNonRefines = 3; // the max number of rounds without refinement
p->TimeLimit = 0; // the runtime limit in seconds
p->fCheckMiter = 0; // the circuit is the miter
// p->fFirstStop = 0; // stop on the first sat output
p->fDualOut = 0; // miter with separate outputs
p->fConstCorr = 0; // consider only constants
p->fSeqSimulate = 0; // performs sequential simulation
p->fVeryVerbose = 0; // verbose stats
p->fVerbose = 0; // verbose stats
}
/**Function************ *************************************************
Synopsis [This procedure sets default parameters.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cec_ManSmfSetDefaultParams( Cec_ParSmf_t * p )
{
memset( p, 0, sizeof(Cec_ParSmf_t) );
p->nWords = 31; // the number of simulation words
p->nRounds = 200; // the number of simulation rounds
p->nFrames = 200; // the max number of time frames
p->nNonRefines = 3; // the max number of rounds without refinement
p->nMinOutputs = 0; // the min outputs to accumulate
p->nBTLimit = 100; // conflict limit at a node
p->TimeLimit = 0; // the runtime limit in seconds
p->fDualOut = 0; // miter with separate outputs
p->fCheckMiter = 0; // the circuit is the miter
// p->fFirstStop = 0; // stop on the first sat output
p->fVerbose = 0; // verbose stats
}
/**Function************ *************************************************
Synopsis [This procedure sets default parameters.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cec_ManFraSetDefaultParams( Cec_ParFra_t * p )
{
memset( p, 0, sizeof(Cec_ParFra_t) );
p->nWords = 15; // the number of simulation words
p->nRounds = 15; // the number of simulation rounds
p->TimeLimit = 0; // the runtime limit in seconds
p->nItersMax = 10; // the maximum number of iterations of SAT sweeping
p->nBTLimit = 100; // conflict limit at a node
p->nLevelMax = 0; // restriction on the level of nodes to be swept
p->nDepthMax = 1; // the depth in terms of steps of speculative reduction
p->fRewriting = 0; // enables AIG rewriting
p->fCheckMiter = 0; // the circuit is the miter
// p->fFirstStop = 0; // stop on the first sat output
p->fDualOut = 0; // miter with separate outputs
p->fColorDiff = 0; // miter with separate outputs
p->fSatSweeping = 0; // enable SAT sweeping
p->fUseCones = 0; // use cones
p->fVeryVerbose = 0; // verbose stats
p->fVerbose = 0; // verbose stats
p->iOutFail = -1; // the failed output
}
/**Function*************************************************************
Synopsis [This procedure sets default parameters.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cec_ManCecSetDefaultParams( Cec_ParCec_t * p )
{
memset( p, 0, sizeof(Cec_ParCec_t) );
p->nBTLimit = 1000; // conflict limit at a node
p->TimeLimit = 0; // the runtime limit in seconds
// p->fFirstStop = 0; // stop on the first sat output
p->fUseSmartCnf = 0; // use smart CNF computation
p->fRewriting = 0; // enables AIG rewriting
p->fVeryVerbose = 0; // verbose stats
p->fVerbose = 0; // verbose stats
p->iOutFail = -1; // the number of failed output
}
/**Function*************************************************************
Synopsis [This procedure sets default parameters.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cec_ManCorSetDefaultParams( Cec_ParCor_t * p )
{
memset( p, 0, sizeof(Cec_ParCor_t) );
p->nWords = 15; // the number of simulation words
p->nRounds = 15; // the number of simulation rounds
p->nFrames = 1; // the number of time frames
p->nBTLimit = 100; // conflict limit at a node
p->nLevelMax = -1; // (scorr only) the max number of levels
p->nStepsMax = -1; // (scorr only) the max number of induction steps
p->fLatchCorr = 0; // consider only latch outputs
p->fConstCorr = 0; // consider only constants
p->fUseRings = 1; // combine classes into rings
p->fUseCSat = 1; // use circuit-based solver
// p->fFirstStop = 0; // stop on the first sat output
p->fUseSmartCnf = 0; // use smart CNF computation
p->fVeryVerbose = 0; // verbose stats
p->fVerbose = 0; // verbose stats
}
/**Function*************************************************************
Synopsis [This procedure sets default parameters.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cec_ManChcSetDefaultParams( Cec_ParChc_t * p )
{
memset( p, 0, sizeof(Cec_ParChc_t) );
p->nWords = 15; // the number of simulation words
p->nRounds = 15; // the number of simulation rounds
p->nBTLimit = 1000; // conflict limit at a node
p->fUseRings = 1; // use rings
p->fUseCSat = 0; // use circuit-based solver
p->fVeryVerbose = 0; // verbose stats
p->fVerbose = 0; // verbose stats
}
/**Function*************************************************************
Synopsis [Core procedure for SAT sweeping.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Cec_ManSatSolving( Gia_Man_t * pAig, Cec_ParSat_t * pPars )
{
Gia_Man_t * pNew;
Cec_ManPat_t * pPat;
pPat = Cec_ManPatStart();
Cec_ManSatSolve( pPat, pAig, pPars, NULL, NULL, NULL );
// pNew = Gia_ManDupDfsSkip( pAig );
pNew = Gia_ManDup( pAig );
Cec_ManPatStop( pPat );
return pNew;
}
/**Function*************************************************************
Synopsis [Core procedure for simulation.]
Description [Returns 1 if refinement has happened.]
SideEffects []
SeeAlso []
***********************************************************************/
int Cec_ManSimulationOne( Gia_Man_t * pAig, Cec_ParSim_t * pPars )
{
Cec_ManSim_t * pSim;
int RetValue = 0;
abctime clkTotal = Abc_Clock();
pSim = Cec_ManSimStart( pAig, pPars );
if ( (pAig->pReprs == NULL && (RetValue = Cec_ManSimClassesPrepare( pSim, -1 ))) ||
(RetValue == 0 && (RetValue = Cec_ManSimClassesRefine( pSim ))) )
Abc_Print( 1, "The number of failed outputs of the miter = %6d. (Words = %4d. Frames = %4d.)\n",
pSim->nOuts, pPars->nWords, pPars->nFrames );
if ( pPars->fVerbose )
Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal );
Cec_ManSimStop( pSim );
return RetValue;
}
/**Function*************************************************************
Synopsis [Core procedure for simulation.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cec_ManSimulation( Gia_Man_t * pAig, Cec_ParSim_t * pPars )
{
int r, nLitsOld, nLitsNew, nCountNoRef = 0, fStop = 0;
Gia_ManRandom( 1 );
if ( pPars->fSeqSimulate )
Abc_Print( 1, "Performing rounds of random simulation of %d frames with %d words.\n",
pPars->nRounds, pPars->nFrames, pPars->nWords );
nLitsOld = Gia_ManEquivCountLits( pAig );
for ( r = 0; r < pPars->nRounds; r++ )
{
if ( Cec_ManSimulationOne( pAig, pPars ) )
{
fStop = 1;
break;
}
// decide when to stop
nLitsNew = Gia_ManEquivCountLits( pAig );
if ( nLitsOld == 0 || nLitsOld > nLitsNew )
{
nLitsOld = nLitsNew;
nCountNoRef = 0;
}
else if ( ++nCountNoRef == pPars->nNonRefines )
{
r++;
break;
}
assert( nLitsOld == nLitsNew );
}
// if ( pPars->fVerbose )
if ( r == pPars->nRounds || fStop )
Abc_Print( 1, "Random simulation is stopped after %d rounds.\n", r );
else
Abc_Print( 1, "Random simulation saturated after %d rounds.\n", r );
if ( pPars->fCheckMiter )
{
int nNonConsts = Cec_ManCountNonConstOutputs( pAig );
if ( nNonConsts )
Abc_Print( 1, "The number of POs that are not const-0 candidates = %d.\n", nNonConsts );
}
}
/**Function*************************************************************
Synopsis [Core procedure for SAT sweeping.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Cec_ManSatSweeping( Gia_Man_t * pAig, Cec_ParFra_t * pPars, int fSilent )
{
int fOutputResult = 0;
Cec_ParSat_t ParsSat, * pParsSat = &ParsSat;
Cec_ParSim_t ParsSim, * pParsSim = &ParsSim;
Gia_Man_t * pIni, * pSrm, * pTemp;
Cec_ManFra_t * p;
Cec_ManSim_t * pSim;
Cec_ManPat_t * pPat;
int i, fTimeOut = 0, nMatches = 0;
abctime clk, clk2, clkTotal = Abc_Clock();
// duplicate AIG and transfer equivalence classes
Gia_ManRandom( 1 );
pIni = Gia_ManDup(pAig);
pIni->pReprs = pAig->pReprs; pAig->pReprs = NULL;
pIni->pNexts = pAig->pNexts; pAig->pNexts = NULL;
if ( pPars->fUseOrigIds )
{
Gia_ManOrigIdsInit( pIni );
Vec_IntFreeP( &pAig->vIdsEquiv );
pAig->vIdsEquiv = Vec_IntAlloc( 1000 );
}
// prepare the managers
// SAT sweeping
p = Cec_ManFraStart( pIni, pPars );
if ( pPars->fDualOut )
pPars->fColorDiff = 1;
// simulation
Cec_ManSimSetDefaultParams( pParsSim );
pParsSim->nWords = pPars->nWords;
pParsSim->nFrames = pPars->nRounds;
pParsSim->fCheckMiter = pPars->fCheckMiter;
pParsSim->fDualOut = pPars->fDualOut;
pParsSim->fVerbose = pPars->fVerbose;
pSim = Cec_ManSimStart( p->pAig, pParsSim );
// SAT solving
Cec_ManSatSetDefaultParams( pParsSat );
pParsSat->nBTLimit = pPars->nBTLimit;
pParsSat->fVerbose = pPars->fVeryVerbose;
// simulation patterns
pPat = Cec_ManPatStart();
pPat->fVerbose = pPars->fVeryVerbose;
// start equivalence classes
clk = Abc_Clock();
if ( p->pAig->pReprs == NULL )
{
if ( Cec_ManSimClassesPrepare(pSim, -1) || Cec_ManSimClassesRefine(pSim) )
{
Gia_ManStop( p->pAig );
p->pAig = NULL;
goto finalize;
}
}
p->timeSim += Abc_Clock() - clk;
// perform solving
for ( i = 1; i <= pPars->nItersMax; i++ )
{
clk2 = Abc_Clock();
nMatches = 0;
if ( pPars->fDualOut )
{
nMatches = Gia_ManEquivSetColors( p->pAig, pPars->fVeryVerbose );
// p->pAig->pIso = Cec_ManDetectIsomorphism( p->pAig );
// Gia_ManEquivTransform( p->pAig, 1 );
}
pSrm = Cec_ManFraSpecReduction( p );
// Gia_AigerWrite( pSrm, "gia_srm.aig", 0, 0 );
if ( pPars->fVeryVerbose )
Gia_ManPrintStats( pSrm, NULL );
if ( Gia_ManCoNum(pSrm) == 0 )
{
Gia_ManStop( pSrm );
if ( p->pPars->fVerbose )
Abc_Print( 1, "Considered all available candidate equivalences.\n" );
if ( pPars->fDualOut && Gia_ManAndNum(p->pAig) > 0 )
{
if ( pPars->fColorDiff )
{
if ( p->pPars->fVerbose )
Abc_Print( 1, "Switching into reduced mode.\n" );
pPars->fColorDiff = 0;
}
else
{
if ( p->pPars->fVerbose )
Abc_Print( 1, "Switching into normal mode.\n" );
pPars->fDualOut = 0;
}
continue;
}
break;
}
clk = Abc_Clock();
if ( pPars->fRunCSat )
Cec_ManSatSolveCSat( pPat, pSrm, pParsSat );
else
Cec_ManSatSolve( pPat, pSrm, pParsSat, p->pAig->vIdsOrig, p->vXorNodes, pAig->vIdsEquiv );
p->timeSat += Abc_Clock() - clk;
if ( Cec_ManFraClassesUpdate( p, pSim, pPat, pSrm ) )
{
Gia_ManStop( pSrm );
Gia_ManStop( p->pAig );
p->pAig = NULL;
goto finalize;
}
Gia_ManStop( pSrm );
// update the manager
pSim->pAig = p->pAig = Gia_ManEquivReduceAndRemap( pTemp = p->pAig, 0, pParsSim->fDualOut );
if ( p->pAig == NULL )
{
p->pAig = pTemp;
break;
}
Gia_ManStop( pTemp );
if ( p->pPars->fVerbose )
{
Abc_Print( 1, "%3d : P =%7d. D =%7d. F =%6d. M = %7d. And =%8d. ",
i, p->nAllProved, p->nAllDisproved, p->nAllFailed, nMatches, Gia_ManAndNum(p->pAig) );
Abc_PrintTime( 1, "Time", Abc_Clock() - clk2 );
}
if ( Gia_ManAndNum(p->pAig) == 0 )
{
if ( p->pPars->fVerbose )
Abc_Print( 1, "Network after reduction is empty.\n" );
break;
}
// check resource limits
if ( p->pPars->TimeLimit && (Abc_Clock() - clkTotal)/CLOCKS_PER_SEC >= p->pPars->TimeLimit )
{
fTimeOut = 1;
break;
}
// if ( p->nAllFailed && !p->nAllProved && !p->nAllDisproved )
if ( p->nAllFailed > p->nAllProved + p->nAllDisproved )
{
if ( pParsSat->nBTLimit >= 10001 )
break;
if ( pPars->fSatSweeping )
{
if ( p->pPars->fVerbose )
Abc_Print( 1, "Exceeded the limit on the number of conflicts (%d).\n", pParsSat->nBTLimit );
break;
}
pParsSat->nBTLimit *= 10;
if ( p->pPars->fVerbose )
{
if ( p->pPars->fVerbose )
Abc_Print( 1, "Increasing conflict limit to %d.\n", pParsSat->nBTLimit );
if ( fOutputResult )
{
Gia_AigerWrite( p->pAig, "gia_cec_temp.aig", 0, 0 );
Abc_Print( 1,"The result is written into file \"%s\".\n", "gia_cec_temp.aig" );
}
}
}
if ( pPars->fDualOut && pPars->fColorDiff && (Gia_ManAndNum(p->pAig) < 100000 || p->nAllProved + p->nAllDisproved < 10) )
{
if ( p->pPars->fVerbose )
Abc_Print( 1, "Switching into reduced mode.\n" );
pPars->fColorDiff = 0;
}
// if ( pPars->fDualOut && Gia_ManAndNum(p->pAig) < 20000 )
else if ( pPars->fDualOut && (Gia_ManAndNum(p->pAig) < 20000 || p->nAllProved + p->nAllDisproved < 10) )
{
if ( p->pPars->fVerbose )
Abc_Print( 1, "Switching into normal mode.\n" );
pPars->fColorDiff = 0;
pPars->fDualOut = 0;
}
}
finalize:
if ( p->pPars->fVerbose && p->pAig )
{
Abc_Print( 1, "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n",
Gia_ManAndNum(pAig), Gia_ManAndNum(p->pAig),
100.0*(Gia_ManAndNum(pAig)-Gia_ManAndNum(p->pAig))/(Gia_ManAndNum(pAig)?Gia_ManAndNum(pAig):1),
Gia_ManRegNum(pAig), Gia_ManRegNum(p->pAig),
100.0*(Gia_ManRegNum(pAig)-Gia_ManRegNum(p->pAig))/(Gia_ManRegNum(pAig)?Gia_ManRegNum(pAig):1) );
Abc_PrintTimeP( 1, "Sim ", p->timeSim, Abc_Clock() - (int)clkTotal );
Abc_PrintTimeP( 1, "Sat ", p->timeSat-pPat->timeTotalSave, Abc_Clock() - (int)clkTotal );
Abc_PrintTimeP( 1, "Pat ", p->timePat+pPat->timeTotalSave, Abc_Clock() - (int)clkTotal );
Abc_PrintTime( 1, "Time", (int)(Abc_Clock() - clkTotal) );
}
pTemp = p->pAig; p->pAig = NULL;
if ( pTemp == NULL && pSim->iOut >= 0 )
{
if ( !fSilent )
Abc_Print( 1, "Disproved at least one output of the miter (zero-based number %d).\n", pSim->iOut );
pPars->iOutFail = pSim->iOut;
}
else if ( pSim->pCexes && !fSilent )
Abc_Print( 1, "Disproved %d outputs of the miter.\n", pSim->nOuts );
if ( fTimeOut && !fSilent )
Abc_Print( 1, "Timed out after %d seconds.\n", (int)((double)Abc_Clock() - clkTotal)/CLOCKS_PER_SEC );
pAig->pCexComb = pSim->pCexComb; pSim->pCexComb = NULL;
Cec_ManSimStop( pSim );
Cec_ManPatStop( pPat );
Cec_ManFraStop( p );
return pTemp;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END