summaryrefslogtreecommitdiffstats
path: root/src/proof
diff options
context:
space:
mode:
authorAlan Mishchenko <alanmi@berkeley.edu>2012-01-21 04:30:10 -0800
committerAlan Mishchenko <alanmi@berkeley.edu>2012-01-21 04:30:10 -0800
commit8014f25f6db719fa62336f997963532a14c568f6 (patch)
treec691ee91a3a2d452a2bd24ac89a8c717beaa7af7 /src/proof
parentc44cc5de9429e6b4f1c05045fcf43c9cb96437b5 (diff)
downloadabc-8014f25f6db719fa62336f997963532a14c568f6.tar.gz
abc-8014f25f6db719fa62336f997963532a14c568f6.tar.bz2
abc-8014f25f6db719fa62336f997963532a14c568f6.zip
Major restructuring of the code.
Diffstat (limited to 'src/proof')
-rw-r--r--src/proof/bbr/bbr.h93
-rw-r--r--src/proof/bbr/bbrCex.c172
-rw-r--r--src/proof/bbr/bbrImage.c1327
-rw-r--r--src/proof/bbr/bbrNtbdd.c218
-rw-r--r--src/proof/bbr/bbrReach.c606
-rw-r--r--src/proof/bbr/bbr_.c52
-rw-r--r--src/proof/bbr/module.make4
-rw-r--r--src/proof/cec/cec.c53
-rw-r--r--src/proof/cec/cec.h233
-rw-r--r--src/proof/cec/cecCec.c373
-rw-r--r--src/proof/cec/cecChoice.c409
-rw-r--r--src/proof/cec/cecClass.c931
-rw-r--r--src/proof/cec/cecCore.c542
-rw-r--r--src/proof/cec/cecCorr.c1137
-rw-r--r--src/proof/cec/cecCorr_updated.c1027
-rw-r--r--src/proof/cec/cecInt.h225
-rw-r--r--src/proof/cec/cecIso.c375
-rw-r--r--src/proof/cec/cecMan.c297
-rw-r--r--src/proof/cec/cecPat.c569
-rw-r--r--src/proof/cec/cecSeq.c448
-rw-r--r--src/proof/cec/cecSim.c53
-rw-r--r--src/proof/cec/cecSolve.c1023
-rw-r--r--src/proof/cec/cecSweep.c299
-rw-r--r--src/proof/cec/cecSynth.c380
-rw-r--r--src/proof/cec/module.make13
-rw-r--r--src/proof/dch/dch.h90
-rw-r--r--src/proof/dch/dchAig.c119
-rw-r--r--src/proof/dch/dchChoice.c508
-rw-r--r--src/proof/dch/dchClass.c611
-rw-r--r--src/proof/dch/dchCnf.c334
-rw-r--r--src/proof/dch/dchCore.c158
-rw-r--r--src/proof/dch/dchInt.h170
-rw-r--r--src/proof/dch/dchMan.c191
-rw-r--r--src/proof/dch/dchSat.c166
-rw-r--r--src/proof/dch/dchSim.c297
-rw-r--r--src/proof/dch/dchSimSat.c258
-rw-r--r--src/proof/dch/dchSweep.c146
-rw-r--r--src/proof/dch/module.make10
-rw-r--r--src/proof/fra/fra.h389
-rw-r--r--src/proof/fra/fraBmc.c451
-rw-r--r--src/proof/fra/fraCec.c516
-rw-r--r--src/proof/fra/fraClass.c862
-rw-r--r--src/proof/fra/fraClau.c763
-rw-r--r--src/proof/fra/fraClaus.c1875
-rw-r--r--src/proof/fra/fraCnf.c289
-rw-r--r--src/proof/fra/fraCore.c490
-rw-r--r--src/proof/fra/fraHot.c476
-rw-r--r--src/proof/fra/fraImp.c731
-rw-r--r--src/proof/fra/fraInd.c709
-rw-r--r--src/proof/fra/fraIndVer.c166
-rw-r--r--src/proof/fra/fraLcr.c709
-rw-r--r--src/proof/fra/fraMan.c314
-rw-r--r--src/proof/fra/fraPart.c268
-rw-r--r--src/proof/fra/fraSat.c566
-rw-r--r--src/proof/fra/fraSec.c696
-rw-r--r--src/proof/fra/fraSim.c1023
-rw-r--r--src/proof/fra/fra_.c53
-rw-r--r--src/proof/fra/module.make17
-rw-r--r--src/proof/fraig/fraig.h260
-rw-r--r--src/proof/fraig/fraigApi.c302
-rw-r--r--src/proof/fraig/fraigCanon.c223
-rw-r--r--src/proof/fraig/fraigChoice.c246
-rw-r--r--src/proof/fraig/fraigFanout.c180
-rw-r--r--src/proof/fraig/fraigFeed.c913
-rw-r--r--src/proof/fraig/fraigInt.h433
-rw-r--r--src/proof/fraig/fraigMan.c545
-rw-r--r--src/proof/fraig/fraigMem.c251
-rw-r--r--src/proof/fraig/fraigNode.c318
-rw-r--r--src/proof/fraig/fraigPrime.c113
-rw-r--r--src/proof/fraig/fraigSat.c1459
-rw-r--r--src/proof/fraig/fraigTable.c662
-rw-r--r--src/proof/fraig/fraigUtil.c1039
-rw-r--r--src/proof/fraig/fraigVec.c550
-rw-r--r--src/proof/fraig/module.make12
-rw-r--r--src/proof/int/int.h94
-rw-r--r--src/proof/int/intCheck.c305
-rw-r--r--src/proof/int/intContain.c341
-rw-r--r--src/proof/int/intCore.c389
-rw-r--r--src/proof/int/intCtrex.c167
-rw-r--r--src/proof/int/intDup.c184
-rw-r--r--src/proof/int/intFrames.c115
-rw-r--r--src/proof/int/intInt.h142
-rw-r--r--src/proof/int/intInter.c145
-rw-r--r--src/proof/int/intM114.c320
-rw-r--r--src/proof/int/intM114p.c442
-rw-r--r--src/proof/int/intMan.c163
-rw-r--r--src/proof/int/intUtil.c108
-rw-r--r--src/proof/int/module.make11
-rw-r--r--src/proof/live/liveness.c2575
-rw-r--r--src/proof/live/liveness_sim.c848
-rw-r--r--src/proof/live/ltl_parser.c839
-rw-r--r--src/proof/live/module.make3
-rw-r--r--src/proof/llb/llb.c52
-rw-r--r--src/proof/llb/llb.h96
-rw-r--r--src/proof/llb/llb1Cluster.c356
-rw-r--r--src/proof/llb/llb1Constr.c313
-rw-r--r--src/proof/llb/llb1Core.c222
-rw-r--r--src/proof/llb/llb1Group.c474
-rw-r--r--src/proof/llb/llb1Hint.c226
-rw-r--r--src/proof/llb/llb1Man.c218
-rw-r--r--src/proof/llb/llb1Matrix.c430
-rw-r--r--src/proof/llb/llb1Pivot.c254
-rw-r--r--src/proof/llb/llb1Reach.c898
-rw-r--r--src/proof/llb/llb1Sched.c257
-rw-r--r--src/proof/llb/llb2Bad.c137
-rw-r--r--src/proof/llb/llb2Core.c775
-rw-r--r--src/proof/llb/llb2Driver.c221
-rw-r--r--src/proof/llb/llb2Dump.c104
-rw-r--r--src/proof/llb/llb2Flow.c1374
-rw-r--r--src/proof/llb/llb2Image.c478
-rw-r--r--src/proof/llb/llb3Image.c1093
-rw-r--r--src/proof/llb/llb3Nonlin.c871
-rw-r--r--src/proof/llb/llb4Cex.c320
-rw-r--r--src/proof/llb/llb4Cluster.c452
-rw-r--r--src/proof/llb/llb4Image.c861
-rw-r--r--src/proof/llb/llb4Map.c123
-rw-r--r--src/proof/llb/llb4Nonlin.c1080
-rw-r--r--src/proof/llb/llb4Sweep.c588
-rw-r--r--src/proof/llb/llbInt.h211
-rw-r--r--src/proof/llb/module.make23
-rw-r--r--src/proof/pdr/module.make8
-rw-r--r--src/proof/pdr/pdr.c53
-rw-r--r--src/proof/pdr/pdr.h79
-rw-r--r--src/proof/pdr/pdrClass.c223
-rw-r--r--src/proof/pdr/pdrCnf.c357
-rw-r--r--src/proof/pdr/pdrCore.c722
-rw-r--r--src/proof/pdr/pdrInt.h198
-rw-r--r--src/proof/pdr/pdrInv.c374
-rw-r--r--src/proof/pdr/pdrMan.c194
-rw-r--r--src/proof/pdr/pdrSat.c373
-rw-r--r--src/proof/pdr/pdrTsim.c450
-rw-r--r--src/proof/pdr/pdrUtil.c719
-rw-r--r--src/proof/ssw/module.make20
-rw-r--r--src/proof/ssw/ssw.h142
-rw-r--r--src/proof/ssw/sswAig.c259
-rw-r--r--src/proof/ssw/sswBmc.c224
-rw-r--r--src/proof/ssw/sswClass.c1170
-rw-r--r--src/proof/ssw/sswCnf.c428
-rw-r--r--src/proof/ssw/sswConstr.c714
-rw-r--r--src/proof/ssw/sswCore.c522
-rw-r--r--src/proof/ssw/sswDyn.c489
-rw-r--r--src/proof/ssw/sswFilter.c493
-rw-r--r--src/proof/ssw/sswInt.h302
-rw-r--r--src/proof/ssw/sswIslands.c598
-rw-r--r--src/proof/ssw/sswLcorr.c336
-rw-r--r--src/proof/ssw/sswMan.c218
-rw-r--r--src/proof/ssw/sswPairs.c477
-rw-r--r--src/proof/ssw/sswPart.c141
-rw-r--r--src/proof/ssw/sswRarity.c1158
-rw-r--r--src/proof/ssw/sswRarity2.c517
-rw-r--r--src/proof/ssw/sswSat.c306
-rw-r--r--src/proof/ssw/sswSemi.c322
-rw-r--r--src/proof/ssw/sswSim.c1405
-rw-r--r--src/proof/ssw/sswSimSat.c123
-rw-r--r--src/proof/ssw/sswSweep.c435
-rw-r--r--src/proof/ssw/sswUnique.c197
156 files changed, 67230 insertions, 0 deletions
diff --git a/src/proof/bbr/bbr.h b/src/proof/bbr/bbr.h
new file mode 100644
index 00000000..71061759
--- /dev/null
+++ b/src/proof/bbr/bbr.h
@@ -0,0 +1,93 @@
+/**CFile****************************************************************
+
+ FileName [bbr.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD-based reachability analysis.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: bbr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__bbr__bbr_h
+#define ABC__aig__bbr__bbr_h
+
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "src/aig/aig/aig.h"
+#include "src/aig/saig/saig.h"
+#include "src/bdd/cudd/cuddInt.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static inline DdNode * Aig_ObjGlobalBdd( Aig_Obj_t * pObj ) { return (DdNode *)pObj->pData; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== bbrImage.c ==========================================================*/
+typedef struct Bbr_ImageTree_t_ Bbr_ImageTree_t;
+extern Bbr_ImageTree_t * Bbr_bddImageStart(
+ DdManager * dd, DdNode * bCare,
+ int nParts, DdNode ** pbParts,
+ int nVars, DdNode ** pbVars, int nBddMax, int fVerbose );
+extern DdNode * Bbr_bddImageCompute( Bbr_ImageTree_t * pTree, DdNode * bCare );
+extern void Bbr_bddImageTreeDelete( Bbr_ImageTree_t * pTree );
+extern DdNode * Bbr_bddImageRead( Bbr_ImageTree_t * pTree );
+typedef struct Bbr_ImageTree2_t_ Bbr_ImageTree2_t;
+extern Bbr_ImageTree2_t * Bbr_bddImageStart2(
+ DdManager * dd, DdNode * bCare,
+ int nParts, DdNode ** pbParts,
+ int nVars, DdNode ** pbVars, int fVerbose );
+extern DdNode * Bbr_bddImageCompute2( Bbr_ImageTree2_t * pTree, DdNode * bCare );
+extern void Bbr_bddImageTreeDelete2( Bbr_ImageTree2_t * pTree );
+extern DdNode * Bbr_bddImageRead2( Bbr_ImageTree2_t * pTree );
+/*=== bbrNtbdd.c ==========================================================*/
+extern void Aig_ManFreeGlobalBdds( Aig_Man_t * p, DdManager * dd );
+extern int Aig_ManSizeOfGlobalBdds( Aig_Man_t * p );
+extern DdManager * Aig_ManComputeGlobalBdds( Aig_Man_t * p, int nBddSizeMax, int fDropInternal, int fReorder, int fVerbose );
+/*=== bbrReach.c ==========================================================*/
+extern int Aig_ManVerifyUsingBdds( Aig_Man_t * p, Saig_ParBbr_t * pPars );
+extern void Bbr_ManSetDefaultParams( Saig_ParBbr_t * p );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/proof/bbr/bbrCex.c b/src/proof/bbr/bbrCex.c
new file mode 100644
index 00000000..7ee95e7c
--- /dev/null
+++ b/src/proof/bbr/bbrCex.c
@@ -0,0 +1,172 @@
+/**CFile****************************************************************
+
+ FileName [bbrCex.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD-based reachability analysis.]
+
+ Synopsis [Procedures to derive a satisfiable counter-example.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: bbrCex.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bbr.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern DdNode * Bbr_bddComputeRangeCube( DdManager * dd, int iStart, int iStop );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Derives the counter-example using the set of reached states.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Cex_t * Aig_ManVerifyUsingBddsCountExample( Aig_Man_t * p, DdManager * dd,
+ DdNode ** pbParts, Vec_Ptr_t * vOnionRings, DdNode * bCubeFirst,
+ int iOutput, int fVerbose, int fSilent )
+{
+ Abc_Cex_t * pCex;
+ Aig_Obj_t * pObj;
+ Bbr_ImageTree_t * pTree;
+ DdNode * bCubeNs, * bState, * bImage;
+ DdNode * bTemp, * bVar, * bRing;
+ int i, v, RetValue, nPiOffset;
+ char * pValues;
+ int clk = clock();
+//printf( "\nDeriving counter-example.\n" );
+
+ // allocate room for the counter-example
+ pCex = Abc_CexAlloc( Saig_ManRegNum(p), Saig_ManPiNum(p), Vec_PtrSize(vOnionRings)+1 );
+ pCex->iFrame = Vec_PtrSize(vOnionRings);
+ pCex->iPo = iOutput;
+ nPiOffset = Saig_ManRegNum(p) + Saig_ManPiNum(p) * Vec_PtrSize(vOnionRings);
+
+ // create the cube of NS variables
+ bCubeNs = Bbr_bddComputeRangeCube( dd, Saig_ManCiNum(p), Saig_ManCiNum(p)+Saig_ManRegNum(p) ); Cudd_Ref( bCubeNs );
+ pTree = Bbr_bddImageStart( dd, bCubeNs, Saig_ManRegNum(p), pbParts, Saig_ManCiNum(p), dd->vars, 100000000, fVerbose );
+ Cudd_RecursiveDeref( dd, bCubeNs );
+ if ( pTree == NULL )
+ {
+ if ( !fSilent )
+ printf( "BDDs blew up during qualitification scheduling. " );
+ return NULL;
+ }
+
+ // allocate room for the cube
+ pValues = ABC_ALLOC( char, dd->size );
+
+ // get the last cube
+ RetValue = Cudd_bddPickOneCube( dd, bCubeFirst, pValues );
+ assert( RetValue );
+
+ // write PIs of counter-example
+ Saig_ManForEachPi( p, pObj, i )
+ if ( pValues[i] == 1 )
+ Abc_InfoSetBit( pCex->pData, nPiOffset + i );
+ nPiOffset -= Saig_ManPiNum(p);
+
+ // write state in terms of NS variables
+ bState = (dd)->one; Cudd_Ref( bState );
+ Saig_ManForEachLo( p, pObj, i )
+ {
+ bVar = Cudd_NotCond( dd->vars[Saig_ManCiNum(p)+i], pValues[Saig_ManPiNum(p)+i] != 1 );
+ bState = Cudd_bddAnd( dd, bTemp = bState, bVar ); Cudd_Ref( bState );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+
+ // perform backward analysis
+ Vec_PtrForEachEntryReverse( DdNode *, vOnionRings, bRing, v )
+ {
+ // compute the next states
+ bImage = Bbr_bddImageCompute( pTree, bState );
+ if ( bImage == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bState );
+ if ( !fSilent )
+ printf( "BDDs blew up during image computation. " );
+ Bbr_bddImageTreeDelete( pTree );
+ ABC_FREE( pValues );
+ return NULL;
+ }
+ Cudd_Ref( bImage );
+ Cudd_RecursiveDeref( dd, bState );
+
+ // intersect with the previous set
+ bImage = Cudd_bddAnd( dd, bTemp = bImage, bRing ); Cudd_Ref( bImage );
+ Cudd_RecursiveDeref( dd, bTemp );
+
+ // find any assignment of the BDD
+ RetValue = Cudd_bddPickOneCube( dd, bImage, pValues );
+ assert( RetValue );
+ Cudd_RecursiveDeref( dd, bImage );
+
+ // write PIs of counter-example
+ Saig_ManForEachPi( p, pObj, i )
+ if ( pValues[i] == 1 )
+ Abc_InfoSetBit( pCex->pData, nPiOffset + i );
+ nPiOffset -= Saig_ManPiNum(p);
+
+ // check that we get the init state
+ if ( v == 0 )
+ {
+ Saig_ManForEachLo( p, pObj, i )
+ assert( pValues[Saig_ManPiNum(p)+i] == 0 );
+ break;
+ }
+
+ // write state in terms of NS variables
+ bState = (dd)->one; Cudd_Ref( bState );
+ Saig_ManForEachLo( p, pObj, i )
+ {
+ bVar = Cudd_NotCond( dd->vars[Saig_ManCiNum(p)+i], pValues[Saig_ManPiNum(p)+i] != 1 );
+ bState = Cudd_bddAnd( dd, bTemp = bState, bVar ); Cudd_Ref( bState );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ }
+ // cleanup
+ Bbr_bddImageTreeDelete( pTree );
+ ABC_FREE( pValues );
+ // verify the counter example
+ if ( Vec_PtrSize(vOnionRings) < 1000 )
+ {
+ RetValue = Saig_ManVerifyCex( p, pCex );
+ if ( RetValue == 0 && !fSilent )
+ printf( "Aig_ManVerifyUsingBdds(): Counter-example verification has FAILED.\n" );
+ }
+ if ( fVerbose && !fSilent )
+ {
+ ABC_PRT( "Counter-example generation time", clock() - clk );
+ }
+ return pCex;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/bbr/bbrImage.c b/src/proof/bbr/bbrImage.c
new file mode 100644
index 00000000..23b43169
--- /dev/null
+++ b/src/proof/bbr/bbrImage.c
@@ -0,0 +1,1327 @@
+/**CFile****************************************************************
+
+ FileName [bbrImage.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD-based reachability analysis.]
+
+ Synopsis [Performs image computation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: bbrImage.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bbr.h"
+#include "src/bdd/mtr/mtr.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+ The ideas implemented in this file are inspired by the paper:
+ Pankaj Chauhan, Edmund Clarke, Somesh Jha, Jim Kukula, Tom Shiple,
+ Helmut Veith, Dong Wang. Non-linear Quantification Scheduling in
+ Image Computation. ICCAD, 2001.
+*/
+
+/*---------------------------------------------------------------------------*/
+/* Constant declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Stucture declarations */
+/*---------------------------------------------------------------------------*/
+
+typedef struct Bbr_ImageNode_t_ Bbr_ImageNode_t;
+typedef struct Bbr_ImagePart_t_ Bbr_ImagePart_t;
+typedef struct Bbr_ImageVar_t_ Bbr_ImageVar_t;
+
+struct Bbr_ImageTree_t_
+{
+ Bbr_ImageNode_t * pRoot; // the root of quantification tree
+ Bbr_ImageNode_t * pCare; // the leaf node with the care set
+ DdNode * bCareSupp; // the cube to quantify from the care
+ int fVerbose; // the verbosity flag
+ int nNodesMax; // the max number of nodes in one iter
+ int nNodesMaxT; // the overall max number of nodes
+ int nIter; // the number of iterations with this tree
+ int nBddMax; // the number of node to stop
+};
+
+struct Bbr_ImageNode_t_
+{
+ DdManager * dd; // the manager
+ DdNode * bCube; // the cube to quantify
+ DdNode * bImage; // the partial image
+ Bbr_ImageNode_t * pNode1; // the first branch
+ Bbr_ImageNode_t * pNode2; // the second branch
+ Bbr_ImagePart_t * pPart; // the partition (temporary)
+};
+
+struct Bbr_ImagePart_t_
+{
+ DdNode * bFunc; // the partition
+ DdNode * bSupp; // the support of this partition
+ int nNodes; // the number of BDD nodes
+ short nSupp; // the number of support variables
+ short iPart; // the number of this partition
+};
+
+struct Bbr_ImageVar_t_
+{
+ int iNum; // the BDD index of this variable
+ DdNode * bParts; // the partition numbers
+ int nParts; // the number of partitions
+};
+
+/*---------------------------------------------------------------------------*/
+/* Type declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Variable declarations */
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* Macro declarations */
+/*---------------------------------------------------------------------------*/
+
+#define b0 Cudd_Not((dd)->one)
+#define b1 (dd)->one
+
+#ifndef ABC_PRB
+#define ABC_PRB(dd,f) printf("%s = ", #f); Bbr_bddPrint(dd,f); printf("\n")
+#endif
+
+/**AutomaticStart*************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Static function prototypes */
+/*---------------------------------------------------------------------------*/
+
+static Bbr_ImagePart_t ** Bbr_CreateParts( DdManager * dd,
+ int nParts, DdNode ** pbParts, DdNode * bCare );
+static Bbr_ImageVar_t ** Bbr_CreateVars( DdManager * dd,
+ int nParts, Bbr_ImagePart_t ** pParts,
+ int nVars, DdNode ** pbVarsNs );
+static Bbr_ImageNode_t ** Bbr_CreateNodes( DdManager * dd,
+ int nParts, Bbr_ImagePart_t ** pParts,
+ int nVars, Bbr_ImageVar_t ** pVars );
+static void Bbr_DeleteParts_rec( Bbr_ImageNode_t * pNode );
+static int Bbr_BuildTreeNode( DdManager * dd,
+ int nNodes, Bbr_ImageNode_t ** pNodes,
+ int nVars, Bbr_ImageVar_t ** pVars, int * pfStop, int nBddMax );
+static Bbr_ImageNode_t * Bbr_MergeTopNodes( DdManager * dd,
+ int nNodes, Bbr_ImageNode_t ** pNodes );
+static void Bbr_bddImageTreeDelete_rec( Bbr_ImageNode_t * pNode );
+static int Bbr_bddImageCompute_rec( Bbr_ImageTree_t * pTree, Bbr_ImageNode_t * pNode );
+static int Bbr_FindBestVariable( DdManager * dd,
+ int nNodes, Bbr_ImageNode_t ** pNodes,
+ int nVars, Bbr_ImageVar_t ** pVars );
+static void Bbr_FindBestPartitions( DdManager * dd, DdNode * bParts,
+ int nNodes, Bbr_ImageNode_t ** pNodes,
+ int * piNode1, int * piNode2 );
+static Bbr_ImageNode_t * Bbr_CombineTwoNodes( DdManager * dd, DdNode * bCube,
+ Bbr_ImageNode_t * pNode1, Bbr_ImageNode_t * pNode2 );
+
+static void Bbr_bddImagePrintLatchDependency( DdManager * dd, DdNode * bCare,
+ int nParts, DdNode ** pbParts,
+ int nVars, DdNode ** pbVars );
+static void Bbr_bddImagePrintLatchDependencyOne( DdManager * dd, DdNode * bFunc,
+ DdNode * bVarsCs, DdNode * bVarsNs, int iPart );
+
+static void Bbr_bddImagePrintTree( Bbr_ImageTree_t * pTree );
+static void Bbr_bddImagePrintTree_rec( Bbr_ImageNode_t * pNode, int nOffset );
+
+static void Bbr_bddPrint( DdManager * dd, DdNode * F );
+
+/**AutomaticEnd***************************************************************/
+
+
+/*---------------------------------------------------------------------------*/
+/* Definition of exported functions */
+/*---------------------------------------------------------------------------*/
+
+/**Function*************************************************************
+
+ Synopsis [Starts the image computation using tree-based scheduling.]
+
+ Description [This procedure starts the image computation. It uses
+ the given care set to test-run the image computation and creates the
+ quantification tree by scheduling variable quantifications. The tree can
+ be used to compute images for other care sets without rescheduling.
+ In this case, Bbr_bddImageCompute() should be called.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Bbr_ImageTree_t * Bbr_bddImageStart(
+ DdManager * dd, DdNode * bCare, // the care set
+ int nParts, DdNode ** pbParts, // the partitions for image computation
+ int nVars, DdNode ** pbVars, int nBddMax, int fVerbose ) // the NS and parameter variables (not quantified!)
+{
+ Bbr_ImageTree_t * pTree;
+ Bbr_ImagePart_t ** pParts;
+ Bbr_ImageVar_t ** pVars;
+ Bbr_ImageNode_t ** pNodes, * pCare;
+ int fStop, v;
+
+ if ( fVerbose && dd->size <= 80 )
+ Bbr_bddImagePrintLatchDependency( dd, bCare, nParts, pbParts, nVars, pbVars );
+
+ // create variables, partitions and leaf nodes
+ pParts = Bbr_CreateParts( dd, nParts, pbParts, bCare );
+ pVars = Bbr_CreateVars( dd, nParts + 1, pParts, nVars, pbVars );
+ pNodes = Bbr_CreateNodes( dd, nParts + 1, pParts, dd->size, pVars );
+ pCare = pNodes[nParts];
+
+ // process the nodes
+ while ( Bbr_BuildTreeNode( dd, nParts + 1, pNodes, dd->size, pVars, &fStop, nBddMax ) );
+
+ // consider the case of BDD node blowup
+ if ( fStop )
+ {
+ for ( v = 0; v < dd->size; v++ )
+ if ( pVars[v] )
+ ABC_FREE( pVars[v] );
+ ABC_FREE( pVars );
+ for ( v = 0; v <= nParts; v++ )
+ if ( pNodes[v] )
+ {
+ Bbr_DeleteParts_rec( pNodes[v] );
+ Bbr_bddImageTreeDelete_rec( pNodes[v] );
+ }
+ ABC_FREE( pNodes );
+ ABC_FREE( pParts );
+ return NULL;
+ }
+
+ // make sure the variables are gone
+ for ( v = 0; v < dd->size; v++ )
+ assert( pVars[v] == NULL );
+ ABC_FREE( pVars );
+
+ // create the tree
+ pTree = ABC_ALLOC( Bbr_ImageTree_t, 1 );
+ memset( pTree, 0, sizeof(Bbr_ImageTree_t) );
+ pTree->pCare = pCare;
+ pTree->nBddMax = nBddMax;
+ pTree->fVerbose = fVerbose;
+
+ // merge the topmost nodes
+ while ( (pTree->pRoot = Bbr_MergeTopNodes( dd, nParts + 1, pNodes )) == NULL );
+
+ // make sure the nodes are gone
+ for ( v = 0; v < nParts + 1; v++ )
+ assert( pNodes[v] == NULL );
+ ABC_FREE( pNodes );
+
+// if ( fVerbose )
+// Bbr_bddImagePrintTree( pTree );
+
+ // set the support of the care set
+ pTree->bCareSupp = Cudd_Support( dd, bCare ); Cudd_Ref( pTree->bCareSupp );
+
+ // clean the partitions
+ Bbr_DeleteParts_rec( pTree->pRoot );
+ ABC_FREE( pParts );
+
+ return pTree;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute the image.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Bbr_bddImageCompute( Bbr_ImageTree_t * pTree, DdNode * bCare )
+{
+ DdManager * dd = pTree->pCare->dd;
+ DdNode * bSupp, * bRem;
+
+ pTree->nIter++;
+
+ // make sure the supports are okay
+ bSupp = Cudd_Support( dd, bCare ); Cudd_Ref( bSupp );
+ if ( bSupp != pTree->bCareSupp )
+ {
+ bRem = Cudd_bddExistAbstract( dd, bSupp, pTree->bCareSupp ); Cudd_Ref( bRem );
+ if ( bRem != b1 )
+ {
+printf( "Original care set support: " );
+ABC_PRB( dd, pTree->bCareSupp );
+printf( "Current care set support: " );
+ABC_PRB( dd, bSupp );
+ Cudd_RecursiveDeref( dd, bSupp );
+ Cudd_RecursiveDeref( dd, bRem );
+ printf( "The care set depends on some vars that were not in the care set during scheduling.\n" );
+ return NULL;
+ }
+ Cudd_RecursiveDeref( dd, bRem );
+ }
+ Cudd_RecursiveDeref( dd, bSupp );
+
+ // remove the previous image
+ Cudd_RecursiveDeref( dd, pTree->pCare->bImage );
+ pTree->pCare->bImage = bCare; Cudd_Ref( bCare );
+
+ // compute the image
+ pTree->nNodesMax = 0;
+ if ( !Bbr_bddImageCompute_rec( pTree, pTree->pRoot ) )
+ return NULL;
+ if ( pTree->nNodesMaxT < pTree->nNodesMax )
+ pTree->nNodesMaxT = pTree->nNodesMax;
+
+// if ( pTree->fVerbose )
+// printf( "Iter %2d : Max nodes = %5d.\n", pTree->nIter, pTree->nNodesMax );
+ return pTree->pRoot->bImage;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Delete the tree.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Bbr_bddImageTreeDelete( Bbr_ImageTree_t * pTree )
+{
+ if ( pTree->bCareSupp )
+ Cudd_RecursiveDeref( pTree->pRoot->dd, pTree->bCareSupp );
+ Bbr_bddImageTreeDelete_rec( pTree->pRoot );
+ ABC_FREE( pTree );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reads the image from the tree.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Bbr_bddImageRead( Bbr_ImageTree_t * pTree )
+{
+ return pTree->pRoot->bImage;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of internal functions */
+/*---------------------------------------------------------------------------*/
+
+/**Function********************************************************************
+
+ Synopsis [Outputs the BDD in a readable format.]
+
+ Description []
+
+ SideEffects [None]
+
+ SeeAlso []
+
+******************************************************************************/
+void Bbr_bddPrint( DdManager * dd, DdNode * F )
+{
+ DdGen * Gen;
+ int * Cube;
+ CUDD_VALUE_TYPE Value;
+ int nVars = dd->size;
+ int fFirstCube = 1;
+ int i;
+
+ if ( F == NULL )
+ {
+ printf("NULL");
+ return;
+ }
+ if ( F == b0 )
+ {
+ printf("Constant 0");
+ return;
+ }
+ if ( F == b1 )
+ {
+ printf("Constant 1");
+ return;
+ }
+
+ Cudd_ForeachCube( dd, F, Gen, Cube, Value )
+ {
+ if ( fFirstCube )
+ fFirstCube = 0;
+ else
+// Output << " + ";
+ printf( " + " );
+
+ for ( i = 0; i < nVars; i++ )
+ if ( Cube[i] == 0 )
+ printf( "[%d]'", i );
+// printf( "%c'", (char)('a'+i) );
+ else if ( Cube[i] == 1 )
+ printf( "[%d]", i );
+// printf( "%c", (char)('a'+i) );
+ }
+
+// printf("\n");
+}
+
+/*---------------------------------------------------------------------------*/
+/* Definition of static Functions */
+/*---------------------------------------------------------------------------*/
+
+/**Function*************************************************************
+
+ Synopsis [Creates partitions.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Bbr_ImagePart_t ** Bbr_CreateParts( DdManager * dd,
+ int nParts, DdNode ** pbParts, DdNode * bCare )
+{
+ Bbr_ImagePart_t ** pParts;
+ int i;
+
+ // start the partitions
+ pParts = ABC_ALLOC( Bbr_ImagePart_t *, nParts + 1 );
+ // create structures for each variable
+ for ( i = 0; i < nParts; i++ )
+ {
+ pParts[i] = ABC_ALLOC( Bbr_ImagePart_t, 1 );
+ pParts[i]->bFunc = pbParts[i]; Cudd_Ref( pParts[i]->bFunc );
+ pParts[i]->bSupp = Cudd_Support( dd, pParts[i]->bFunc ); Cudd_Ref( pParts[i]->bSupp );
+ pParts[i]->nSupp = Cudd_SupportSize( dd, pParts[i]->bSupp );
+ pParts[i]->nNodes = Cudd_DagSize( pParts[i]->bFunc );
+ pParts[i]->iPart = i;
+ }
+ // add the care set as the last partition
+ pParts[nParts] = ABC_ALLOC( Bbr_ImagePart_t, 1 );
+ pParts[nParts]->bFunc = bCare; Cudd_Ref( pParts[nParts]->bFunc );
+ pParts[nParts]->bSupp = Cudd_Support( dd, pParts[nParts]->bFunc ); Cudd_Ref( pParts[nParts]->bSupp );
+ pParts[nParts]->nSupp = Cudd_SupportSize( dd, pParts[nParts]->bSupp );
+ pParts[nParts]->nNodes = Cudd_DagSize( pParts[nParts]->bFunc );
+ pParts[nParts]->iPart = nParts;
+ return pParts;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Bbr_ImageVar_t ** Bbr_CreateVars( DdManager * dd,
+ int nParts, Bbr_ImagePart_t ** pParts,
+ int nVars, DdNode ** pbVars )
+{
+ Bbr_ImageVar_t ** pVars;
+ DdNode ** pbFuncs;
+ DdNode * bCubeNs, * bSupp, * bParts, * bTemp, * bSuppTemp;
+ int nVarsTotal, iVar, p, Counter;
+
+ // put all the functions into one array
+ pbFuncs = ABC_ALLOC( DdNode *, nParts );
+ for ( p = 0; p < nParts; p++ )
+ pbFuncs[p] = pParts[p]->bSupp;
+ bSupp = Cudd_VectorSupport( dd, pbFuncs, nParts ); Cudd_Ref( bSupp );
+ ABC_FREE( pbFuncs );
+
+ // remove the NS vars
+ bCubeNs = Cudd_bddComputeCube( dd, pbVars, NULL, nVars ); Cudd_Ref( bCubeNs );
+ bSupp = Cudd_bddExistAbstract( dd, bTemp = bSupp, bCubeNs ); Cudd_Ref( bSupp );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bCubeNs );
+
+ // get the number of I and CS variables to be quantified
+ nVarsTotal = Cudd_SupportSize( dd, bSupp );
+
+ // start the variables
+ pVars = ABC_ALLOC( Bbr_ImageVar_t *, dd->size );
+ memset( pVars, 0, sizeof(Bbr_ImageVar_t *) * dd->size );
+ // create structures for each variable
+ for ( bSuppTemp = bSupp; bSuppTemp != b1; bSuppTemp = cuddT(bSuppTemp) )
+ {
+ iVar = bSuppTemp->index;
+ pVars[iVar] = ABC_ALLOC( Bbr_ImageVar_t, 1 );
+ pVars[iVar]->iNum = iVar;
+ // collect all the parts this var belongs to
+ Counter = 0;
+ bParts = b1; Cudd_Ref( bParts );
+ for ( p = 0; p < nParts; p++ )
+ if ( Cudd_bddLeq( dd, pParts[p]->bSupp, dd->vars[bSuppTemp->index] ) )
+ {
+ bParts = Cudd_bddAnd( dd, bTemp = bParts, dd->vars[p] ); Cudd_Ref( bParts );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Counter++;
+ }
+ pVars[iVar]->bParts = bParts; // takes ref
+ pVars[iVar]->nParts = Counter;
+ }
+ Cudd_RecursiveDeref( dd, bSupp );
+ return pVars;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Bbr_ImageNode_t ** Bbr_CreateNodes( DdManager * dd,
+ int nParts, Bbr_ImagePart_t ** pParts,
+ int nVars, Bbr_ImageVar_t ** pVars )
+{
+ Bbr_ImageNode_t ** pNodes;
+ Bbr_ImageNode_t * pNode;
+ DdNode * bTemp;
+ int i, v, iPart;
+/*
+ DdManager * dd; // the manager
+ DdNode * bCube; // the cube to quantify
+ DdNode * bImage; // the partial image
+ Bbr_ImageNode_t * pNode1; // the first branch
+ Bbr_ImageNode_t * pNode2; // the second branch
+ Bbr_ImagePart_t * pPart; // the partition (temporary)
+*/
+ // start the partitions
+ pNodes = ABC_ALLOC( Bbr_ImageNode_t *, nParts );
+ // create structures for each leaf nodes
+ for ( i = 0; i < nParts; i++ )
+ {
+ pNodes[i] = ABC_ALLOC( Bbr_ImageNode_t, 1 );
+ memset( pNodes[i], 0, sizeof(Bbr_ImageNode_t) );
+ pNodes[i]->dd = dd;
+ pNodes[i]->pPart = pParts[i];
+ }
+ // find the quantification cubes for each leaf node
+ for ( v = 0; v < nVars; v++ )
+ {
+ if ( pVars[v] == NULL )
+ continue;
+ assert( pVars[v]->nParts > 0 );
+ if ( pVars[v]->nParts > 1 )
+ continue;
+ iPart = pVars[v]->bParts->index;
+ if ( pNodes[iPart]->bCube == NULL )
+ {
+ pNodes[iPart]->bCube = dd->vars[v];
+ Cudd_Ref( dd->vars[v] );
+ }
+ else
+ {
+ pNodes[iPart]->bCube = Cudd_bddAnd( dd, bTemp = pNodes[iPart]->bCube, dd->vars[v] );
+ Cudd_Ref( pNodes[iPart]->bCube );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ // remove these variables
+ Cudd_RecursiveDeref( dd, pVars[v]->bParts );
+ ABC_FREE( pVars[v] );
+ }
+
+ // assign the leaf node images
+ for ( i = 0; i < nParts; i++ )
+ {
+ pNode = pNodes[i];
+ if ( pNode->bCube )
+ {
+ // update the partition
+ pParts[i]->bFunc = Cudd_bddExistAbstract( dd, bTemp = pParts[i]->bFunc, pNode->bCube );
+ Cudd_Ref( pParts[i]->bFunc );
+ Cudd_RecursiveDeref( dd, bTemp );
+ // update the support the partition
+ pParts[i]->bSupp = Cudd_bddExistAbstract( dd, bTemp = pParts[i]->bSupp, pNode->bCube );
+ Cudd_Ref( pParts[i]->bSupp );
+ Cudd_RecursiveDeref( dd, bTemp );
+ // update the numbers
+ pParts[i]->nSupp = Cudd_SupportSize( dd, pParts[i]->bSupp );
+ pParts[i]->nNodes = Cudd_DagSize( pParts[i]->bFunc );
+ // get rid of the cube
+ // save the last (care set) quantification cube
+ if ( i < nParts - 1 )
+ {
+ Cudd_RecursiveDeref( dd, pNode->bCube );
+ pNode->bCube = NULL;
+ }
+ }
+ // copy the function
+ pNode->bImage = pParts[i]->bFunc; Cudd_Ref( pNode->bImage );
+ }
+/*
+ for ( i = 0; i < nParts; i++ )
+ {
+ pNode = pNodes[i];
+ABC_PRB( dd, pNode->bCube );
+ABC_PRB( dd, pNode->pPart->bFunc );
+ABC_PRB( dd, pNode->pPart->bSupp );
+printf( "\n" );
+ }
+*/
+ return pNodes;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Delete the partitions from the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Bbr_DeleteParts_rec( Bbr_ImageNode_t * pNode )
+{
+ Bbr_ImagePart_t * pPart;
+ if ( pNode->pNode1 )
+ Bbr_DeleteParts_rec( pNode->pNode1 );
+ if ( pNode->pNode2 )
+ Bbr_DeleteParts_rec( pNode->pNode2 );
+ pPart = pNode->pPart;
+ Cudd_RecursiveDeref( pNode->dd, pPart->bFunc );
+ Cudd_RecursiveDeref( pNode->dd, pPart->bSupp );
+ ABC_FREE( pNode->pPart );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Delete the partitions from the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Bbr_bddImageTreeDelete_rec( Bbr_ImageNode_t * pNode )
+{
+ if ( pNode->pNode1 )
+ Bbr_bddImageTreeDelete_rec( pNode->pNode1 );
+ if ( pNode->pNode2 )
+ Bbr_bddImageTreeDelete_rec( pNode->pNode2 );
+ if ( pNode->bCube )
+ Cudd_RecursiveDeref( pNode->dd, pNode->bCube );
+ if ( pNode->bImage )
+ Cudd_RecursiveDeref( pNode->dd, pNode->bImage );
+ assert( pNode->pPart == NULL );
+ ABC_FREE( pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recompute the image.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Bbr_bddImageCompute_rec( Bbr_ImageTree_t * pTree, Bbr_ImageNode_t * pNode )
+{
+ DdManager * dd = pNode->dd;
+ DdNode * bTemp;
+ int nNodes;
+
+ // trivial case
+ if ( pNode->pNode1 == NULL )
+ {
+ if ( pNode->bCube )
+ {
+ pNode->bImage = Cudd_bddExistAbstract( dd, bTemp = pNode->bImage, pNode->bCube );
+ Cudd_Ref( pNode->bImage );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ return 1;
+ }
+
+ // compute the children
+ if ( pNode->pNode1 )
+ if ( !Bbr_bddImageCompute_rec( pTree, pNode->pNode1 ) )
+ return 0;
+ if ( pNode->pNode2 )
+ if ( !Bbr_bddImageCompute_rec( pTree, pNode->pNode2 ) )
+ return 0;
+
+ // clean the old image
+ if ( pNode->bImage )
+ Cudd_RecursiveDeref( dd, pNode->bImage );
+ pNode->bImage = NULL;
+
+ // compute the new image
+ if ( pNode->bCube )
+ pNode->bImage = Cudd_bddAndAbstract( dd,
+ pNode->pNode1->bImage, pNode->pNode2->bImage, pNode->bCube );
+ else
+ pNode->bImage = Cudd_bddAnd( dd, pNode->pNode1->bImage, pNode->pNode2->bImage );
+ Cudd_Ref( pNode->bImage );
+
+ if ( pTree->fVerbose )
+ {
+ nNodes = Cudd_DagSize( pNode->bImage );
+ if ( pTree->nNodesMax < nNodes )
+ pTree->nNodesMax = nNodes;
+ }
+ if ( dd->keys-dd->dead > (unsigned)pTree->nBddMax )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Builds the tree.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Bbr_BuildTreeNode( DdManager * dd,
+ int nNodes, Bbr_ImageNode_t ** pNodes,
+ int nVars, Bbr_ImageVar_t ** pVars, int * pfStop, int nBddMax )
+{
+ Bbr_ImageNode_t * pNode1, * pNode2;
+ Bbr_ImageVar_t * pVar;
+ Bbr_ImageNode_t * pNode;
+ DdNode * bCube, * bTemp, * bSuppTemp;//, * bParts;
+ int iNode1, iNode2;
+ int iVarBest, nSupp, v;
+
+ // find the best variable
+ iVarBest = Bbr_FindBestVariable( dd, nNodes, pNodes, nVars, pVars );
+ if ( iVarBest == -1 )
+ return 0;
+/*
+for ( v = 0; v < nVars; v++ )
+{
+ DdNode * bSupp;
+ if ( pVars[v] == NULL )
+ continue;
+ printf( "%3d :", v );
+ printf( "%3d ", pVars[v]->nParts );
+ bSupp = Cudd_Support( dd, pVars[v]->bParts ); Cudd_Ref( bSupp );
+ Bbr_bddPrint( dd, bSupp ); printf( "\n" );
+ Cudd_RecursiveDeref( dd, bSupp );
+}
+*/
+ pVar = pVars[iVarBest];
+
+ // this var cannot appear in one partition only
+ nSupp = Cudd_SupportSize( dd, pVar->bParts );
+ assert( nSupp == pVar->nParts );
+ assert( nSupp != 1 );
+//printf( "var = %d supp = %d\n\n", iVarBest, nSupp );
+
+ // if it appears in only two partitions, quantify it
+ if ( pVar->nParts == 2 )
+ {
+ // get the nodes
+ iNode1 = pVar->bParts->index;
+ iNode2 = cuddT(pVar->bParts)->index;
+ pNode1 = pNodes[iNode1];
+ pNode2 = pNodes[iNode2];
+
+ // get the quantification cube
+ bCube = dd->vars[pVar->iNum]; Cudd_Ref( bCube );
+ // add the variables that appear only in these partitions
+ for ( v = 0; v < nVars; v++ )
+ if ( pVars[v] && v != iVarBest && pVars[v]->bParts == pVars[iVarBest]->bParts )
+ {
+ // add this var
+ bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[pVars[v]->iNum] ); Cudd_Ref( bCube );
+ Cudd_RecursiveDeref( dd, bTemp );
+ // clean this var
+ Cudd_RecursiveDeref( dd, pVars[v]->bParts );
+ ABC_FREE( pVars[v] );
+ }
+ // clean the best var
+ Cudd_RecursiveDeref( dd, pVars[iVarBest]->bParts );
+ ABC_FREE( pVars[iVarBest] );
+
+ // combines two nodes
+ pNode = Bbr_CombineTwoNodes( dd, bCube, pNode1, pNode2 );
+ Cudd_RecursiveDeref( dd, bCube );
+ }
+ else // if ( pVar->nParts > 2 )
+ {
+ // find two smallest BDDs that have this var
+ Bbr_FindBestPartitions( dd, pVar->bParts, nNodes, pNodes, &iNode1, &iNode2 );
+ pNode1 = pNodes[iNode1];
+ pNode2 = pNodes[iNode2];
+//printf( "smallest bdds with this var: %d %d\n", iNode1, iNode2 );
+/*
+ // it is not possible that a var appears only in these two
+ // otherwise, it would have a different cost
+ bParts = Cudd_bddAnd( dd, dd->vars[iNode1], dd->vars[iNode2] ); Cudd_Ref( bParts );
+ for ( v = 0; v < nVars; v++ )
+ if ( pVars[v] && pVars[v]->bParts == bParts )
+ assert( 0 );
+ Cudd_RecursiveDeref( dd, bParts );
+*/
+ // combines two nodes
+ pNode = Bbr_CombineTwoNodes( dd, b1, pNode1, pNode2 );
+ }
+
+ // clean the old nodes
+ pNodes[iNode1] = pNode;
+ pNodes[iNode2] = NULL;
+//printf( "Removing node %d (leaving node %d)\n", iNode2, iNode1 );
+
+ // update the variables that appear in pNode[iNode2]
+ for ( bSuppTemp = pNode2->pPart->bSupp; bSuppTemp != b1; bSuppTemp = cuddT(bSuppTemp) )
+ {
+ pVar = pVars[bSuppTemp->index];
+ if ( pVar == NULL ) // this variable is not be quantified
+ continue;
+ // quantify this var
+ assert( Cudd_bddLeq( dd, pVar->bParts, dd->vars[iNode2] ) );
+ pVar->bParts = Cudd_bddExistAbstract( dd, bTemp = pVar->bParts, dd->vars[iNode2] ); Cudd_Ref( pVar->bParts );
+ Cudd_RecursiveDeref( dd, bTemp );
+ // add the new var
+ pVar->bParts = Cudd_bddAnd( dd, bTemp = pVar->bParts, dd->vars[iNode1] ); Cudd_Ref( pVar->bParts );
+ Cudd_RecursiveDeref( dd, bTemp );
+ // update the score
+ pVar->nParts = Cudd_SupportSize( dd, pVar->bParts );
+ }
+
+ *pfStop = 0;
+ if ( dd->keys-dd->dead > (unsigned)nBddMax )
+ {
+ *pfStop = 1;
+ return 0;
+ }
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Merges the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Bbr_ImageNode_t * Bbr_MergeTopNodes(
+ DdManager * dd, int nNodes, Bbr_ImageNode_t ** pNodes )
+{
+ Bbr_ImageNode_t * pNode;
+ int n1 = -1, n2 = -1, n;
+
+ // find the first and the second non-empty spots
+ for ( n = 0; n < nNodes; n++ )
+ if ( pNodes[n] )
+ {
+ if ( n1 == -1 )
+ n1 = n;
+ else if ( n2 == -1 )
+ {
+ n2 = n;
+ break;
+ }
+ }
+ assert( n1 != -1 );
+ // check the situation when only one such node is detected
+ if ( n2 == -1 )
+ {
+ // save the node
+ pNode = pNodes[n1];
+ // clean the node
+ pNodes[n1] = NULL;
+ return pNode;
+ }
+
+ // combines two nodes
+ pNode = Bbr_CombineTwoNodes( dd, b1, pNodes[n1], pNodes[n2] );
+
+ // clean the old nodes
+ pNodes[n1] = pNode;
+ pNodes[n2] = NULL;
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Merges two nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Bbr_ImageNode_t * Bbr_CombineTwoNodes( DdManager * dd, DdNode * bCube,
+ Bbr_ImageNode_t * pNode1, Bbr_ImageNode_t * pNode2 )
+{
+ Bbr_ImageNode_t * pNode;
+ Bbr_ImagePart_t * pPart;
+
+ // create a new partition
+ pPart = ABC_ALLOC( Bbr_ImagePart_t, 1 );
+ memset( pPart, 0, sizeof(Bbr_ImagePart_t) );
+ // create the function
+ pPart->bFunc = Cudd_bddAndAbstract( dd, pNode1->pPart->bFunc, pNode2->pPart->bFunc, bCube );
+ Cudd_Ref( pPart->bFunc );
+ // update the support the partition
+ pPart->bSupp = Cudd_bddAndAbstract( dd, pNode1->pPart->bSupp, pNode2->pPart->bSupp, bCube );
+ Cudd_Ref( pPart->bSupp );
+ // update the numbers
+ pPart->nSupp = Cudd_SupportSize( dd, pPart->bSupp );
+ pPart->nNodes = Cudd_DagSize( pPart->bFunc );
+ pPart->iPart = -1;
+/*
+ABC_PRB( dd, pNode1->pPart->bSupp );
+ABC_PRB( dd, pNode2->pPart->bSupp );
+ABC_PRB( dd, pPart->bSupp );
+*/
+ // create a new node
+ pNode = ABC_ALLOC( Bbr_ImageNode_t, 1 );
+ memset( pNode, 0, sizeof(Bbr_ImageNode_t) );
+ pNode->dd = dd;
+ pNode->pPart = pPart;
+ pNode->pNode1 = pNode1;
+ pNode->pNode2 = pNode2;
+ // compute the image
+ pNode->bImage = Cudd_bddAndAbstract( dd, pNode1->bImage, pNode2->bImage, bCube );
+ Cudd_Ref( pNode->bImage );
+ // save the cube
+ if ( bCube != b1 )
+ {
+ pNode->bCube = bCube; Cudd_Ref( bCube );
+ }
+ return pNode;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the best variable.]
+
+ Description [The variables is the best if the sum of squares of the
+ BDD sizes of the partitions, in which it participates, is the minimum.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Bbr_FindBestVariable( DdManager * dd,
+ int nNodes, Bbr_ImageNode_t ** pNodes,
+ int nVars, Bbr_ImageVar_t ** pVars )
+{
+ DdNode * bTemp;
+ int iVarBest, v;
+ double CostBest, CostCur;
+
+ CostBest = 100000000000000.0;
+ iVarBest = -1;
+
+ // check if there are two-variable partitions
+ for ( v = 0; v < nVars; v++ )
+ if ( pVars[v] && pVars[v]->nParts == 2 )
+ {
+ CostCur = 0;
+ for ( bTemp = pVars[v]->bParts; bTemp != b1; bTemp = cuddT(bTemp) )
+ CostCur += pNodes[bTemp->index]->pPart->nNodes *
+ pNodes[bTemp->index]->pPart->nNodes;
+ if ( CostBest > CostCur )
+ {
+ CostBest = CostCur;
+ iVarBest = v;
+ }
+ }
+ if ( iVarBest >= 0 )
+ return iVarBest;
+
+ // find other partition
+ for ( v = 0; v < nVars; v++ )
+ if ( pVars[v] )
+ {
+ assert( pVars[v]->nParts > 1 );
+ CostCur = 0;
+ for ( bTemp = pVars[v]->bParts; bTemp != b1; bTemp = cuddT(bTemp) )
+ CostCur += pNodes[bTemp->index]->pPart->nNodes *
+ pNodes[bTemp->index]->pPart->nNodes;
+ if ( CostBest > CostCur )
+ {
+ CostBest = CostCur;
+ iVarBest = v;
+ }
+ }
+ return iVarBest;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes two smallest partions that have this var.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Bbr_FindBestPartitions( DdManager * dd, DdNode * bParts,
+ int nNodes, Bbr_ImageNode_t ** pNodes,
+ int * piNode1, int * piNode2 )
+{
+ DdNode * bTemp;
+ int iPart1, iPart2;
+ int CostMin1, CostMin2, Cost;
+
+ // go through the partitions
+ iPart1 = iPart2 = -1;
+ CostMin1 = CostMin2 = 1000000;
+ for ( bTemp = bParts; bTemp != b1; bTemp = cuddT(bTemp) )
+ {
+ Cost = pNodes[bTemp->index]->pPart->nNodes;
+ if ( CostMin1 > Cost )
+ {
+ CostMin2 = CostMin1; iPart2 = iPart1;
+ CostMin1 = Cost; iPart1 = bTemp->index;
+ }
+ else if ( CostMin2 > Cost )
+ {
+ CostMin2 = Cost; iPart2 = bTemp->index;
+ }
+ }
+
+ *piNode1 = iPart1;
+ *piNode2 = iPart2;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the latch dependency matrix.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Bbr_bddImagePrintLatchDependency(
+ DdManager * dd, DdNode * bCare, // the care set
+ int nParts, DdNode ** pbParts, // the partitions for image computation
+ int nVars, DdNode ** pbVars ) // the NS and parameter variables (not quantified!)
+{
+ int i;
+ DdNode * bVarsCs, * bVarsNs;
+
+ bVarsCs = Cudd_Support( dd, bCare ); Cudd_Ref( bVarsCs );
+ bVarsNs = Cudd_bddComputeCube( dd, pbVars, NULL, nVars ); Cudd_Ref( bVarsNs );
+
+ printf( "The latch dependency matrix:\n" );
+ printf( "Partitions = %d Variables: total = %d non-quantifiable = %d\n",
+ nParts, dd->size, nVars );
+ printf( " : " );
+ for ( i = 0; i < dd->size; i++ )
+ printf( "%d", i % 10 );
+ printf( "\n" );
+
+ for ( i = 0; i < nParts; i++ )
+ Bbr_bddImagePrintLatchDependencyOne( dd, pbParts[i], bVarsCs, bVarsNs, i );
+ Bbr_bddImagePrintLatchDependencyOne( dd, bCare, bVarsCs, bVarsNs, nParts );
+
+ Cudd_RecursiveDeref( dd, bVarsCs );
+ Cudd_RecursiveDeref( dd, bVarsNs );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints one row of the latch dependency matrix.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Bbr_bddImagePrintLatchDependencyOne(
+ DdManager * dd, DdNode * bFunc, // the function
+ DdNode * bVarsCs, DdNode * bVarsNs, // the current/next state vars
+ int iPart )
+{
+ DdNode * bSupport;
+ int v;
+ bSupport = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupport );
+ printf( " %3d : ", iPart );
+ for ( v = 0; v < dd->size; v++ )
+ {
+ if ( Cudd_bddLeq( dd, bSupport, dd->vars[v] ) )
+ {
+ if ( Cudd_bddLeq( dd, bVarsCs, dd->vars[v] ) )
+ printf( "c" );
+ else if ( Cudd_bddLeq( dd, bVarsNs, dd->vars[v] ) )
+ printf( "n" );
+ else
+ printf( "i" );
+ }
+ else
+ printf( "." );
+ }
+ printf( "\n" );
+ Cudd_RecursiveDeref( dd, bSupport );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints the tree for quenstification scheduling.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Bbr_bddImagePrintTree( Bbr_ImageTree_t * pTree )
+{
+ printf( "The quantification scheduling tree:\n" );
+ Bbr_bddImagePrintTree_rec( pTree->pRoot, 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the tree for quenstification scheduling.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Bbr_bddImagePrintTree_rec( Bbr_ImageNode_t * pNode, int Offset )
+{
+ DdNode * Cube;
+ int i;
+
+ Cube = pNode->bCube;
+
+ if ( pNode->pNode1 == NULL )
+ {
+ printf( "<%d> ", pNode->pPart->iPart );
+ if ( Cube != NULL )
+ {
+ ABC_PRB( pNode->dd, Cube );
+ }
+ else
+ printf( "\n" );
+ return;
+ }
+
+ printf( "<*> " );
+ if ( Cube != NULL )
+ {
+ ABC_PRB( pNode->dd, Cube );
+ }
+ else
+ printf( "\n" );
+
+ for ( i = 0; i < Offset; i++ )
+ printf( " " );
+ Bbr_bddImagePrintTree_rec( pNode->pNode1, Offset + 1 );
+
+ for ( i = 0; i < Offset; i++ )
+ printf( " " );
+ Bbr_bddImagePrintTree_rec( pNode->pNode2, Offset + 1 );
+}
+
+/**Function********************************************************************
+
+ Synopsis [Computes the positive polarty cube composed of the first vars in the array.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * Bbr_bddComputeCube( DdManager * dd, DdNode ** bXVars, int nVars )
+{
+ DdNode * bRes;
+ DdNode * bTemp;
+ int i;
+
+ bRes = b1; Cudd_Ref( bRes );
+ for ( i = 0; i < nVars; i++ )
+ {
+ bRes = Cudd_bddAnd( dd, bTemp = bRes, bXVars[i] ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+
+ Cudd_Deref( bRes );
+ return bRes;
+}
+
+
+
+
+
+struct Bbr_ImageTree2_t_
+{
+ DdManager * dd;
+ DdNode * bRel;
+ DdNode * bCube;
+ DdNode * bImage;
+};
+
+/**Function*************************************************************
+
+ Synopsis [Starts the monolithic image computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Bbr_ImageTree2_t * Bbr_bddImageStart2(
+ DdManager * dd, DdNode * bCare,
+ int nParts, DdNode ** pbParts,
+ int nVars, DdNode ** pbVars, int fVerbose )
+{
+ Bbr_ImageTree2_t * pTree;
+ DdNode * bCubeAll, * bCubeNot, * bTemp;
+ int i;
+
+ pTree = ABC_ALLOC( Bbr_ImageTree2_t, 1 );
+ pTree->dd = dd;
+ pTree->bImage = NULL;
+
+ bCubeAll = Bbr_bddComputeCube( dd, dd->vars, dd->size ); Cudd_Ref( bCubeAll );
+ bCubeNot = Bbr_bddComputeCube( dd, pbVars, nVars ); Cudd_Ref( bCubeNot );
+ pTree->bCube = Cudd_bddExistAbstract( dd, bCubeAll, bCubeNot ); Cudd_Ref( pTree->bCube );
+ Cudd_RecursiveDeref( dd, bCubeAll );
+ Cudd_RecursiveDeref( dd, bCubeNot );
+
+ // derive the monolithic relation
+ pTree->bRel = b1; Cudd_Ref( pTree->bRel );
+ for ( i = 0; i < nParts; i++ )
+ {
+ pTree->bRel = Cudd_bddAnd( dd, bTemp = pTree->bRel, pbParts[i] ); Cudd_Ref( pTree->bRel );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Bbr_bddImageCompute2( pTree, bCare );
+ return pTree;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Bbr_bddImageCompute2( Bbr_ImageTree2_t * pTree, DdNode * bCare )
+{
+ if ( pTree->bImage )
+ Cudd_RecursiveDeref( pTree->dd, pTree->bImage );
+ pTree->bImage = Cudd_bddAndAbstract( pTree->dd, pTree->bRel, bCare, pTree->bCube );
+ Cudd_Ref( pTree->bImage );
+ return pTree->bImage;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Bbr_bddImageTreeDelete2( Bbr_ImageTree2_t * pTree )
+{
+ if ( pTree->bRel )
+ Cudd_RecursiveDeref( pTree->dd, pTree->bRel );
+ if ( pTree->bCube )
+ Cudd_RecursiveDeref( pTree->dd, pTree->bCube );
+ if ( pTree->bImage )
+ Cudd_RecursiveDeref( pTree->dd, pTree->bImage );
+ ABC_FREE( pTree );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the previously computed image.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Bbr_bddImageRead2( Bbr_ImageTree2_t * pTree )
+{
+ return pTree->bImage;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/bbr/bbrNtbdd.c b/src/proof/bbr/bbrNtbdd.c
new file mode 100644
index 00000000..09456df0
--- /dev/null
+++ b/src/proof/bbr/bbrNtbdd.c
@@ -0,0 +1,218 @@
+/**CFile****************************************************************
+
+ FileName [bbrNtbdd.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD-based reachability analysis.]
+
+ Synopsis [Procedures to construct global BDDs for the network.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: bbrNtbdd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bbr.h"
+//#include "bar.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+typedef char ProgressBar;
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static inline void Aig_ObjSetGlobalBdd( Aig_Obj_t * pObj, DdNode * bFunc ) { pObj->pData = bFunc; }
+static inline void Aig_ObjCleanGlobalBdd( DdManager * dd, Aig_Obj_t * pObj ) { Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); pObj->pData = NULL; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Derives the global BDD for one AIG node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Bbr_NodeGlobalBdds_rec( DdManager * dd, Aig_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose )
+{
+ DdNode * bFunc, * bFunc0, * bFunc1;
+ assert( !Aig_IsComplement(pNode) );
+ if ( Cudd_ReadKeys(dd)-Cudd_ReadDead(dd) > (unsigned)nBddSizeMax )
+ {
+// Extra_ProgressBarStop( pProgress );
+ if ( fVerbose )
+ printf( "The number of live nodes reached %d.\n", nBddSizeMax );
+ fflush( stdout );
+ return NULL;
+ }
+ // if the result is available return
+ if ( Aig_ObjGlobalBdd(pNode) == NULL )
+ {
+ // compute the result for both branches
+ bFunc0 = Bbr_NodeGlobalBdds_rec( dd, Aig_ObjFanin0(pNode), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose );
+ if ( bFunc0 == NULL )
+ return NULL;
+ Cudd_Ref( bFunc0 );
+ bFunc1 = Bbr_NodeGlobalBdds_rec( dd, Aig_ObjFanin1(pNode), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose );
+ if ( bFunc1 == NULL )
+ return NULL;
+ Cudd_Ref( bFunc1 );
+ bFunc0 = Cudd_NotCond( bFunc0, Aig_ObjFaninC0(pNode) );
+ bFunc1 = Cudd_NotCond( bFunc1, Aig_ObjFaninC1(pNode) );
+ // get the final result
+ bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( dd, bFunc0 );
+ Cudd_RecursiveDeref( dd, bFunc1 );
+ // add the number of used nodes
+ (*pCounter)++;
+ // set the result
+ assert( Aig_ObjGlobalBdd(pNode) == NULL );
+ Aig_ObjSetGlobalBdd( pNode, bFunc );
+ // increment the progress bar
+// if ( pProgress )
+// Extra_ProgressBarUpdate( pProgress, *pCounter, NULL );
+ }
+ // prepare the return value
+ bFunc = Aig_ObjGlobalBdd(pNode);
+ // dereference BDD at the node
+ if ( --pNode->nRefs == 0 && fDropInternal )
+ {
+ Cudd_Deref( bFunc );
+ Aig_ObjSetGlobalBdd( pNode, NULL );
+ }
+ return bFunc;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the global BDDs of the network.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_ManFreeGlobalBdds( Aig_Man_t * p, DdManager * dd )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Aig_ManForEachObj( p, pObj, i )
+ if ( Aig_ObjGlobalBdd(pObj) )
+ Aig_ObjCleanGlobalBdd( dd, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the shared size of global BDDs of the COs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Aig_ManSizeOfGlobalBdds( Aig_Man_t * p )
+{
+ Vec_Ptr_t * vFuncsGlob;
+ Aig_Obj_t * pObj;
+ int RetValue, i;
+ // complement the global functions
+ vFuncsGlob = Vec_PtrAlloc( Aig_ManPoNum(p) );
+ Aig_ManForEachPo( p, pObj, i )
+ Vec_PtrPush( vFuncsGlob, Aig_ObjGlobalBdd(pObj) );
+ RetValue = Cudd_SharingSize( (DdNode **)Vec_PtrArray(vFuncsGlob), Vec_PtrSize(vFuncsGlob) );
+ Vec_PtrFree( vFuncsGlob );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively computes global BDDs for the AIG in the manager.]
+
+ Description [On exit, BDDs are stored in the pNode->pData fields.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdManager * Aig_ManComputeGlobalBdds( Aig_Man_t * p, int nBddSizeMax, int fDropInternal, int fReorder, int fVerbose )
+{
+ ProgressBar * pProgress = NULL;
+ Aig_Obj_t * pObj;
+ DdManager * dd;
+ DdNode * bFunc;
+ int i, Counter;
+ // start the manager
+ dd = Cudd_Init( Aig_ManPiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ // set reordering
+ if ( fReorder )
+ Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+ // prepare to construct global BDDs
+ Aig_ManCleanData( p );
+ // assign the constant node BDD
+ Aig_ObjSetGlobalBdd( Aig_ManConst1(p), dd->one ); Cudd_Ref( dd->one );
+ // set the elementary variables
+ Aig_ManForEachPi( p, pObj, i )
+ {
+ Aig_ObjSetGlobalBdd( pObj, dd->vars[i] ); Cudd_Ref( dd->vars[i] );
+ }
+
+ // collect the global functions of the COs
+ Counter = 0;
+ // construct the BDDs
+// pProgress = Extra_ProgressBarStart( stdout, Aig_ManNodeNum(p) );
+ Aig_ManForEachPo( p, pObj, i )
+ {
+ bFunc = Bbr_NodeGlobalBdds_rec( dd, Aig_ObjFanin0(pObj), nBddSizeMax, fDropInternal, pProgress, &Counter, fVerbose );
+ if ( bFunc == NULL )
+ {
+ if ( fVerbose )
+ printf( "Constructing global BDDs is aborted.\n" );
+ Aig_ManFreeGlobalBdds( p, dd );
+ Cudd_Quit( dd );
+ // reset references
+ Aig_ManResetRefs( p );
+ return NULL;
+ }
+ bFunc = Cudd_NotCond( bFunc, Aig_ObjFaninC0(pObj) ); Cudd_Ref( bFunc );
+ Aig_ObjSetGlobalBdd( pObj, bFunc );
+ }
+// Extra_ProgressBarStop( pProgress );
+ // reset references
+ Aig_ManResetRefs( p );
+ // reorder one more time
+ if ( fReorder )
+ {
+ Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 );
+ Cudd_AutodynDisable( dd );
+ }
+// Cudd_PrintInfo( dd, stdout );
+ return dd;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/bbr/bbrReach.c b/src/proof/bbr/bbrReach.c
new file mode 100644
index 00000000..1b5c3984
--- /dev/null
+++ b/src/proof/bbr/bbrReach.c
@@ -0,0 +1,606 @@
+/**CFile****************************************************************
+
+ FileName [bbrReach.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD-based reachability analysis.]
+
+ Synopsis [Procedures to perform reachability analysis.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: bbrReach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "bbr.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern Abc_Cex_t * Aig_ManVerifyUsingBddsCountExample( Aig_Man_t * p, DdManager * dd,
+ DdNode ** pbParts, Vec_Ptr_t * vOnionRings, DdNode * bCubeFirst,
+ int iOutput, int fVerbose, int fSilent );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [This procedure sets default resynthesis parameters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Bbr_ManSetDefaultParams( Saig_ParBbr_t * p )
+{
+ memset( p, 0, sizeof(Saig_ParBbr_t) );
+ p->TimeLimit = 0;
+ p->nBddMax = 50000;
+ p->nIterMax = 1000;
+ p->fPartition = 1;
+ p->fReorder = 1;
+ p->fReorderImage = 1;
+ p->fVerbose = 0;
+ p->fSilent = 0;
+ p->iFrame = -1;
+}
+
+/**Function********************************************************************
+
+ Synopsis [Performs the reordering-sensitive step of Extra_bddMove().]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+******************************************************************************/
+DdNode * Bbr_bddComputeRangeCube( DdManager * dd, int iStart, int iStop )
+{
+ DdNode * bTemp, * bProd;
+ int i;
+ assert( iStart <= iStop );
+ assert( iStart >= 0 && iStart <= dd->size );
+ assert( iStop >= 0 && iStop <= dd->size );
+ bProd = (dd)->one; Cudd_Ref( bProd );
+ for ( i = iStart; i < iStop; i++ )
+ {
+ bProd = Cudd_bddAnd( dd, bTemp = bProd, dd->vars[i] ); Cudd_Ref( bProd );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bProd );
+ return bProd;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Bbr_StopManager( DdManager * dd )
+{
+ int RetValue;
+ // check for remaining references in the package
+ RetValue = Cudd_CheckZeroRef( dd );
+ if ( RetValue > 0 )
+ printf( "\nThe number of referenced nodes = %d\n\n", RetValue );
+// Cudd_PrintInfo( dd, stdout );
+ Cudd_Quit( dd );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the initial state and sets up the variable map.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Aig_ManInitStateVarMap( DdManager * dd, Aig_Man_t * p, int fVerbose )
+{
+ DdNode ** pbVarsX, ** pbVarsY;
+ DdNode * bTemp, * bProd;
+ Aig_Obj_t * pLatch;
+ int i;
+
+ // set the variable mapping for Cudd_bddVarMap()
+ pbVarsX = ABC_ALLOC( DdNode *, dd->size );
+ pbVarsY = ABC_ALLOC( DdNode *, dd->size );
+ bProd = (dd)->one; Cudd_Ref( bProd );
+ Saig_ManForEachLo( p, pLatch, i )
+ {
+ pbVarsX[i] = dd->vars[ Saig_ManPiNum(p) + i ];
+ pbVarsY[i] = dd->vars[ Saig_ManCiNum(p) + i ];
+ // get the initial value of the latch
+ bProd = Cudd_bddAnd( dd, bTemp = bProd, Cudd_Not(pbVarsX[i]) ); Cudd_Ref( bProd );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_SetVarMap( dd, pbVarsX, pbVarsY, Saig_ManRegNum(p) );
+ ABC_FREE( pbVarsX );
+ ABC_FREE( pbVarsY );
+
+ Cudd_Deref( bProd );
+ return bProd;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the array of output BDDs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode ** Aig_ManCreateOutputs( DdManager * dd, Aig_Man_t * p )
+{
+ DdNode ** pbOutputs;
+ Aig_Obj_t * pNode;
+ int i;
+ // compute the transition relation
+ pbOutputs = ABC_ALLOC( DdNode *, Saig_ManPoNum(p) );
+ Saig_ManForEachPo( p, pNode, i )
+ {
+ pbOutputs[i] = Aig_ObjGlobalBdd(pNode); Cudd_Ref( pbOutputs[i] );
+ }
+ return pbOutputs;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the array of partition BDDs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode ** Aig_ManCreatePartitions( DdManager * dd, Aig_Man_t * p, int fReorder, int fVerbose )
+{
+ DdNode ** pbParts;
+ DdNode * bVar;
+ Aig_Obj_t * pNode;
+ int i;
+
+ // extand the BDD manager to represent NS variables
+ assert( dd->size == Saig_ManCiNum(p) );
+ Cudd_bddIthVar( dd, Saig_ManCiNum(p) + Saig_ManRegNum(p) - 1 );
+
+ // enable reordering
+ if ( fReorder )
+ Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+ else
+ Cudd_AutodynDisable( dd );
+
+ // compute the transition relation
+ pbParts = ABC_ALLOC( DdNode *, Saig_ManRegNum(p) );
+ Saig_ManForEachLi( p, pNode, i )
+ {
+ bVar = Cudd_bddIthVar( dd, Saig_ManCiNum(p) + i );
+ pbParts[i] = Cudd_bddXnor( dd, bVar, Aig_ObjGlobalBdd(pNode) ); Cudd_Ref( pbParts[i] );
+ }
+ // free global BDDs
+ Aig_ManFreeGlobalBdds( p, dd );
+
+ // reorder and disable reordering
+ if ( fReorder )
+ {
+ if ( fVerbose )
+ fprintf( stdout, "BDD nodes in the partitions before reordering %d.\n", Cudd_SharingSize(pbParts,Saig_ManRegNum(p)) );
+ Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+ Cudd_AutodynDisable( dd );
+ if ( fVerbose )
+ fprintf( stdout, "BDD nodes in the partitions after reordering %d.\n", Cudd_SharingSize(pbParts,Saig_ManRegNum(p)) );
+ }
+ return pbParts;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the set of unreachable states.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Aig_ManComputeReachable( DdManager * dd, Aig_Man_t * p, DdNode ** pbParts, DdNode * bInitial, DdNode ** pbOutputs, Saig_ParBbr_t * pPars, int fCheckOutputs )
+{
+ int fInternalReorder = 0;
+ Bbr_ImageTree_t * pTree = NULL; // Suppress "might be used uninitialized"
+ Bbr_ImageTree2_t * pTree2 = NULL; // Supprses "might be used uninitialized"
+ DdNode * bReached, * bCubeCs;
+ DdNode * bCurrent;
+ DdNode * bNext = NULL; // Suppress "might be used uninitialized"
+ DdNode * bTemp;
+ Cudd_ReorderingType method;
+ int i, nIters, nBddSize = 0, status;
+ int nThreshold = 10000, clk = clock();
+ Vec_Ptr_t * vOnionRings;
+
+ status = Cudd_ReorderingStatus( dd, &method );
+ if ( status )
+ Cudd_AutodynDisable( dd );
+
+ // start the image computation
+ bCubeCs = Bbr_bddComputeRangeCube( dd, Saig_ManPiNum(p), Saig_ManCiNum(p) ); Cudd_Ref( bCubeCs );
+ if ( pPars->fPartition )
+ pTree = Bbr_bddImageStart( dd, bCubeCs, Saig_ManRegNum(p), pbParts, Saig_ManRegNum(p), dd->vars+Saig_ManCiNum(p), pPars->nBddMax, pPars->fVerbose );
+ else
+ pTree2 = Bbr_bddImageStart2( dd, bCubeCs, Saig_ManRegNum(p), pbParts, Saig_ManRegNum(p), dd->vars+Saig_ManCiNum(p), pPars->fVerbose );
+ Cudd_RecursiveDeref( dd, bCubeCs );
+ if ( pTree == NULL )
+ {
+ if ( !pPars->fSilent )
+ printf( "BDDs blew up during qualitification scheduling. " );
+ return -1;
+ }
+
+ if ( status )
+ Cudd_AutodynEnable( dd, method );
+
+ // start the onion rings
+ vOnionRings = Vec_PtrAlloc( 1000 );
+
+ // perform reachability analysis
+ bCurrent = bInitial; Cudd_Ref( bCurrent );
+ bReached = bInitial; Cudd_Ref( bReached );
+ Vec_PtrPush( vOnionRings, bCurrent ); Cudd_Ref( bCurrent );
+ for ( nIters = 0; nIters < pPars->nIterMax; nIters++ )
+ {
+ // check the runtime limit
+ if ( pPars->TimeLimit && ((float)pPars->TimeLimit <= (float)(clock()-clk)/(float)(CLOCKS_PER_SEC)) )
+ {
+ printf( "Reached timeout after image computation (%d seconds).\n", pPars->TimeLimit );
+ Vec_PtrFree( vOnionRings );
+ // undo the image tree
+ if ( pPars->fPartition )
+ Bbr_bddImageTreeDelete( pTree );
+ else
+ Bbr_bddImageTreeDelete2( pTree2 );
+ pPars->iFrame = nIters - 1;
+ return -1;
+ }
+
+ // compute the next states
+ if ( pPars->fPartition )
+ bNext = Bbr_bddImageCompute( pTree, bCurrent );
+ else
+ bNext = Bbr_bddImageCompute2( pTree2, bCurrent );
+ if ( bNext == NULL )
+ {
+ if ( !pPars->fSilent )
+ printf( "BDDs blew up during image computation. " );
+ if ( pPars->fPartition )
+ Bbr_bddImageTreeDelete( pTree );
+ else
+ Bbr_bddImageTreeDelete2( pTree2 );
+ Vec_PtrFree( vOnionRings );
+ pPars->iFrame = nIters - 1;
+ return -1;
+ }
+ Cudd_Ref( bNext );
+ Cudd_RecursiveDeref( dd, bCurrent );
+
+ // remap these states into the current state vars
+ bNext = Cudd_bddVarMap( dd, bTemp = bNext ); Cudd_Ref( bNext );
+ Cudd_RecursiveDeref( dd, bTemp );
+ // check if there are any new states
+ if ( Cudd_bddLeq( dd, bNext, bReached ) )
+ break;
+ // check the BDD size
+ nBddSize = Cudd_DagSize(bNext);
+ if ( nBddSize > pPars->nBddMax )
+ break;
+ // check the result
+ for ( i = 0; i < Saig_ManPoNum(p); i++ )
+ {
+ if ( fCheckOutputs && !Cudd_bddLeq( dd, bNext, Cudd_Not(pbOutputs[i]) ) )
+ {
+ DdNode * bIntersect;
+ bIntersect = Cudd_bddIntersect( dd, bNext, pbOutputs[i] ); Cudd_Ref( bIntersect );
+ assert( p->pSeqModel == NULL );
+ p->pSeqModel = Aig_ManVerifyUsingBddsCountExample( p, dd, pbParts,
+ vOnionRings, bIntersect, i, pPars->fVerbose, pPars->fSilent );
+ Cudd_RecursiveDeref( dd, bIntersect );
+ if ( !pPars->fSilent )
+ printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump a witness). ", i, Vec_PtrSize(vOnionRings) );
+ Cudd_RecursiveDeref( dd, bReached );
+ bReached = NULL;
+ pPars->iFrame = nIters;
+ break;
+ }
+ }
+ if ( i < Saig_ManPoNum(p) )
+ break;
+ // get the new states
+ bCurrent = Cudd_bddAnd( dd, bNext, Cudd_Not(bReached) ); Cudd_Ref( bCurrent );
+ Vec_PtrPush( vOnionRings, bCurrent ); Cudd_Ref( bCurrent );
+ // minimize the new states with the reached states
+// bCurrent = Cudd_bddConstrain( dd, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent );
+// Cudd_RecursiveDeref( dd, bTemp );
+ // add to the reached states
+ bReached = Cudd_bddOr( dd, bTemp = bReached, bNext ); Cudd_Ref( bReached );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bNext );
+ if ( pPars->fVerbose )
+ fprintf( stdout, "Frame = %3d. BDD = %5d. ", nIters, nBddSize );
+ if ( fInternalReorder && pPars->fReorder && nBddSize > nThreshold )
+ {
+ if ( pPars->fVerbose )
+ fprintf( stdout, "Reordering... Before = %5d. ", Cudd_DagSize(bReached) );
+ Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+ Cudd_AutodynDisable( dd );
+ if ( pPars->fVerbose )
+ fprintf( stdout, "After = %5d.\r", Cudd_DagSize(bReached) );
+ nThreshold *= 2;
+ }
+ if ( pPars->fVerbose )
+// fprintf( stdout, "\r" );
+ fprintf( stdout, "\n" );
+
+ if ( pPars->fVerbose )
+ {
+ double nMints = Cudd_CountMinterm(dd, bReached, Saig_ManRegNum(p) );
+// Extra_bddPrint( dd, bReached );printf( "\n" );
+ fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p)) );
+ fflush( stdout );
+ }
+
+ }
+ Cudd_RecursiveDeref( dd, bNext );
+ // free the onion rings
+ Vec_PtrForEachEntry( DdNode *, vOnionRings, bTemp, i )
+ Cudd_RecursiveDeref( dd, bTemp );
+ Vec_PtrFree( vOnionRings );
+ // undo the image tree
+ if ( pPars->fPartition )
+ Bbr_bddImageTreeDelete( pTree );
+ else
+ Bbr_bddImageTreeDelete2( pTree2 );
+ if ( bReached == NULL )
+ return 0; // proved reachable
+ // report the stats
+ if ( pPars->fVerbose )
+ {
+ double nMints = Cudd_CountMinterm(dd, bReached, Saig_ManRegNum(p) );
+ if ( nIters > pPars->nIterMax || nBddSize > pPars->nBddMax )
+ fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters );
+ else
+ fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters );
+ fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p)) );
+ fflush( stdout );
+ }
+//ABC_PRB( dd, bReached );
+ Cudd_RecursiveDeref( dd, bReached );
+ if ( nIters > pPars->nIterMax || nBddSize > pPars->nBddMax )
+ {
+ if ( !pPars->fSilent )
+ printf( "Verified only for states reachable in %d frames. ", nIters );
+ return -1; // undecided
+ }
+ if ( !pPars->fSilent )
+ printf( "The miter is proved unreachable after %d iterations. ", nIters );
+ pPars->iFrame = nIters - 1;
+ return 1; // unreachable
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs reachability to see if any PO can be asserted.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Aig_ManVerifyUsingBdds_int( Aig_Man_t * p, Saig_ParBbr_t * pPars )
+{
+ int fCheckOutputs = !pPars->fSkipOutCheck;
+ DdManager * dd;
+ DdNode ** pbParts, ** pbOutputs;
+ DdNode * bInitial, * bTemp;
+ int RetValue, i, clk = clock();
+ Vec_Ptr_t * vOnionRings;
+
+ assert( Saig_ManRegNum(p) > 0 );
+
+ // compute the global BDDs of the latches
+ dd = Aig_ManComputeGlobalBdds( p, pPars->nBddMax, 1, pPars->fReorder, pPars->fVerbose );
+ if ( dd == NULL )
+ {
+ if ( !pPars->fSilent )
+ printf( "The number of intermediate BDD nodes exceeded the limit (%d).\n", pPars->nBddMax );
+ return -1;
+ }
+ if ( pPars->fVerbose )
+ printf( "Shared BDD size is %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+
+ // check the runtime limit
+ if ( pPars->TimeLimit && ((float)pPars->TimeLimit <= (float)(clock()-clk)/(float)(CLOCKS_PER_SEC)) )
+ {
+ printf( "Reached timeout after constructing global BDDs (%d seconds).\n", pPars->TimeLimit );
+ Cudd_Quit( dd );
+ return -1;
+ }
+
+ // start the onion rings
+ vOnionRings = Vec_PtrAlloc( 1000 );
+
+ // save outputs
+ pbOutputs = Aig_ManCreateOutputs( dd, p );
+
+ // create partitions
+ pbParts = Aig_ManCreatePartitions( dd, p, pPars->fReorder, pPars->fVerbose );
+
+ // create the initial state and the variable map
+ bInitial = Aig_ManInitStateVarMap( dd, p, pPars->fVerbose ); Cudd_Ref( bInitial );
+
+ // set reordering
+ if ( pPars->fReorderImage )
+ Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+
+ // check the result
+ RetValue = -1;
+ for ( i = 0; i < Saig_ManPoNum(p); i++ )
+ {
+ if ( fCheckOutputs && !Cudd_bddLeq( dd, bInitial, Cudd_Not(pbOutputs[i]) ) )
+ {
+ DdNode * bIntersect;
+ bIntersect = Cudd_bddIntersect( dd, bInitial, pbOutputs[i] ); Cudd_Ref( bIntersect );
+ assert( p->pSeqModel == NULL );
+ p->pSeqModel = Aig_ManVerifyUsingBddsCountExample( p, dd, pbParts,
+ vOnionRings, bIntersect, i, pPars->fVerbose, pPars->fSilent );
+ Cudd_RecursiveDeref( dd, bIntersect );
+ if ( !pPars->fSilent )
+ printf( "The miter output %d is proved REACHABLE in the initial state (use \"write_counter\" to dump a witness). ", i );
+ RetValue = 0;
+ break;
+ }
+ }
+ // free the onion rings
+ Vec_PtrForEachEntry( DdNode *, vOnionRings, bTemp, i )
+ Cudd_RecursiveDeref( dd, bTemp );
+ Vec_PtrFree( vOnionRings );
+ // explore reachable states
+ if ( RetValue == -1 )
+ RetValue = Aig_ManComputeReachable( dd, p, pbParts, bInitial, pbOutputs, pPars, fCheckOutputs );
+
+ // cleanup
+ Cudd_RecursiveDeref( dd, bInitial );
+ for ( i = 0; i < Saig_ManRegNum(p); i++ )
+ Cudd_RecursiveDeref( dd, pbParts[i] );
+ ABC_FREE( pbParts );
+ for ( i = 0; i < Saig_ManPoNum(p); i++ )
+ Cudd_RecursiveDeref( dd, pbOutputs[i] );
+ ABC_FREE( pbOutputs );
+// if ( RetValue == -1 )
+ Cudd_Quit( dd );
+// else
+// Bbr_StopManager( dd );
+
+ // report the runtime
+ if ( !pPars->fSilent )
+ {
+ ABC_PRT( "Time", clock() - clk );
+ fflush( stdout );
+ }
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs reachability to see if any PO can be asserted.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Aig_ManVerifyUsingBdds( Aig_Man_t * pInit, Saig_ParBbr_t * pPars )
+{
+ Abc_Cex_t * pCexOld, * pCexNew;
+ Aig_Man_t * p;
+ Aig_Obj_t * pObj;
+ Vec_Int_t * vInputMap;
+ int i, k, Entry, iBitOld, iBitNew, RetValue;
+// pPars->fVerbose = 1;
+ // check if there are PIs without fanout
+ Saig_ManForEachPi( pInit, pObj, i )
+ if ( Aig_ObjRefs(pObj) == 0 )
+ break;
+ if ( i == Saig_ManPiNum(pInit) )
+ return Aig_ManVerifyUsingBdds_int( pInit, pPars );
+ // create new AIG
+ p = Aig_ManDupTrim( pInit );
+ assert( Aig_ManPiNum(p) < Aig_ManPiNum(pInit) );
+ assert( Aig_ManRegNum(p) == Aig_ManRegNum(pInit) );
+ RetValue = Aig_ManVerifyUsingBdds_int( p, pPars );
+ if ( RetValue != 0 )
+ {
+ Aig_ManStop( p );
+ return RetValue;
+ }
+ // the problem is satisfiable - remap the pattern
+ pCexOld = p->pSeqModel;
+ assert( pCexOld != NULL );
+ // create input map
+ vInputMap = Vec_IntAlloc( Saig_ManPiNum(pInit) );
+ Saig_ManForEachPi( pInit, pObj, i )
+ if ( pObj->pData != NULL )
+ Vec_IntPush( vInputMap, Aig_ObjPioNum((Aig_Obj_t *)pObj->pData) );
+ else
+ Vec_IntPush( vInputMap, -1 );
+ // create new pattern
+ pCexNew = Abc_CexAlloc( Saig_ManRegNum(pInit), Saig_ManPiNum(pInit), pCexOld->iFrame+1 );
+ pCexNew->iFrame = pCexOld->iFrame;
+ pCexNew->iPo = pCexOld->iPo;
+ // copy the bit-data
+ for ( iBitOld = 0; iBitOld < pCexOld->nRegs; iBitOld++ )
+ if ( Abc_InfoHasBit( pCexOld->pData, iBitOld ) )
+ Abc_InfoSetBit( pCexNew->pData, iBitOld );
+ // copy the primary input data
+ iBitNew = iBitOld;
+ for ( i = 0; i <= pCexNew->iFrame; i++ )
+ {
+ Vec_IntForEachEntry( vInputMap, Entry, k )
+ {
+ if ( Entry == -1 )
+ continue;
+ if ( Abc_InfoHasBit( pCexOld->pData, iBitOld + Entry ) )
+ Abc_InfoSetBit( pCexNew->pData, iBitNew + k );
+ }
+ iBitOld += Saig_ManPiNum(p);
+ iBitNew += Saig_ManPiNum(pInit);
+ }
+ assert( iBitOld < iBitNew );
+ assert( iBitOld == pCexOld->nBits );
+ assert( iBitNew == pCexNew->nBits );
+ Vec_IntFree( vInputMap );
+ pInit->pSeqModel = pCexNew;
+ Aig_ManStop( p );
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/bbr/bbr_.c b/src/proof/bbr/bbr_.c
new file mode 100644
index 00000000..df934f7d
--- /dev/null
+++ b/src/proof/bbr/bbr_.c
@@ -0,0 +1,52 @@
+/**CFile****************************************************************
+
+ FileName [.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName []
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: .c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "__Int.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/bbr/module.make b/src/proof/bbr/module.make
new file mode 100644
index 00000000..11ba768e
--- /dev/null
+++ b/src/proof/bbr/module.make
@@ -0,0 +1,4 @@
+SRC += src/proof/bbr/bbrCex.c \
+ src/proof/bbr/bbrImage.c \
+ src/proof/bbr/bbrNtbdd.c \
+ src/proof/bbr/bbrReach.c
diff --git a/src/proof/cec/cec.c b/src/proof/cec/cec.c
new file mode 100644
index 00000000..6968a599
--- /dev/null
+++ b/src/proof/cec/cec.c
@@ -0,0 +1,53 @@
+/**CFile****************************************************************
+
+ FileName [cec.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Combinational equivalence checking.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/cec/cec.h b/src/proof/cec/cec.h
new file mode 100644
index 00000000..10b06c28
--- /dev/null
+++ b/src/proof/cec/cec.h
@@ -0,0 +1,233 @@
+/**CFile****************************************************************
+
+ FileName [cec.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Combinational equivalence checking.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__cec__cec_h
+#define ABC__aig__cec__cec_h
+
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+// dynamic SAT parameters
+typedef struct Cec_ParSat_t_ Cec_ParSat_t;
+struct Cec_ParSat_t_
+{
+ int nBTLimit; // conflict limit at a node
+ int nSatVarMax; // the max number of SAT variables
+ int nCallsRecycle; // calls to perform before recycling SAT solver
+ int fNonChrono; // use non-chronological backtracling (for circuit SAT only)
+ int fPolarFlip; // flops polarity of variables
+ int fCheckMiter; // the circuit is the miter
+// int fFirstStop; // stop on the first sat output
+ int fLearnCls; // perform clause learning
+ int fVerbose; // verbose stats
+};
+
+// simulation parameters
+typedef struct Cec_ParSim_t_ Cec_ParSim_t;
+struct Cec_ParSim_t_
+{
+ int nWords; // the number of simulation words
+ int nFrames; // the number of simulation frames
+ int nRounds; // the number of simulation rounds
+ int nNonRefines; // the max number of rounds without refinement
+ int TimeLimit; // the runtime limit in seconds
+ int fDualOut; // miter with separate outputs
+ int fCheckMiter; // the circuit is the miter
+// int fFirstStop; // stop on the first sat output
+ int fSeqSimulate; // performs sequential simulation
+ int fLatchCorr; // consider only latch outputs
+ int fConstCorr; // consider only constants
+ int fVeryVerbose; // verbose stats
+ int fVerbose; // verbose stats
+};
+
+// semiformal parameters
+typedef struct Cec_ParSmf_t_ Cec_ParSmf_t;
+struct Cec_ParSmf_t_
+{
+ int nWords; // the number of simulation words
+ int nRounds; // the number of simulation rounds
+ int nFrames; // the max number of time frames
+ int nNonRefines; // the max number of rounds without refinement
+ int nMinOutputs; // the min outputs to accumulate
+ int nBTLimit; // conflict limit at a node
+ int TimeLimit; // the runtime limit in seconds
+ int fDualOut; // miter with separate outputs
+ int fCheckMiter; // the circuit is the miter
+// int fFirstStop; // stop on the first sat output
+ int fVerbose; // verbose stats
+};
+
+// combinational SAT sweeping parameters
+typedef struct Cec_ParFra_t_ Cec_ParFra_t;
+struct Cec_ParFra_t_
+{
+ int nWords; // the number of simulation words
+ int nRounds; // the number of simulation rounds
+ int nItersMax; // the maximum number of iterations of SAT sweeping
+ int nBTLimit; // conflict limit at a node
+ int TimeLimit; // the runtime limit in seconds
+ int nLevelMax; // restriction on the level nodes to be swept
+ int nDepthMax; // the depth in terms of steps of speculative reduction
+ int fRewriting; // enables AIG rewriting
+ int fCheckMiter; // the circuit is the miter
+// int fFirstStop; // stop on the first sat output
+ int fDualOut; // miter with separate outputs
+ int fColorDiff; // miter with separate outputs
+ int fSatSweeping; // enable SAT sweeping
+ int fVeryVerbose; // verbose stats
+ int fVerbose; // verbose stats
+ int iOutFail; // the failed output
+};
+
+// combinational equivalence checking parameters
+typedef struct Cec_ParCec_t_ Cec_ParCec_t;
+struct Cec_ParCec_t_
+{
+ int nBTLimit; // conflict limit at a node
+ int TimeLimit; // the runtime limit in seconds
+// int fFirstStop; // stop on the first sat output
+ int fUseSmartCnf; // use smart CNF computation
+ int fRewriting; // enables AIG rewriting
+ int fVeryVerbose; // verbose stats
+ int fVerbose; // verbose stats
+ int iOutFail; // the number of failed output
+};
+
+// sequential register correspodence parameters
+typedef struct Cec_ParCor_t_ Cec_ParCor_t;
+struct Cec_ParCor_t_
+{
+ int nWords; // the number of simulation words
+ int nRounds; // the number of simulation rounds
+ int nFrames; // the number of time frames
+ int nPrefix; // the number of time frames in the prefix
+ int nBTLimit; // conflict limit at a node
+ int nLevelMax; // (scorr only) the max number of levels
+ int nStepsMax; // (scorr only) the max number of induction steps
+ int fLatchCorr; // consider only latch outputs
+ int fConstCorr; // consider only constants
+ int fUseRings; // use rings
+ int fMakeChoices; // use equilvaences as choices
+ int fUseCSat; // use circuit-based solver
+// int fFirstStop; // stop on the first sat output
+ int fUseSmartCnf; // use smart CNF computation
+ int fVerboseFlops; // verbose stats
+ int fVeryVerbose; // verbose stats
+ int fVerbose; // verbose stats
+ // callback
+ void * pData;
+ void * pFunc;
+};
+
+// sequential register correspodence parameters
+typedef struct Cec_ParChc_t_ Cec_ParChc_t;
+struct Cec_ParChc_t_
+{
+ int nWords; // the number of simulation words
+ int nRounds; // the number of simulation rounds
+ int nBTLimit; // conflict limit at a node
+ int fUseRings; // use rings
+ int fUseCSat; // use circuit-based solver
+ int fVeryVerbose; // verbose stats
+ int fVerbose; // verbose stats
+};
+
+// sequential synthesis parameters
+typedef struct Cec_ParSeq_t_ Cec_ParSeq_t;
+struct Cec_ParSeq_t_
+{
+ int fUseLcorr; // enables latch correspondence
+ int fUseScorr; // enables signal correspondence
+ int nBTLimit; // (scorr/lcorr) conflict limit at a node
+ int nFrames; // (scorr/lcorr) the number of timeframes
+ int nLevelMax; // (scorr only) the max number of levels
+ int fConsts; // (scl only) merging constants
+ int fEquivs; // (scl only) merging equivalences
+ int fUseMiniSat; // enables MiniSat in lcorr/scorr
+ int nMinDomSize; // the size of minimum clock domain
+ int fVeryVerbose; // verbose stats
+ int fVerbose; // verbose stats
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== cecCec.c ==========================================================*/
+extern int Cec_ManVerify( Gia_Man_t * p, Cec_ParCec_t * pPars );
+extern int Cec_ManVerifyTwo( Gia_Man_t * p0, Gia_Man_t * p1, int fVerbose );
+/*=== cecChoice.c ==========================================================*/
+extern Gia_Man_t * Cec_ManChoiceComputation( Gia_Man_t * pAig, Cec_ParChc_t * pPars );
+/*=== cecCorr.c ==========================================================*/
+extern int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars );
+extern Gia_Man_t * Cec_ManLSCorrespondence( Gia_Man_t * pAig, Cec_ParCor_t * pPars );
+/*=== cecCore.c ==========================================================*/
+extern void Cec_ManSatSetDefaultParams( Cec_ParSat_t * p );
+extern void Cec_ManSimSetDefaultParams( Cec_ParSim_t * p );
+extern void Cec_ManSmfSetDefaultParams( Cec_ParSmf_t * p );
+extern void Cec_ManFraSetDefaultParams( Cec_ParFra_t * p );
+extern void Cec_ManCecSetDefaultParams( Cec_ParCec_t * p );
+extern void Cec_ManCorSetDefaultParams( Cec_ParCor_t * p );
+extern void Cec_ManChcSetDefaultParams( Cec_ParChc_t * p );
+extern Gia_Man_t * Cec_ManSatSweeping( Gia_Man_t * pAig, Cec_ParFra_t * pPars );
+extern Gia_Man_t * Cec_ManSatSolving( Gia_Man_t * pAig, Cec_ParSat_t * pPars );
+extern void Cec_ManSimulation( Gia_Man_t * pAig, Cec_ParSim_t * pPars );
+/*=== cecSeq.c ==========================================================*/
+extern int Cec_ManSeqResimulateCounter( Gia_Man_t * pAig, Cec_ParSim_t * pPars, Abc_Cex_t * pCex );
+extern int Cec_ManSeqSemiformal( Gia_Man_t * pAig, Cec_ParSmf_t * pPars );
+extern int Cec_ManCheckNonTrivialCands( Gia_Man_t * pAig );
+/*=== cecSynth.c ==========================================================*/
+extern int Cec_SeqReadMinDomSize( Cec_ParSeq_t * p );
+extern int Cec_SeqReadVerbose( Cec_ParSeq_t * p );
+extern void Cec_SeqSynthesisSetDefaultParams( Cec_ParSeq_t * pPars );
+extern int Cec_SequentialSynthesisPart( Gia_Man_t * p, Cec_ParSeq_t * pPars );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/proof/cec/cecCec.c b/src/proof/cec/cecCec.c
new file mode 100644
index 00000000..1460ba91
--- /dev/null
+++ b/src/proof/cec/cecCec.c
@@ -0,0 +1,373 @@
+/**CFile****************************************************************
+
+ FileName [cecCec.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Combinational equivalence checking.]
+
+ Synopsis [Integrated combinatinal equivalence checker.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cecCec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+#include "src/proof/fra/fra.h"
+#include "src/aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Saves the input pattern with the given number.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManTransformPattern( Gia_Man_t * p, int iOut, int * pValues )
+{
+ int i;
+ assert( p->pCexComb == NULL );
+ p->pCexComb = (Abc_Cex_t *)ABC_CALLOC( char,
+ sizeof(Abc_Cex_t) + sizeof(unsigned) * Abc_BitWordNum(Gia_ManCiNum(p)) );
+ p->pCexComb->iPo = iOut;
+ p->pCexComb->nPis = Gia_ManCiNum(p);
+ p->pCexComb->nBits = Gia_ManCiNum(p);
+ for ( i = 0; i < Gia_ManCiNum(p); i++ )
+ if ( pValues[i] )
+ Abc_InfoSetBit( p->pCexComb->pData, i );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Interface to the old CEC engine]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManVerifyOld( Gia_Man_t * pMiter, int fVerbose, int * piOutFail )
+{
+// extern int Fra_FraigCec( Aig_Man_t ** ppAig, int nConfLimit, int fVerbose );
+ extern int Ssw_SecCexResimulate( Aig_Man_t * p, int * pModel, int * pnOutputs );
+ Gia_Man_t * pTemp = Gia_ManTransformMiter( pMiter );
+ Aig_Man_t * pMiterCec = Gia_ManToAig( pTemp, 0 );
+ int RetValue, iOut, nOuts, clkTotal = clock();
+ if ( piOutFail )
+ *piOutFail = -1;
+ Gia_ManStop( pTemp );
+ // run CEC on this miter
+ RetValue = Fra_FraigCec( &pMiterCec, 10000000, fVerbose );
+ // report the miter
+ if ( RetValue == 1 )
+ {
+ Abc_Print( 1, "Networks are equivalent. " );
+Abc_PrintTime( 1, "Time", clock() - clkTotal );
+ }
+ else if ( RetValue == 0 )
+ {
+ Abc_Print( 1, "Networks are NOT EQUIVALENT. " );
+Abc_PrintTime( 1, "Time", clock() - clkTotal );
+ if ( pMiterCec->pData == NULL )
+ Abc_Print( 1, "Counter-example is not available.\n" );
+ else
+ {
+ iOut = Ssw_SecCexResimulate( pMiterCec, (int *)pMiterCec->pData, &nOuts );
+ if ( iOut == -1 )
+ Abc_Print( 1, "Counter-example verification has failed.\n" );
+ else
+ {
+// Aig_Obj_t * pObj = Aig_ManPo(pMiterCec, iOut);
+// Aig_Obj_t * pFan = Aig_ObjFanin0(pObj);
+ Abc_Print( 1, "Primary output %d has failed", iOut );
+ if ( nOuts-1 >= 0 )
+ Abc_Print( 1, ", along with other %d incorrect outputs", nOuts-1 );
+ Abc_Print( 1, ".\n" );
+ if ( piOutFail )
+ *piOutFail = iOut;
+ }
+ Cec_ManTransformPattern( pMiter, iOut, (int *)pMiterCec->pData );
+ }
+ }
+ else
+ {
+ Abc_Print( 1, "Networks are UNDECIDED. " );
+Abc_PrintTime( 1, "Time", clock() - clkTotal );
+ }
+ fflush( stdout );
+ Aig_ManStop( pMiterCec );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [New CEC engine.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManVerify( Gia_Man_t * pInit, Cec_ParCec_t * pPars )
+{
+ int fDumpUndecided = 0;
+ Cec_ParFra_t ParsFra, * pParsFra = &ParsFra;
+ Gia_Man_t * p, * pNew;
+ int RetValue, clk = clock();
+ double clkTotal = clock();
+ // preprocess
+ p = Gia_ManDup( pInit );
+ Gia_ManEquivFixOutputPairs( p );
+ p = Gia_ManCleanup( pNew = p );
+ Gia_ManStop( pNew );
+ // sweep for equivalences
+ Cec_ManFraSetDefaultParams( pParsFra );
+ pParsFra->nItersMax = 1000;
+ pParsFra->nBTLimit = pPars->nBTLimit;
+ pParsFra->TimeLimit = pPars->TimeLimit;
+ pParsFra->fVerbose = pPars->fVerbose;
+ pParsFra->fCheckMiter = 1;
+ pParsFra->fDualOut = 1;
+ pNew = Cec_ManSatSweeping( p, pParsFra );
+ pPars->iOutFail = pParsFra->iOutFail;
+ // update
+ pInit->pCexComb = p->pCexComb; p->pCexComb = NULL;
+ Gia_ManStop( p );
+ p = pInit;
+ // continue
+ if ( pNew == NULL )
+ {
+ if ( p->pCexComb != NULL )
+ {
+ if ( p->pCexComb && !Gia_ManVerifyCex( p, p->pCexComb, 1 ) )
+ Abc_Print( 1, "Counter-example simulation has failed.\n" );
+ Abc_Print( 1, "Networks are NOT EQUIVALENT. " );
+ Abc_PrintTime( 1, "Time", clock() - clk );
+ return 0;
+ }
+ p = Gia_ManDup( pInit );
+ Gia_ManEquivFixOutputPairs( p );
+ p = Gia_ManCleanup( pNew = p );
+ Gia_ManStop( pNew );
+ pNew = p;
+ }
+ if ( Gia_ManAndNum(pNew) == 0 )
+ {
+ Gia_Obj_t * pObj1, * pObj2;
+ int i;
+ Gia_ManForEachPo( pNew, pObj1, i )
+ {
+ pObj2 = Gia_ManPo( pNew, ++i );
+ if ( Gia_ObjChild0(pObj1) != Gia_ObjChild0(pObj2) )
+ {
+ Abc_Print( 1, "Networks are NOT EQUIVALENT. Outputs %d trivially differ. ", i/2 );
+ Abc_PrintTime( 1, "Time", clock() - clk );
+ Gia_ManStop( pNew );
+ pPars->iOutFail = i/2;
+ return 0;
+ }
+ }
+ Abc_Print( 1, "Networks are equivalent. " );
+ Abc_PrintTime( 1, "Time", clock() - clk );
+ Gia_ManStop( pNew );
+ return 1;
+ }
+ if ( pPars->fVerbose )
+ {
+ Abc_Print( 1, "Networks are UNDECIDED after the new CEC engine. " );
+ Abc_PrintTime( 1, "Time", clock() - clk );
+ }
+ if ( fDumpUndecided )
+ {
+ ABC_FREE( pNew->pReprs );
+ ABC_FREE( pNew->pNexts );
+ Gia_WriteAiger( pNew, "gia_cec_undecided.aig", 0, 0 );
+ Abc_Print( 1, "The result is written into file \"%s\".\n", "gia_cec_undecided.aig" );
+ }
+ if ( pPars->TimeLimit && ((double)clock() - clkTotal)/CLOCKS_PER_SEC >= pPars->TimeLimit )
+ {
+ Gia_ManStop( pNew );
+ return -1;
+ }
+ // call other solver
+ if ( pPars->fVerbose )
+ Abc_Print( 1, "Calling the old CEC engine.\n" );
+ fflush( stdout );
+ RetValue = Cec_ManVerifyOld( pNew, pPars->fVerbose, &pPars->iOutFail );
+ p->pCexComb = pNew->pCexComb; pNew->pCexComb = NULL;
+ if ( p->pCexComb && !Gia_ManVerifyCex( p, p->pCexComb, 1 ) )
+ Abc_Print( 1, "Counter-example simulation has failed.\n" );
+ Gia_ManStop( pNew );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [New CEC engine applied to two circuits.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManVerifyTwo( Gia_Man_t * p0, Gia_Man_t * p1, int fVerbose )
+{
+ Cec_ParCec_t ParsCec, * pPars = &ParsCec;
+ Gia_Man_t * pMiter;
+ int RetValue;
+ Cec_ManCecSetDefaultParams( pPars );
+ pPars->fVerbose = fVerbose;
+ pMiter = Gia_ManMiter( p0, p1, 1, 0, pPars->fVerbose );
+ if ( pMiter == NULL )
+ return -1;
+ RetValue = Cec_ManVerify( pMiter, pPars );
+ p0->pCexComb = pMiter->pCexComb; pMiter->pCexComb = NULL;
+ Gia_ManStop( pMiter );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [New CEC engine applied to two circuits.]
+
+ Description [Returns 1 if equivalent, 0 if counter-example, -1 if undecided.
+ Counter-example is returned in the first manager as pAig0->pSeqModel.
+ The format is given in Abc_Cex_t (file "abc\src\aig\gia\gia.h").]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManVerifyTwoAigs( Aig_Man_t * pAig0, Aig_Man_t * pAig1, int fVerbose )
+{
+ Gia_Man_t * p0, * p1, * pTemp;
+ int RetValue;
+
+ p0 = Gia_ManFromAig( pAig0 );
+ p0 = Gia_ManCleanup( pTemp = p0 );
+ Gia_ManStop( pTemp );
+
+ p1 = Gia_ManFromAig( pAig1 );
+ p1 = Gia_ManCleanup( pTemp = p1 );
+ Gia_ManStop( pTemp );
+
+ RetValue = Cec_ManVerifyTwo( p0, p1, fVerbose );
+ pAig0->pSeqModel = p0->pCexComb; p0->pCexComb = NULL;
+ Gia_ManStop( p0 );
+ Gia_ManStop( p1 );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implementation of new signal correspodence.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Cec_LatchCorrespondence( Aig_Man_t * pAig, int nConfs, int fUseCSat )
+{
+ Gia_Man_t * pGia;
+ Cec_ParCor_t CorPars, * pCorPars = &CorPars;
+ Cec_ManCorSetDefaultParams( pCorPars );
+ pCorPars->fLatchCorr = 1;
+ pCorPars->fUseCSat = fUseCSat;
+ pCorPars->nBTLimit = nConfs;
+ pGia = Gia_ManFromAigSimple( pAig );
+ Cec_ManLSCorrespondenceClasses( pGia, pCorPars );
+ Gia_ManReprToAigRepr( pAig, pGia );
+ Gia_ManStop( pGia );
+ return Aig_ManDupSimple( pAig );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implementation of new signal correspodence.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Cec_SignalCorrespondence( Aig_Man_t * pAig, int nConfs, int fUseCSat )
+{
+ Gia_Man_t * pGia;
+ Cec_ParCor_t CorPars, * pCorPars = &CorPars;
+ Cec_ManCorSetDefaultParams( pCorPars );
+ pCorPars->fUseCSat = fUseCSat;
+ pCorPars->nBTLimit = nConfs;
+ pGia = Gia_ManFromAigSimple( pAig );
+ Cec_ManLSCorrespondenceClasses( pGia, pCorPars );
+ Gia_ManReprToAigRepr( pAig, pGia );
+ Gia_ManStop( pGia );
+ return Aig_ManDupSimple( pAig );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implementation of fraiging.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Cec_FraigCombinational( Aig_Man_t * pAig, int nConfs, int fVerbose )
+{
+ Gia_Man_t * pGia;
+ Cec_ParFra_t FraPars, * pFraPars = &FraPars;
+ Cec_ManFraSetDefaultParams( pFraPars );
+ pFraPars->fSatSweeping = 1;
+ pFraPars->nBTLimit = nConfs;
+ pFraPars->nItersMax = 20;
+ pFraPars->fVerbose = fVerbose;
+ pGia = Gia_ManFromAigSimple( pAig );
+ Cec_ManSatSweeping( pGia, pFraPars );
+ Gia_ManReprToAigRepr( pAig, pGia );
+ Gia_ManStop( pGia );
+ return Aig_ManDupSimple( pAig );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/cec/cecChoice.c b/src/proof/cec/cecChoice.c
new file mode 100644
index 00000000..3ddb975e
--- /dev/null
+++ b/src/proof/cec/cecChoice.c
@@ -0,0 +1,409 @@
+/**CFile****************************************************************
+
+ FileName [cecChoice.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Combinational equivalence checking.]
+
+ Synopsis [Computation of structural choices.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cecChoice.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+#include "src/aig/gia/giaAig.h"
+#include "src/proof/dch/dch.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Cec_ManCombSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj );
+
+extern int Cec_ManResimulateCounterExamplesComb( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore );
+extern int Gia_ManCheckRefinements( Gia_Man_t * p, Vec_Str_t * vStatus, Vec_Int_t * vOutputs, Cec_ManSim_t * pSim, int fRings );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes the real value of the literal w/o spec reduction.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Cec_ManCombSpecReal( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+ assert( Gia_ObjIsAnd(pObj) );
+ Cec_ManCombSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj) );
+ Cec_ManCombSpecReduce_rec( pNew, p, Gia_ObjFanin1(pObj) );
+ return Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively performs speculative reduction for the object.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManCombSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+ Gia_Obj_t * pRepr;
+ if ( ~pObj->Value )
+ return;
+ if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) )
+ {
+ Cec_ManCombSpecReduce_rec( pNew, p, pRepr );
+ pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) );
+ return;
+ }
+ pObj->Value = Cec_ManCombSpecReal( pNew, p, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives SRM for signal correspondence.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Gia_Man_t * Cec_ManCombSpecReduce( Gia_Man_t * p, Vec_Int_t ** pvOutputs, int fRings )
+{
+ Gia_Man_t * pNew, * pTemp;
+ Gia_Obj_t * pObj, * pRepr;
+ Vec_Int_t * vXorLits;
+ int i, iPrev, iObj, iPrevNew, iObjNew;
+ assert( p->pReprs != NULL );
+ Gia_ManSetPhase( p );
+ Gia_ManFillValue( p );
+ pNew = Gia_ManStart( Gia_ManObjNum(p) );
+ pNew->pName = Abc_UtilStrsav( p->pName );
+ Gia_ManHashAlloc( pNew );
+ Gia_ManConst0(p)->Value = 0;
+ Gia_ManForEachCi( p, pObj, i )
+ pObj->Value = Gia_ManAppendCi(pNew);
+ *pvOutputs = Vec_IntAlloc( 1000 );
+ vXorLits = Vec_IntAlloc( 1000 );
+ if ( fRings )
+ {
+ Gia_ManForEachObj1( p, pObj, i )
+ {
+ if ( Gia_ObjIsConst( p, i ) )
+ {
+ iObjNew = Cec_ManCombSpecReal( pNew, p, pObj );
+ iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pObj) );
+ if ( iObjNew != 0 )
+ {
+ Vec_IntPush( *pvOutputs, 0 );
+ Vec_IntPush( *pvOutputs, i );
+ Vec_IntPush( vXorLits, iObjNew );
+ }
+ }
+ else if ( Gia_ObjIsHead( p, i ) )
+ {
+ iPrev = i;
+ Gia_ClassForEachObj1( p, i, iObj )
+ {
+ iPrevNew = Cec_ManCombSpecReal( pNew, p, Gia_ManObj(p, iPrev) );
+ iObjNew = Cec_ManCombSpecReal( pNew, p, Gia_ManObj(p, iObj) );
+ iPrevNew = Abc_LitNotCond( iPrevNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) );
+ iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) );
+ if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 )
+ {
+ Vec_IntPush( *pvOutputs, iPrev );
+ Vec_IntPush( *pvOutputs, iObj );
+ Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Abc_LitNot(iObjNew)) );
+ }
+ iPrev = iObj;
+ }
+ iObj = i;
+ iPrevNew = Cec_ManCombSpecReal( pNew, p, Gia_ManObj(p, iPrev) );
+ iObjNew = Cec_ManCombSpecReal( pNew, p, Gia_ManObj(p, iObj) );
+ iPrevNew = Abc_LitNotCond( iPrevNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) );
+ iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) );
+ if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 )
+ {
+ Vec_IntPush( *pvOutputs, iPrev );
+ Vec_IntPush( *pvOutputs, iObj );
+ Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Abc_LitNot(iObjNew)) );
+ }
+ }
+ }
+ }
+ else
+ {
+ Gia_ManForEachObj1( p, pObj, i )
+ {
+ pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) );
+ if ( pRepr == NULL )
+ continue;
+ iPrevNew = Gia_ObjIsConst(p, i)? 0 : Cec_ManCombSpecReal( pNew, p, pRepr );
+ iObjNew = Cec_ManCombSpecReal( pNew, p, pObj );
+ iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) );
+ if ( iPrevNew != iObjNew )
+ {
+ Vec_IntPush( *pvOutputs, Gia_ObjId(p, pRepr) );
+ Vec_IntPush( *pvOutputs, Gia_ObjId(p, pObj) );
+ Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, iPrevNew, iObjNew) );
+ }
+ }
+ }
+ Vec_IntForEachEntry( vXorLits, iObjNew, i )
+ Gia_ManAppendCo( pNew, iObjNew );
+ Vec_IntFree( vXorLits );
+ Gia_ManHashStop( pNew );
+//Abc_Print( 1, "Before sweeping = %d\n", Gia_ManAndNum(pNew) );
+ pNew = Gia_ManCleanup( pTemp = pNew );
+//Abc_Print( 1, "After sweeping = %d\n", Gia_ManAndNum(pNew) );
+ Gia_ManStop( pTemp );
+ return pNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManChoiceComputation_int( Gia_Man_t * pAig, Cec_ParChc_t * pPars )
+{
+ int nItersMax = 1000;
+ Vec_Str_t * vStatus;
+ Vec_Int_t * vOutputs;
+ Vec_Int_t * vCexStore;
+ Cec_ParSim_t ParsSim, * pParsSim = &ParsSim;
+ Cec_ParSat_t ParsSat, * pParsSat = &ParsSat;
+ Cec_ManSim_t * pSim;
+ Gia_Man_t * pSrm;
+ int r, RetValue;
+ int clkSat = 0, clkSim = 0, clkSrm = 0, clkTotal = clock();
+ int clk2, clk = clock();
+ ABC_FREE( pAig->pReprs );
+ ABC_FREE( pAig->pNexts );
+ Gia_ManRandom( 1 );
+ // prepare simulation manager
+ Cec_ManSimSetDefaultParams( pParsSim );
+ pParsSim->nWords = pPars->nWords;
+ pParsSim->nFrames = pPars->nRounds;
+ pParsSim->fVerbose = pPars->fVerbose;
+ pParsSim->fLatchCorr = 0;
+ pParsSim->fSeqSimulate = 0;
+ // create equivalence classes of registers
+ pSim = Cec_ManSimStart( pAig, pParsSim );
+ Cec_ManSimClassesPrepare( pSim, -1 );
+ Cec_ManSimClassesRefine( pSim );
+ // prepare SAT solving
+ Cec_ManSatSetDefaultParams( pParsSat );
+ pParsSat->nBTLimit = pPars->nBTLimit;
+ pParsSat->fVerbose = pPars->fVerbose;
+ if ( pPars->fVerbose )
+ {
+ Abc_Print( 1, "Obj = %7d. And = %7d. Conf = %5d. Ring = %d. CSat = %d.\n",
+ Gia_ManObjNum(pAig), Gia_ManAndNum(pAig), pPars->nBTLimit, pPars->fUseRings, pPars->fUseCSat );
+ Cec_ManRefinedClassPrintStats( pAig, NULL, 0, clock() - clk );
+ }
+ // perform refinement of equivalence classes
+ for ( r = 0; r < nItersMax; r++ )
+ {
+ clk = clock();
+ // perform speculative reduction
+ clk2 = clock();
+ pSrm = Cec_ManCombSpecReduce( pAig, &vOutputs, pPars->fUseRings );
+ assert( Gia_ManRegNum(pSrm) == 0 && Gia_ManCiNum(pSrm) == Gia_ManCiNum(pAig) );
+ clkSrm += clock() - clk2;
+ if ( Gia_ManCoNum(pSrm) == 0 )
+ {
+ if ( pPars->fVerbose )
+ Cec_ManRefinedClassPrintStats( pAig, NULL, r+1, clock() - clk );
+ Vec_IntFree( vOutputs );
+ Gia_ManStop( pSrm );
+ break;
+ }
+//Gia_DumpAiger( pSrm, "choicesrm", r, 2 );
+ // found counter-examples to speculation
+ clk2 = clock();
+ if ( pPars->fUseCSat )
+ vCexStore = Cbs_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0 );
+ else
+ vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus );
+ Gia_ManStop( pSrm );
+ clkSat += clock() - clk2;
+ if ( Vec_IntSize(vCexStore) == 0 )
+ {
+ if ( pPars->fVerbose )
+ Cec_ManRefinedClassPrintStats( pAig, vStatus, r+1, clock() - clk );
+ Vec_IntFree( vCexStore );
+ Vec_StrFree( vStatus );
+ Vec_IntFree( vOutputs );
+ break;
+ }
+ // refine classes with these counter-examples
+ clk2 = clock();
+ RetValue = Cec_ManResimulateCounterExamplesComb( pSim, vCexStore );
+ Vec_IntFree( vCexStore );
+ clkSim += clock() - clk2;
+ Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings );
+ if ( pPars->fVerbose )
+ Cec_ManRefinedClassPrintStats( pAig, vStatus, r+1, clock() - clk );
+ Vec_StrFree( vStatus );
+ Vec_IntFree( vOutputs );
+//Gia_ManEquivPrintClasses( pAig, 1, 0 );
+ }
+ // check the overflow
+ if ( r == nItersMax )
+ Abc_Print( 1, "The refinement was not finished. The result may be incorrect.\n" );
+ Cec_ManSimStop( pSim );
+ clkTotal = clock() - clkTotal;
+ // report the results
+ if ( pPars->fVerbose )
+ {
+ Abc_PrintTimeP( 1, "Srm ", clkSrm, clkTotal );
+ Abc_PrintTimeP( 1, "Sat ", clkSat, clkTotal );
+ Abc_PrintTimeP( 1, "Sim ", clkSim, clkTotal );
+ Abc_PrintTimeP( 1, "Other", clkTotal-clkSat-clkSrm-clkSim, clkTotal );
+ Abc_PrintTime( 1, "TOTAL", clkTotal );
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes choices for the vector of AIGs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Gia_Man_t * Cec_ManChoiceComputationVec( Gia_Man_t * pGia, int nGias, Cec_ParChc_t * pPars )
+{
+ Gia_Man_t * pNew;
+ int RetValue;
+ // compute equivalences of the miter
+// pMiter = Gia_ManChoiceMiter( vGias );
+// Gia_ManSetRegNum( pMiter, 0 );
+ RetValue = Cec_ManChoiceComputation_int( pGia, pPars );
+ // derive AIG with choices
+ pNew = Gia_ManEquivToChoices( pGia, nGias );
+ Gia_ManHasChoices( pNew );
+// Gia_ManStop( pMiter );
+ // report the results
+ if ( pPars->fVerbose )
+ {
+// Abc_Print( 1, "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n",
+// Gia_ManAndNum(pAig), Gia_ManAndNum(pNew),
+// 100.0*(Gia_ManAndNum(pAig)-Gia_ManAndNum(pNew))/(Gia_ManAndNum(pAig)?Gia_ManAndNum(pAig):1),
+// Gia_ManRegNum(pAig), Gia_ManRegNum(pNew),
+// 100.0*(Gia_ManRegNum(pAig)-Gia_ManRegNum(pNew))/(Gia_ManRegNum(pAig)?Gia_ManRegNum(pAig):1) );
+ }
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes choices for one AIGs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Gia_Man_t * Cec_ManChoiceComputation( Gia_Man_t * pAig, Cec_ParChc_t * pParsChc )
+{
+// extern Aig_Man_t * Dar_ManChoiceNew( Aig_Man_t * pAig, Dch_Pars_t * pPars );
+ Dch_Pars_t Pars, * pPars = &Pars;
+ Aig_Man_t * pMan, * pManNew;
+ Gia_Man_t * pGia;
+ if ( 0 )
+ {
+ pGia = Cec_ManChoiceComputationVec( pAig, 3, pParsChc );
+ }
+ else
+ {
+ pMan = Gia_ManToAig( pAig, 0 );
+ Dch_ManSetDefaultParams( pPars );
+ pPars->fUseGia = 1;
+ pPars->nBTLimit = pParsChc->nBTLimit;
+ pPars->fUseCSat = pParsChc->fUseCSat;
+ pPars->fVerbose = pParsChc->fVerbose;
+ pManNew = Dar_ManChoiceNew( pMan, pPars );
+ pGia = Gia_ManFromAig( pManNew );
+ Aig_ManStop( pManNew );
+// Aig_ManStop( pMan );
+ }
+ return pGia;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs computation of AIGs with choices.]
+
+ Description [Takes several AIGs and performs choicing.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Cec_ComputeChoices( Gia_Man_t * pGia, Dch_Pars_t * pPars )
+{
+ Cec_ParChc_t ParsChc, * pParsChc = &ParsChc;
+ Aig_Man_t * pAig;
+ if ( pPars->fVerbose )
+ Abc_PrintTime( 1, "Synthesis time", pPars->timeSynth );
+ Cec_ManChcSetDefaultParams( pParsChc );
+ pParsChc->nBTLimit = pPars->nBTLimit;
+ pParsChc->fUseCSat = pPars->fUseCSat;
+ if ( pParsChc->fUseCSat && pParsChc->nBTLimit > 100 )
+ pParsChc->nBTLimit = 100;
+ pParsChc->fVerbose = pPars->fVerbose;
+ pGia = Cec_ManChoiceComputationVec( pGia, 3, pParsChc );
+ Gia_ManSetRegNum( pGia, Gia_ManRegNum(pGia) );
+ pAig = Gia_ManToAig( pGia, 1 );
+ Gia_ManStop( pGia );
+ return pAig;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/cec/cecClass.c b/src/proof/cec/cecClass.c
new file mode 100644
index 00000000..46e585a9
--- /dev/null
+++ b/src/proof/cec/cecClass.c
@@ -0,0 +1,931 @@
+/**CFile****************************************************************
+
+ FileName [cecClass.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Combinational equivalence checking.]
+
+ Synopsis [Equivalence class refinement.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cecClass.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static inline unsigned * Cec_ObjSim( Cec_ManSim_t * p, int Id ) { return p->pMems + p->pSimInfo[Id] + 1; }
+static inline void Cec_ObjSetSim( Cec_ManSim_t * p, int Id, int n ) { p->pSimInfo[Id] = n; }
+
+static inline float Cec_MemUsage( Cec_ManSim_t * p ) { return 1.0*p->nMemsMax*(p->pPars->nWords+1)/(1<<20); }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Compares simulation info of one node with constant 0.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManSimCompareConst( unsigned * p, int nWords )
+{
+ int w;
+ if ( p[0] & 1 )
+ {
+ for ( w = 0; w < nWords; w++ )
+ if ( p[w] != ~0 )
+ return 0;
+ return 1;
+ }
+ else
+ {
+ for ( w = 0; w < nWords; w++ )
+ if ( p[w] != 0 )
+ return 0;
+ return 1;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares simulation info of two nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManSimCompareEqual( unsigned * p0, unsigned * p1, int nWords )
+{
+ int w;
+ if ( (p0[0] & 1) == (p1[0] & 1) )
+ {
+ for ( w = 0; w < nWords; w++ )
+ if ( p0[w] != p1[w] )
+ return 0;
+ return 1;
+ }
+ else
+ {
+ for ( w = 0; w < nWords; w++ )
+ if ( p0[w] != ~p1[w] )
+ return 0;
+ return 1;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of the first non-equal bit.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManSimCompareConstFirstBit( unsigned * p, int nWords )
+{
+ int w;
+ if ( p[0] & 1 )
+ {
+ for ( w = 0; w < nWords; w++ )
+ if ( p[w] != ~0 )
+ return 32*w + Gia_WordFindFirstBit( ~p[w] );
+ return -1;
+ }
+ else
+ {
+ for ( w = 0; w < nWords; w++ )
+ if ( p[w] != 0 )
+ return 32*w + Gia_WordFindFirstBit( p[w] );
+ return -1;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares simulation info of two nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManSimCompareEqualFirstBit( unsigned * p0, unsigned * p1, int nWords )
+{
+ int w;
+ if ( (p0[0] & 1) == (p1[0] & 1) )
+ {
+ for ( w = 0; w < nWords; w++ )
+ if ( p0[w] != p1[w] )
+ return 32*w + Gia_WordFindFirstBit( p0[w] ^ p1[w] );
+ return -1;
+ }
+ else
+ {
+ for ( w = 0; w < nWords; w++ )
+ if ( p0[w] != ~p1[w] )
+ return 32*w + Gia_WordFindFirstBit( p0[w] ^ ~p1[w] );
+ return -1;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of the first non-equal bit.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManSimCompareConstScore( unsigned * p, int nWords, int * pScores )
+{
+ int w, b;
+ if ( p[0] & 1 )
+ {
+ for ( w = 0; w < nWords; w++ )
+ if ( p[w] != ~0 )
+ for ( b = 0; b < 32; b++ )
+ if ( ((~p[w]) >> b ) & 1 )
+ pScores[32*w + b]++;
+ }
+ else
+ {
+ for ( w = 0; w < nWords; w++ )
+ if ( p[w] != 0 )
+ for ( b = 0; b < 32; b++ )
+ if ( ((p[w]) >> b ) & 1 )
+ pScores[32*w + b]++;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares simulation info of two nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManSimCompareEqualScore( unsigned * p0, unsigned * p1, int nWords, int * pScores )
+{
+ int w, b;
+ if ( (p0[0] & 1) == (p1[0] & 1) )
+ {
+ for ( w = 0; w < nWords; w++ )
+ if ( p0[w] != p1[w] )
+ for ( b = 0; b < 32; b++ )
+ if ( ((p0[w] ^ p1[w]) >> b ) & 1 )
+ pScores[32*w + b]++;
+ }
+ else
+ {
+ for ( w = 0; w < nWords; w++ )
+ if ( p0[w] != ~p1[w] )
+ for ( b = 0; b < 32; b++ )
+ if ( ((p0[w] ^ ~p1[w]) >> b ) & 1 )
+ pScores[32*w + b]++;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates equivalence class.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManSimClassCreate( Gia_Man_t * p, Vec_Int_t * vClass )
+{
+ int Repr = GIA_VOID, EntPrev = -1, Ent, i;
+ assert( Vec_IntSize(vClass) > 0 );
+ Vec_IntForEachEntry( vClass, Ent, i )
+ {
+ if ( i == 0 )
+ {
+ Repr = Ent;
+ Gia_ObjSetRepr( p, Ent, GIA_VOID );
+ EntPrev = Ent;
+ }
+ else
+ {
+ assert( Repr < Ent );
+ Gia_ObjSetRepr( p, Ent, Repr );
+ Gia_ObjSetNext( p, EntPrev, Ent );
+ EntPrev = Ent;
+ }
+ }
+ Gia_ObjSetNext( p, EntPrev, 0 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Refines one equivalence class.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManSimClassRefineOne( Cec_ManSim_t * p, int i )
+{
+ unsigned * pSim0, * pSim1;
+ int Ent;
+ Vec_IntClear( p->vClassOld );
+ Vec_IntClear( p->vClassNew );
+ Vec_IntPush( p->vClassOld, i );
+ pSim0 = Cec_ObjSim(p, i);
+ Gia_ClassForEachObj1( p->pAig, i, Ent )
+ {
+ pSim1 = Cec_ObjSim(p, Ent);
+ if ( Cec_ManSimCompareEqual( pSim0, pSim1, p->nWords ) )
+ Vec_IntPush( p->vClassOld, Ent );
+ else
+ {
+ Vec_IntPush( p->vClassNew, Ent );
+ if ( p->pBestState )
+ Cec_ManSimCompareEqualScore( pSim0, pSim1, p->nWords, p->pScores );
+ }
+ }
+ if ( Vec_IntSize( p->vClassNew ) == 0 )
+ return 0;
+ Cec_ManSimClassCreate( p->pAig, p->vClassOld );
+ Cec_ManSimClassCreate( p->pAig, p->vClassNew );
+ if ( Vec_IntSize(p->vClassNew) > 1 )
+ return 1 + Cec_ManSimClassRefineOne( p, Vec_IntEntry(p->vClassNew,0) );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Refines one equivalence class.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManSimClassRemoveOne( Cec_ManSim_t * p, int i )
+{
+ int iRepr, Ent;
+ if ( Gia_ObjIsConst(p->pAig, i) )
+ {
+ Gia_ObjSetRepr( p->pAig, i, GIA_VOID );
+ return 1;
+ }
+ if ( !Gia_ObjIsClass(p->pAig, i) )
+ return 0;
+ assert( Gia_ObjIsClass(p->pAig, i) );
+ iRepr = Gia_ObjRepr( p->pAig, i );
+ if ( iRepr == GIA_VOID )
+ iRepr = i;
+ // collect nodes
+ Vec_IntClear( p->vClassOld );
+ Vec_IntClear( p->vClassNew );
+ Gia_ClassForEachObj( p->pAig, iRepr, Ent )
+ {
+ if ( Ent == i )
+ Vec_IntPush( p->vClassNew, Ent );
+ else
+ Vec_IntPush( p->vClassOld, Ent );
+ }
+ assert( Vec_IntSize( p->vClassNew ) == 1 );
+ Cec_ManSimClassCreate( p->pAig, p->vClassOld );
+ Cec_ManSimClassCreate( p->pAig, p->vClassNew );
+ assert( !Gia_ObjIsClass(p->pAig, i) );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes hash key of the simuation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManSimHashKey( unsigned * pSim, int nWords, int nTableSize )
+{
+ static int s_Primes[16] = {
+ 1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177,
+ 4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 };
+ unsigned uHash = 0;
+ int i;
+ if ( pSim[0] & 1 )
+ for ( i = 0; i < nWords; i++ )
+ uHash ^= ~pSim[i] * s_Primes[i & 0xf];
+ else
+ for ( i = 0; i < nWords; i++ )
+ uHash ^= pSim[i] * s_Primes[i & 0xf];
+ return (int)(uHash % nTableSize);
+
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resets pointers to the simulation memory.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManSimMemRelink( Cec_ManSim_t * p )
+{
+ unsigned * pPlace, Ent;
+ pPlace = (unsigned *)&p->MemFree;
+ for ( Ent = p->nMems * (p->nWords + 1);
+ Ent + p->nWords + 1 < (unsigned)p->nWordsAlloc;
+ Ent += p->nWords + 1 )
+ {
+ *pPlace = Ent;
+ pPlace = p->pMems + Ent;
+ }
+ *pPlace = 0;
+ p->nWordsOld = p->nWords;
+}
+
+/**Function*************************************************************
+
+ Synopsis [References simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Cec_ManSimSimRef( Cec_ManSim_t * p, int i )
+{
+ unsigned * pSim;
+ assert( p->pSimInfo[i] == 0 );
+ if ( p->MemFree == 0 )
+ {
+ if ( p->nWordsAlloc == 0 )
+ {
+ assert( p->pMems == NULL );
+ p->nWordsAlloc = (1<<17); // -> 1Mb
+ p->nMems = 1;
+ }
+ p->nWordsAlloc *= 2;
+ p->pMems = ABC_REALLOC( unsigned, p->pMems, p->nWordsAlloc );
+ Cec_ManSimMemRelink( p );
+ }
+ p->pSimInfo[i] = p->MemFree;
+ pSim = p->pMems + p->MemFree;
+ p->MemFree = pSim[0];
+ pSim[0] = Gia_ObjValue( Gia_ManObj(p->pAig, i) );
+ p->nMems++;
+ if ( p->nMemsMax < p->nMems )
+ p->nMemsMax = p->nMems;
+ return pSim;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Dereferences simulaton info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Cec_ManSimSimDeref( Cec_ManSim_t * p, int i )
+{
+ unsigned * pSim;
+ assert( p->pSimInfo[i] > 0 );
+ pSim = p->pMems + p->pSimInfo[i];
+ if ( --pSim[0] == 0 )
+ {
+ pSim[0] = p->MemFree;
+ p->MemFree = p->pSimInfo[i];
+ p->pSimInfo[i] = 0;
+ p->nMems--;
+ }
+ return pSim;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Refines nodes belonging to candidate constant class.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManSimProcessRefined( Cec_ManSim_t * p, Vec_Int_t * vRefined )
+{
+ unsigned * pSim;
+ int * pTable, nTableSize, i, k, Key;
+ if ( Vec_IntSize(vRefined) == 0 )
+ return;
+ nTableSize = Abc_PrimeCudd( 100 + Vec_IntSize(vRefined) / 3 );
+ pTable = ABC_CALLOC( int, nTableSize );
+ Vec_IntForEachEntry( vRefined, i, k )
+ {
+ pSim = Cec_ObjSim( p, i );
+ assert( !Cec_ManSimCompareConst( pSim, p->nWords ) );
+ Key = Cec_ManSimHashKey( pSim, p->nWords, nTableSize );
+ if ( pTable[Key] == 0 )
+ {
+ assert( Gia_ObjRepr(p->pAig, i) == 0 );
+ assert( Gia_ObjNext(p->pAig, i) == 0 );
+ Gia_ObjSetRepr( p->pAig, i, GIA_VOID );
+ }
+ else
+ {
+ Gia_ObjSetNext( p->pAig, pTable[Key], i );
+ Gia_ObjSetRepr( p->pAig, i, Gia_ObjRepr(p->pAig, pTable[Key]) );
+ if ( Gia_ObjRepr(p->pAig, i) == GIA_VOID )
+ Gia_ObjSetRepr( p->pAig, i, pTable[Key] );
+ assert( Gia_ObjRepr(p->pAig, i) > 0 );
+ }
+ pTable[Key] = i;
+ }
+ Vec_IntForEachEntry( vRefined, i, k )
+ {
+ if ( Gia_ObjIsHead( p->pAig, i ) )
+ Cec_ManSimClassRefineOne( p, i );
+ }
+ Vec_IntForEachEntry( vRefined, i, k )
+ Cec_ManSimSimDeref( p, i );
+ ABC_FREE( pTable );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Saves the input pattern with the given number.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManSimSavePattern( Cec_ManSim_t * p, int iPat )
+{
+ unsigned * pInfo;
+ int i;
+ assert( p->pCexComb == NULL );
+ assert( iPat >= 0 && iPat < 32 * p->nWords );
+ p->pCexComb = (Abc_Cex_t *)ABC_CALLOC( char,
+ sizeof(Abc_Cex_t) + sizeof(unsigned) * Abc_BitWordNum(Gia_ManCiNum(p->pAig)) );
+ p->pCexComb->iPo = p->iOut;
+ p->pCexComb->nPis = Gia_ManCiNum(p->pAig);
+ p->pCexComb->nBits = Gia_ManCiNum(p->pAig);
+ for ( i = 0; i < Gia_ManCiNum(p->pAig); i++ )
+ {
+ pInfo = (unsigned *)Vec_PtrEntry( p->vCiSimInfo, i );
+ if ( Abc_InfoHasBit( pInfo, iPat ) )
+ Abc_InfoSetBit( p->pCexComb->pData, i );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find the best pattern using the scores.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManSimFindBestPattern( Cec_ManSim_t * p )
+{
+ unsigned * pInfo;
+ int i, ScoreBest = 0, iPatBest = 1; // set the first pattern
+ // find the best pattern
+ for ( i = 0; i < 32 * p->nWords; i++ )
+ if ( ScoreBest < p->pScores[i] )
+ {
+ ScoreBest = p->pScores[i];
+ iPatBest = i;
+ }
+ // compare this with the available patterns - and save
+ if ( p->pBestState->iPo <= ScoreBest )
+ {
+ assert( p->pBestState->nRegs == Gia_ManRegNum(p->pAig) );
+ for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ )
+ {
+ pInfo = (unsigned *)Vec_PtrEntry( p->vCiSimInfo, Gia_ManPiNum(p->pAig) + i );
+ if ( Abc_InfoHasBit(p->pBestState->pData, i) != Abc_InfoHasBit(pInfo, iPatBest) )
+ Abc_InfoXorBit( p->pBestState->pData, i );
+ }
+ p->pBestState->iPo = ScoreBest;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if computation should stop.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManSimAnalyzeOutputs( Cec_ManSim_t * p )
+{
+ unsigned * pInfo, * pInfo2;
+ int i;
+ if ( !p->pPars->fCheckMiter )
+ return 0;
+ assert( p->vCoSimInfo != NULL );
+ // compare outputs with 0
+ if ( p->pPars->fDualOut )
+ {
+ assert( (Gia_ManPoNum(p->pAig) & 1) == 0 );
+ for ( i = 0; i < Gia_ManPoNum(p->pAig); i++ )
+ {
+ pInfo = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, i );
+ pInfo2 = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, ++i );
+ if ( !Cec_ManSimCompareEqual( pInfo, pInfo2, p->nWords ) )
+ {
+ if ( p->iOut == -1 )
+ {
+ p->iOut = i/2;
+ Cec_ManSimSavePattern( p, Cec_ManSimCompareEqualFirstBit(pInfo, pInfo2, p->nWords) );
+ }
+ if ( p->pCexes == NULL )
+ p->pCexes = ABC_CALLOC( void *, Gia_ManPoNum(p->pAig)/2 );
+ if ( p->pCexes[i/2] == NULL )
+ {
+ p->nOuts++;
+ p->pCexes[i/2] = (void *)1;
+ }
+ }
+ }
+ }
+ else
+ {
+ for ( i = 0; i < Gia_ManPoNum(p->pAig); i++ )
+ {
+ pInfo = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, i );
+ if ( !Cec_ManSimCompareConst( pInfo, p->nWords ) )
+ {
+ if ( p->iOut == -1 )
+ {
+ p->iOut = i;
+ Cec_ManSimSavePattern( p, Cec_ManSimCompareConstFirstBit(pInfo, p->nWords) );
+ }
+ if ( p->pCexes == NULL )
+ p->pCexes = ABC_CALLOC( void *, Gia_ManPoNum(p->pAig) );
+ if ( p->pCexes[i] == NULL )
+ {
+ p->nOuts++;
+ p->pCexes[i] = (void *)1;
+ }
+ }
+ }
+ }
+ return p->pCexes != NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one round.]
+
+ Description [Returns the number of PO entry if failed; 0 otherwise.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManSimSimulateRound( Cec_ManSim_t * p, Vec_Ptr_t * vInfoCis, Vec_Ptr_t * vInfoCos )
+{
+ Gia_Obj_t * pObj;
+ unsigned * pRes0, * pRes1, * pRes;
+ int i, k, w, Ent, iCiId = 0, iCoId = 0;
+ // prepare internal storage
+ if ( p->nWordsOld != p->nWords )
+ Cec_ManSimMemRelink( p );
+ p->nMemsMax = 0;
+ // allocate score counters
+ ABC_FREE( p->pScores );
+ if ( p->pBestState )
+ p->pScores = ABC_CALLOC( int, 32 * p->nWords );
+ // simulate nodes
+ Vec_IntClear( p->vRefinedC );
+ if ( Gia_ObjValue(Gia_ManConst0(p->pAig)) )
+ {
+ pRes = Cec_ManSimSimRef( p, 0 );
+ for ( w = 1; w <= p->nWords; w++ )
+ pRes[w] = 0;
+ }
+ Gia_ManForEachObj1( p->pAig, pObj, i )
+ {
+ if ( Gia_ObjIsCi(pObj) )
+ {
+ if ( Gia_ObjValue(pObj) == 0 )
+ {
+ iCiId++;
+ continue;
+ }
+ pRes = Cec_ManSimSimRef( p, i );
+ if ( vInfoCis )
+ {
+ pRes0 = (unsigned *)Vec_PtrEntry( vInfoCis, iCiId++ );
+ for ( w = 1; w <= p->nWords; w++ )
+ pRes[w] = pRes0[w-1];
+ }
+ else
+ {
+ for ( w = 1; w <= p->nWords; w++ )
+ pRes[w] = Gia_ManRandom( 0 );
+ }
+ // make sure the first pattern is always zero
+ pRes[1] ^= (pRes[1] & 1);
+ goto references;
+ }
+ if ( Gia_ObjIsCo(pObj) ) // co always has non-zero 1st fanin and zero 2nd fanin
+ {
+ pRes0 = Cec_ManSimSimDeref( p, Gia_ObjFaninId0(pObj,i) );
+ if ( vInfoCos )
+ {
+ pRes = (unsigned *)Vec_PtrEntry( vInfoCos, iCoId++ );
+ if ( Gia_ObjFaninC0(pObj) )
+ for ( w = 1; w <= p->nWords; w++ )
+ pRes[w-1] = ~pRes0[w];
+ else
+ for ( w = 1; w <= p->nWords; w++ )
+ pRes[w-1] = pRes0[w];
+ }
+ continue;
+ }
+ assert( Gia_ObjValue(pObj) );
+ pRes = Cec_ManSimSimRef( p, i );
+ pRes0 = Cec_ManSimSimDeref( p, Gia_ObjFaninId0(pObj,i) );
+ pRes1 = Cec_ManSimSimDeref( p, Gia_ObjFaninId1(pObj,i) );
+
+// Abc_Print( 1, "%d,%d ", Gia_ObjValue( Gia_ObjFanin0(pObj) ), Gia_ObjValue( Gia_ObjFanin1(pObj) ) );
+
+ if ( Gia_ObjFaninC0(pObj) )
+ {
+ if ( Gia_ObjFaninC1(pObj) )
+ for ( w = 1; w <= p->nWords; w++ )
+ pRes[w] = ~(pRes0[w] | pRes1[w]);
+ else
+ for ( w = 1; w <= p->nWords; w++ )
+ pRes[w] = ~pRes0[w] & pRes1[w];
+ }
+ else
+ {
+ if ( Gia_ObjFaninC1(pObj) )
+ for ( w = 1; w <= p->nWords; w++ )
+ pRes[w] = pRes0[w] & ~pRes1[w];
+ else
+ for ( w = 1; w <= p->nWords; w++ )
+ pRes[w] = pRes0[w] & pRes1[w];
+ }
+
+references:
+ // if this node is candidate constant, collect it
+ if ( Gia_ObjIsConst(p->pAig, i) && !Cec_ManSimCompareConst(pRes + 1, p->nWords) )
+ {
+ pRes[0]++;
+ Vec_IntPush( p->vRefinedC, i );
+ if ( p->pBestState )
+ Cec_ManSimCompareConstScore( pRes + 1, p->nWords, p->pScores );
+ }
+ // if the node belongs to a class, save it
+ if ( Gia_ObjIsClass(p->pAig, i) )
+ pRes[0]++;
+ // if this is the last node of the class, process it
+ if ( Gia_ObjIsTail(p->pAig, i) )
+ {
+ Vec_IntClear( p->vClassTemp );
+ Gia_ClassForEachObj( p->pAig, Gia_ObjRepr(p->pAig, i), Ent )
+ Vec_IntPush( p->vClassTemp, Ent );
+ Cec_ManSimClassRefineOne( p, Gia_ObjRepr(p->pAig, i) );
+ Vec_IntForEachEntry( p->vClassTemp, Ent, k )
+ Cec_ManSimSimDeref( p, Ent );
+ }
+ }
+
+ if ( p->pPars->fConstCorr )
+ {
+ Vec_IntForEachEntry( p->vRefinedC, i, k )
+ {
+ Gia_ObjSetRepr( p->pAig, i, GIA_VOID );
+ Cec_ManSimSimDeref( p, i );
+ }
+ Vec_IntClear( p->vRefinedC );
+ }
+
+ if ( Vec_IntSize(p->vRefinedC) > 0 )
+ Cec_ManSimProcessRefined( p, p->vRefinedC );
+ assert( vInfoCis == NULL || iCiId == Gia_ManCiNum(p->pAig) );
+ assert( vInfoCos == NULL || iCoId == Gia_ManCoNum(p->pAig) );
+ assert( p->nMems == 1 );
+ if ( p->nMems != 1 )
+ Abc_Print( 1, "Cec_ManSimSimulateRound(): Memory management error!\n" );
+ if ( p->pPars->fVeryVerbose )
+ Gia_ManEquivPrintClasses( p->pAig, 0, Cec_MemUsage(p) );
+ if ( p->pBestState )
+ Cec_ManSimFindBestPattern( p );
+/*
+ if ( p->nMems > 1 ) {
+ for ( i = 1; i < p->nObjs; i++ )
+ if ( p->pSims[i] ) {
+ int x = 0;
+ }
+ }
+*/
+ return Cec_ManSimAnalyzeOutputs( p );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Creates simulation info for this round.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManSimCreateInfo( Cec_ManSim_t * p, Vec_Ptr_t * vInfoCis, Vec_Ptr_t * vInfoCos )
+{
+ unsigned * pRes0, * pRes1;
+ int i, w;
+ if ( p->pPars->fSeqSimulate && Gia_ManRegNum(p->pAig) > 0 )
+ {
+ assert( vInfoCis && vInfoCos );
+ for ( i = 0; i < Gia_ManPiNum(p->pAig); i++ )
+ {
+ pRes0 = (unsigned *)Vec_PtrEntry( vInfoCis, i );
+ for ( w = 0; w < p->nWords; w++ )
+ pRes0[w] = Gia_ManRandom( 0 );
+ }
+ for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ )
+ {
+ pRes0 = (unsigned *)Vec_PtrEntry( vInfoCis, Gia_ManPiNum(p->pAig) + i );
+ pRes1 = (unsigned *)Vec_PtrEntry( vInfoCos, Gia_ManPoNum(p->pAig) + i );
+ for ( w = 0; w < p->nWords; w++ )
+ pRes0[w] = pRes1[w];
+ }
+ }
+ else
+ {
+ for ( i = 0; i < Gia_ManCiNum(p->pAig); i++ )
+ {
+ pRes0 = (unsigned *)Vec_PtrEntry( vInfoCis, i );
+ for ( w = 0; w < p->nWords; w++ )
+ pRes0[w] = Gia_ManRandom( 0 );
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the bug is found.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManSimClassesPrepare( Cec_ManSim_t * p, int LevelMax )
+{
+ Gia_Obj_t * pObj;
+ int i;
+ assert( p->pAig->pReprs == NULL );
+ // allocate representation
+ p->pAig->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p->pAig) );
+ p->pAig->pNexts = ABC_CALLOC( int, Gia_ManObjNum(p->pAig) );
+ // create references
+ Gia_ManSetRefs( p->pAig );
+ // set starting representative of internal nodes to be constant 0
+ if ( p->pPars->fLatchCorr )
+ Gia_ManForEachObj( p->pAig, pObj, i )
+ Gia_ObjSetRepr( p->pAig, i, GIA_VOID );
+ else if ( LevelMax == -1 )
+ Gia_ManForEachObj( p->pAig, pObj, i )
+ Gia_ObjSetRepr( p->pAig, i, Gia_ObjIsAnd(pObj) ? 0 : GIA_VOID );
+ else
+ {
+ Gia_ManLevelNum( p->pAig );
+ Gia_ManForEachObj( p->pAig, pObj, i )
+ Gia_ObjSetRepr( p->pAig, i, (Gia_ObjIsAnd(pObj) && Gia_ObjLevel(p->pAig,pObj) <= LevelMax) ? 0 : GIA_VOID );
+ Vec_IntFreeP( &p->pAig->vLevels );
+ }
+ // if sequential simulation, set starting representative of ROs to be constant 0
+ if ( p->pPars->fSeqSimulate )
+ Gia_ManForEachRo( p->pAig, pObj, i )
+ if ( pObj->Value )
+ Gia_ObjSetRepr( p->pAig, Gia_ObjId(p->pAig, pObj), 0 );
+ // perform simulation
+ p->nWords = 1;
+ do {
+ if ( p->pPars->fVerbose )
+ Gia_ManEquivPrintClasses( p->pAig, 0, Cec_MemUsage(p) );
+ for ( i = 0; i < 4; i++ )
+ {
+ Cec_ManSimCreateInfo( p, p->vCiSimInfo, p->vCoSimInfo );
+ if ( Cec_ManSimSimulateRound( p, p->vCiSimInfo, p->vCoSimInfo ) )
+ return 1;
+ }
+ p->nWords = 2 * p->nWords + 1;
+ }
+ while ( p->nWords <= p->pPars->nWords );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the bug is found.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManSimClassesRefine( Cec_ManSim_t * p )
+{
+ int i;
+ Gia_ManSetRefs( p->pAig );
+ p->nWords = p->pPars->nWords;
+ for ( i = 0; i < p->pPars->nRounds; i++ )
+ {
+ if ( (i % (p->pPars->nRounds / 5)) == 0 && p->pPars->fVerbose )
+ Gia_ManEquivPrintClasses( p->pAig, 0, Cec_MemUsage(p) );
+ Cec_ManSimCreateInfo( p, p->vCiSimInfo, p->vCoSimInfo );
+ if ( Cec_ManSimSimulateRound( p, p->vCiSimInfo, p->vCoSimInfo ) )
+ return 1;
+ }
+ if ( p->pPars->fVerbose )
+ Gia_ManEquivPrintClasses( p->pAig, 0, Cec_MemUsage(p) );
+ return 0;
+}
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/cec/cecCore.c b/src/proof/cec/cecCore.c
new file mode 100644
index 00000000..bf41304b
--- /dev/null
+++ b/src/proof/cec/cecCore.c
@@ -0,0 +1,542 @@
+/**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 = 0; // 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->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 );
+// 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, clkTotal = 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", 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 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, clk, clk2;
+ double clkTotal = 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;
+
+ // 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 = 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 += clock() - clk;
+ // perform solving
+ for ( i = 1; i <= pPars->nItersMax; i++ )
+ {
+ clk2 = 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_WriteAiger( pSrm, "gia_srm.aig", 0, 0 );
+
+ if ( pPars->fVeryVerbose )
+ Gia_ManPrintStats( pSrm, 0 );
+ 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 = clock();
+ Cec_ManSatSolve( pPat, pSrm, pParsSat );
+p->timeSat += 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", 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 && ((double)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_WriteAiger( 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, clock() - (int)clkTotal );
+ Abc_PrintTimeP( 1, "Sat ", p->timeSat-pPat->timeTotalSave, clock() - (int)clkTotal );
+ Abc_PrintTimeP( 1, "Pat ", p->timePat+pPat->timeTotalSave, clock() - (int)clkTotal );
+ Abc_PrintTime( 1, "Time", (int)(clock() - clkTotal) );
+ }
+
+ pTemp = p->pAig; p->pAig = NULL;
+ if ( pTemp == NULL && pSim->iOut >= 0 )
+ {
+ 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 )
+ Abc_Print( 1, "Disproved %d outputs of the miter.\n", pSim->nOuts );
+ if ( fTimeOut )
+ Abc_Print( 1, "Timed out after %d seconds.\n", (int)((double)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
+
diff --git a/src/proof/cec/cecCorr.c b/src/proof/cec/cecCorr.c
new file mode 100644
index 00000000..6f3ce785
--- /dev/null
+++ b/src/proof/cec/cecCorr.c
@@ -0,0 +1,1137 @@
+/**CFile****************************************************************
+
+ FileName [cecCorr.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Combinational equivalence checking.]
+
+ Synopsis [Latch/signal correspondence computation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cecCorr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Gia_ManCorrSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes the real value of the literal w/o spec reduction.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Gia_ManCorrSpecReal( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix )
+{
+ if ( Gia_ObjIsAnd(pObj) )
+ {
+ Gia_ManCorrSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj), f, nPrefix );
+ Gia_ManCorrSpecReduce_rec( pNew, p, Gia_ObjFanin1(pObj), f, nPrefix );
+ return Gia_ManHashAnd( pNew, Gia_ObjFanin0CopyF(p, f, pObj), Gia_ObjFanin1CopyF(p, f, pObj) );
+ }
+ if ( f == 0 )
+ {
+ assert( Gia_ObjIsRo(p, pObj) );
+ return Gia_ObjCopyF(p, f, pObj);
+ }
+ assert( f && Gia_ObjIsRo(p, pObj) );
+ pObj = Gia_ObjRoToRi( p, pObj );
+ Gia_ManCorrSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj), f-1, nPrefix );
+ return Gia_ObjFanin0CopyF( p, f-1, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively performs speculative reduction for the object.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Gia_ManCorrSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix )
+{
+ Gia_Obj_t * pRepr;
+ int iLitNew;
+ if ( ~Gia_ObjCopyF(p, f, pObj) )
+ return;
+ if ( f >= nPrefix && (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) )
+ {
+ Gia_ManCorrSpecReduce_rec( pNew, p, pRepr, f, nPrefix );
+ iLitNew = Abc_LitNotCond( Gia_ObjCopyF(p, f, pRepr), Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) );
+ Gia_ObjSetCopyF( p, f, pObj, iLitNew );
+ return;
+ }
+ assert( Gia_ObjIsCand(pObj) );
+ iLitNew = Gia_ManCorrSpecReal( pNew, p, pObj, f, nPrefix );
+ Gia_ObjSetCopyF( p, f, pObj, iLitNew );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives SRM for signal correspondence.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManCorrSpecReduce( Gia_Man_t * p, int nFrames, int fScorr, Vec_Int_t ** pvOutputs, int fRings )
+{
+ Gia_Man_t * pNew, * pTemp;
+ Gia_Obj_t * pObj, * pRepr;
+ Vec_Int_t * vXorLits;
+ int f, i, iPrev, iObj, iPrevNew, iObjNew;
+ assert( nFrames > 0 );
+ assert( Gia_ManRegNum(p) > 0 );
+ assert( p->pReprs != NULL );
+ p->pCopies = ABC_FALLOC( int, (nFrames+fScorr)*Gia_ManObjNum(p) );
+ Gia_ManSetPhase( p );
+ pNew = Gia_ManStart( nFrames * Gia_ManObjNum(p) );
+ pNew->pName = Abc_UtilStrsav( p->pName );
+ Gia_ManHashAlloc( pNew );
+ Gia_ObjSetCopyF( p, 0, Gia_ManConst0(p), 0 );
+ Gia_ManForEachRo( p, pObj, i )
+ Gia_ObjSetCopyF( p, 0, pObj, Gia_ManAppendCi(pNew) );
+ Gia_ManForEachRo( p, pObj, i )
+ if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) )
+ Gia_ObjSetCopyF( p, 0, pObj, Gia_ObjCopyF(p, 0, pRepr) );
+ for ( f = 0; f < nFrames+fScorr; f++ )
+ {
+ Gia_ObjSetCopyF( p, f, Gia_ManConst0(p), 0 );
+ Gia_ManForEachPi( p, pObj, i )
+ Gia_ObjSetCopyF( p, f, pObj, Gia_ManAppendCi(pNew) );
+ }
+ *pvOutputs = Vec_IntAlloc( 1000 );
+ vXorLits = Vec_IntAlloc( 1000 );
+ if ( fRings )
+ {
+ Gia_ManForEachObj1( p, pObj, i )
+ {
+ if ( Gia_ObjIsConst( p, i ) )
+ {
+ iObjNew = Gia_ManCorrSpecReal( pNew, p, pObj, nFrames, 0 );
+ iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pObj) );
+ if ( iObjNew != 0 )
+ {
+ Vec_IntPush( *pvOutputs, 0 );
+ Vec_IntPush( *pvOutputs, i );
+ Vec_IntPush( vXorLits, iObjNew );
+ }
+ }
+ else if ( Gia_ObjIsHead( p, i ) )
+ {
+ iPrev = i;
+ Gia_ClassForEachObj1( p, i, iObj )
+ {
+ iPrevNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iPrev), nFrames, 0 );
+ iObjNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iObj), nFrames, 0 );
+ iPrevNew = Abc_LitNotCond( iPrevNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) );
+ iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) );
+ if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 )
+ {
+ Vec_IntPush( *pvOutputs, iPrev );
+ Vec_IntPush( *pvOutputs, iObj );
+ Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Abc_LitNot(iObjNew)) );
+ }
+ iPrev = iObj;
+ }
+ iObj = i;
+ iPrevNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iPrev), nFrames, 0 );
+ iObjNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iObj), nFrames, 0 );
+ iPrevNew = Abc_LitNotCond( iPrevNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) );
+ iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) );
+ if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 )
+ {
+ Vec_IntPush( *pvOutputs, iPrev );
+ Vec_IntPush( *pvOutputs, iObj );
+ Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Abc_LitNot(iObjNew)) );
+ }
+ }
+ }
+ }
+ else
+ {
+ Gia_ManForEachObj1( p, pObj, i )
+ {
+ pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) );
+ if ( pRepr == NULL )
+ continue;
+ iPrevNew = Gia_ObjIsConst(p, i)? 0 : Gia_ManCorrSpecReal( pNew, p, pRepr, nFrames, 0 );
+ iObjNew = Gia_ManCorrSpecReal( pNew, p, pObj, nFrames, 0 );
+ iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) );
+ if ( iPrevNew != iObjNew )
+ {
+ Vec_IntPush( *pvOutputs, Gia_ObjId(p, pRepr) );
+ Vec_IntPush( *pvOutputs, Gia_ObjId(p, pObj) );
+ Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, iPrevNew, iObjNew) );
+ }
+ }
+ }
+ Vec_IntForEachEntry( vXorLits, iObjNew, i )
+ Gia_ManAppendCo( pNew, iObjNew );
+ Vec_IntFree( vXorLits );
+ Gia_ManHashStop( pNew );
+ ABC_FREE( p->pCopies );
+//Abc_Print( 1, "Before sweeping = %d\n", Gia_ManAndNum(pNew) );
+ pNew = Gia_ManCleanup( pTemp = pNew );
+//Abc_Print( 1, "After sweeping = %d\n", Gia_ManAndNum(pNew) );
+ Gia_ManStop( pTemp );
+ return pNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Derives SRM for signal correspondence.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManCorrSpecReduceInit( Gia_Man_t * p, int nFrames, int nPrefix, int fScorr, Vec_Int_t ** pvOutputs, int fRings )
+{
+ Gia_Man_t * pNew, * pTemp;
+ Gia_Obj_t * pObj, * pRepr;
+ Vec_Int_t * vXorLits;
+ int f, i, iPrevNew, iObjNew;
+ assert( (!fScorr && nFrames > 1) || (fScorr && nFrames > 0) || nPrefix );
+ assert( Gia_ManRegNum(p) > 0 );
+ assert( p->pReprs != NULL );
+ p->pCopies = ABC_FALLOC( int, (nFrames+nPrefix+fScorr)*Gia_ManObjNum(p) );
+ Gia_ManSetPhase( p );
+ pNew = Gia_ManStart( (nFrames+nPrefix) * Gia_ManObjNum(p) );
+ pNew->pName = Abc_UtilStrsav( p->pName );
+ Gia_ManHashAlloc( pNew );
+ Gia_ManForEachRo( p, pObj, i )
+ {
+ Gia_ManAppendCi(pNew);
+ Gia_ObjSetCopyF( p, 0, pObj, 0 );
+ }
+ for ( f = 0; f < nFrames+nPrefix+fScorr; f++ )
+ {
+ Gia_ObjSetCopyF( p, f, Gia_ManConst0(p), 0 );
+ Gia_ManForEachPi( p, pObj, i )
+ Gia_ObjSetCopyF( p, f, pObj, Gia_ManAppendCi(pNew) );
+ }
+ *pvOutputs = Vec_IntAlloc( 1000 );
+ vXorLits = Vec_IntAlloc( 1000 );
+ for ( f = nPrefix; f < nFrames+nPrefix; f++ )
+ {
+ Gia_ManForEachObj1( p, pObj, i )
+ {
+ pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) );
+ if ( pRepr == NULL )
+ continue;
+ iPrevNew = Gia_ObjIsConst(p, i)? 0 : Gia_ManCorrSpecReal( pNew, p, pRepr, f, nPrefix );
+ iObjNew = Gia_ManCorrSpecReal( pNew, p, pObj, f, nPrefix );
+ iObjNew = Abc_LitNotCond( iObjNew, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) );
+ if ( iPrevNew != iObjNew )
+ {
+ Vec_IntPush( *pvOutputs, Gia_ObjId(p, pRepr) );
+ Vec_IntPush( *pvOutputs, Gia_ObjId(p, pObj) );
+ Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, iPrevNew, iObjNew) );
+ }
+ }
+ }
+ Vec_IntForEachEntry( vXorLits, iObjNew, i )
+ Gia_ManAppendCo( pNew, iObjNew );
+ Vec_IntFree( vXorLits );
+ Gia_ManHashStop( pNew );
+ ABC_FREE( p->pCopies );
+//Abc_Print( 1, "Before sweeping = %d\n", Gia_ManAndNum(pNew) );
+ pNew = Gia_ManCleanup( pTemp = pNew );
+//Abc_Print( 1, "After sweeping = %d\n", Gia_ManAndNum(pNew) );
+ Gia_ManStop( pTemp );
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Initializes simulation info for lcorr/scorr counter-examples.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManStartSimInfo( Vec_Ptr_t * vInfo, int nFlops )
+{
+ unsigned * pInfo;
+ int k, w, nWords;
+ nWords = Vec_PtrReadWordsSimInfo( vInfo );
+ assert( nFlops <= Vec_PtrSize(vInfo) );
+ for ( k = 0; k < nFlops; k++ )
+ {
+ pInfo = (unsigned *)Vec_PtrEntry( vInfo, k );
+ for ( w = 0; w < nWords; w++ )
+ pInfo[w] = 0;
+ }
+ for ( k = nFlops; k < Vec_PtrSize(vInfo); k++ )
+ {
+ pInfo = (unsigned *)Vec_PtrEntry( vInfo, k );
+ for ( w = 0; w < nWords; w++ )
+ pInfo[w] = Gia_ManRandom( 0 );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Remaps simulation info from SRM to the original AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Gia_ManCorrRemapSimInfo( Gia_Man_t * p, Vec_Ptr_t * vInfo )
+{
+ Gia_Obj_t * pObj, * pRepr;
+ unsigned * pInfoObj, * pInfoRepr;
+ int i, w, nWords;
+ nWords = Vec_PtrReadWordsSimInfo( vInfo );
+ Gia_ManForEachRo( p, pObj, i )
+ {
+ // skip ROs without representatives
+ pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) );
+ if ( pRepr == NULL || Gia_ObjFailed(p, Gia_ObjId(p,pObj)) )
+ continue;
+ pInfoObj = (unsigned *)Vec_PtrEntry( vInfo, i );
+ for ( w = 0; w < nWords; w++ )
+ assert( pInfoObj[w] == 0 );
+ // skip ROs with constant representatives
+ if ( Gia_ObjIsConst0(pRepr) )
+ continue;
+ assert( Gia_ObjIsRo(p, pRepr) );
+// Abc_Print( 1, "%d -> %d ", i, Gia_ObjId(p, pRepr) );
+ // transfer info from the representative
+ pInfoRepr = (unsigned *)Vec_PtrEntry( vInfo, Gia_ObjCioId(pRepr) - Gia_ManPiNum(p) );
+ for ( w = 0; w < nWords; w++ )
+ pInfoObj[w] = pInfoRepr[w];
+ }
+// Abc_Print( 1, "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects information about remapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManCorrCreateRemapping( Gia_Man_t * p )
+{
+ Vec_Int_t * vPairs;
+ Gia_Obj_t * pObj, * pRepr;
+ int i;
+ vPairs = Vec_IntAlloc( 100 );
+ Gia_ManForEachRo( p, pObj, i )
+ {
+ // skip ROs without representatives
+ pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) );
+ if ( pRepr == NULL || Gia_ObjIsConst0(pRepr) || Gia_ObjFailed(p, Gia_ObjId(p,pObj)) )
+// if ( pRepr == NULL || Gia_ObjIsConst0(pRepr) || Gia_ObjIsFailedPair(p, Gia_ObjId(p, pRepr), Gia_ObjId(p, pObj)) )
+ continue;
+ assert( Gia_ObjIsRo(p, pRepr) );
+// Abc_Print( 1, "%d -> %d ", Gia_ObjId(p,pObj), Gia_ObjId(p, pRepr) );
+ // remember the pair
+ Vec_IntPush( vPairs, Gia_ObjCioId(pRepr) - Gia_ManPiNum(p) );
+ Vec_IntPush( vPairs, i );
+ }
+ return vPairs;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Remaps simulation info from SRM to the original AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Gia_ManCorrPerformRemapping( Vec_Int_t * vPairs, Vec_Ptr_t * vInfo )
+{
+ unsigned * pInfoObj, * pInfoRepr;
+ int w, i, iObj, iRepr, nWords;
+ nWords = Vec_PtrReadWordsSimInfo( vInfo );
+ Vec_IntForEachEntry( vPairs, iRepr, i )
+ {
+ iObj = Vec_IntEntry( vPairs, ++i );
+ pInfoObj = (unsigned *)Vec_PtrEntry( vInfo, iObj );
+ pInfoRepr = (unsigned *)Vec_PtrEntry( vInfo, iRepr );
+ for ( w = 0; w < nWords; w++ )
+ {
+ assert( pInfoObj[w] == 0 );
+ pInfoObj[w] = pInfoRepr[w];
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Packs one counter-examples into the array of simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+*************************************`**********************************/
+int Cec_ManLoadCounterExamplesTry( Vec_Ptr_t * vInfo, Vec_Ptr_t * vPres, int iBit, int * pLits, int nLits )
+{
+ unsigned * pInfo, * pPres;
+ int i;
+ for ( i = 0; i < nLits; i++ )
+ {
+ pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i]));
+ pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i]));
+ if ( Abc_InfoHasBit( pPres, iBit ) &&
+ Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) )
+ return 0;
+ }
+ for ( i = 0; i < nLits; i++ )
+ {
+ pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i]));
+ pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i]));
+ Abc_InfoSetBit( pPres, iBit );
+ if ( Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) )
+ Abc_InfoXorBit( pInfo, iBit );
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs bitpacking of counter-examples.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManLoadCounterExamples( Vec_Ptr_t * vInfo, Vec_Int_t * vCexStore, int iStart )
+{
+ Vec_Int_t * vPat;
+ Vec_Ptr_t * vPres;
+ int nWords = Vec_PtrReadWordsSimInfo(vInfo);
+ int nBits = 32 * nWords;
+ int k, nSize, iBit = 1, kMax = 0;
+ vPat = Vec_IntAlloc( 100 );
+ vPres = Vec_PtrAllocSimInfo( Vec_PtrSize(vInfo), nWords );
+ Vec_PtrCleanSimInfo( vPres, 0, nWords );
+ while ( iStart < Vec_IntSize(vCexStore) )
+ {
+ // skip the output number
+ iStart++;
+ // get the number of items
+ nSize = Vec_IntEntry( vCexStore, iStart++ );
+ if ( nSize <= 0 )
+ continue;
+ // extract pattern
+ Vec_IntClear( vPat );
+ for ( k = 0; k < nSize; k++ )
+ Vec_IntPush( vPat, Vec_IntEntry( vCexStore, iStart++ ) );
+ // add pattern to storage
+ for ( k = 1; k < nBits; k++ )
+ if ( Cec_ManLoadCounterExamplesTry( vInfo, vPres, k, (int *)Vec_IntArray(vPat), Vec_IntSize(vPat) ) )
+ break;
+ kMax = Abc_MaxInt( kMax, k );
+ if ( k == nBits-1 )
+ break;
+ }
+ Vec_PtrFree( vPres );
+ Vec_IntFree( vPat );
+ return iStart;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs bitpacking of counter-examples.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManLoadCounterExamples2( Vec_Ptr_t * vInfo, Vec_Int_t * vCexStore, int iStart )
+{
+ unsigned * pInfo;
+ int nBits = 32 * Vec_PtrReadWordsSimInfo(vInfo);
+ int k, iLit, nLits, Out, iBit = 1;
+ while ( iStart < Vec_IntSize(vCexStore) )
+ {
+ // skip the output number
+// iStart++;
+ Out = Vec_IntEntry( vCexStore, iStart++ );
+// Abc_Print( 1, "iBit = %d. Out = %d.\n", iBit, Out );
+ // get the number of items
+ nLits = Vec_IntEntry( vCexStore, iStart++ );
+ if ( nLits <= 0 )
+ continue;
+ // add pattern to storage
+ for ( k = 0; k < nLits; k++ )
+ {
+ iLit = Vec_IntEntry( vCexStore, iStart++ );
+ pInfo = (unsigned *)Vec_PtrEntry( vInfo, Abc_Lit2Var(iLit) );
+ if ( Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(iLit) )
+ Abc_InfoXorBit( pInfo, iBit );
+ }
+ if ( ++iBit == nBits )
+ break;
+ }
+// Abc_Print( 1, "added %d bits\n", iBit-1 );
+ return iStart;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resimulates counter-examples derived by the SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManResimulateCounterExamples( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore, int nFrames )
+{
+ Vec_Int_t * vPairs;
+ Vec_Ptr_t * vSimInfo;
+ int RetValue = 0, iStart = 0;
+ vPairs = Gia_ManCorrCreateRemapping( pSim->pAig );
+ Gia_ManSetRefs( pSim->pAig );
+// pSim->pPars->nWords = 63;
+ pSim->pPars->nFrames = nFrames;
+ vSimInfo = Vec_PtrAllocSimInfo( Gia_ManRegNum(pSim->pAig) + Gia_ManPiNum(pSim->pAig) * nFrames, pSim->pPars->nWords );
+ while ( iStart < Vec_IntSize(vCexStore) )
+ {
+ Cec_ManStartSimInfo( vSimInfo, Gia_ManRegNum(pSim->pAig) );
+ iStart = Cec_ManLoadCounterExamples( vSimInfo, vCexStore, iStart );
+// iStart = Cec_ManLoadCounterExamples2( vSimInfo, vCexStore, iStart );
+// Gia_ManCorrRemapSimInfo( pSim->pAig, vSimInfo );
+ Gia_ManCorrPerformRemapping( vPairs, vSimInfo );
+ RetValue |= Cec_ManSeqResimulate( pSim, vSimInfo );
+// Cec_ManSeqResimulateInfo( pSim->pAig, vSimInfo, NULL );
+ }
+//Gia_ManEquivPrintOne( pSim->pAig, 85, 0 );
+ assert( iStart == Vec_IntSize(vCexStore) );
+ Vec_PtrFree( vSimInfo );
+ Vec_IntFree( vPairs );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resimulates counter-examples derived by the SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManResimulateCounterExamplesComb( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore )
+{
+ Vec_Ptr_t * vSimInfo;
+ int RetValue = 0, iStart = 0;
+ Gia_ManSetRefs( pSim->pAig );
+ pSim->pPars->nFrames = 1;
+ vSimInfo = Vec_PtrAllocSimInfo( Gia_ManCiNum(pSim->pAig), pSim->pPars->nWords );
+ while ( iStart < Vec_IntSize(vCexStore) )
+ {
+ Cec_ManStartSimInfo( vSimInfo, 0 );
+ iStart = Cec_ManLoadCounterExamples( vSimInfo, vCexStore, iStart );
+ RetValue |= Cec_ManSeqResimulate( pSim, vSimInfo );
+ }
+ assert( iStart == Vec_IntSize(vCexStore) );
+ Vec_PtrFree( vSimInfo );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates equivalence classes by marking those that timed out.]
+
+ Description [Returns 1 if all ndoes are proved.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Gia_ManCheckRefinements( Gia_Man_t * p, Vec_Str_t * vStatus, Vec_Int_t * vOutputs, Cec_ManSim_t * pSim, int fRings )
+{
+ int i, status, iRepr, iObj;
+ int Counter = 0;
+ assert( 2 * Vec_StrSize(vStatus) == Vec_IntSize(vOutputs) );
+ Vec_StrForEachEntry( vStatus, status, i )
+ {
+ iRepr = Vec_IntEntry( vOutputs, 2*i );
+ iObj = Vec_IntEntry( vOutputs, 2*i+1 );
+ if ( status == 1 )
+ continue;
+ if ( status == 0 )
+ {
+ if ( Gia_ObjHasSameRepr(p, iRepr, iObj) )
+ Counter++;
+// if ( Gia_ObjHasSameRepr(p, iRepr, iObj) )
+// Abc_Print( 1, "Gia_ManCheckRefinements(): Disproved equivalence (%d,%d) is not refined!\n", iRepr, iObj );
+// if ( Gia_ObjHasSameRepr(p, iRepr, iObj) )
+// Cec_ManSimClassRemoveOne( pSim, iObj );
+ continue;
+ }
+ if ( status == -1 )
+ {
+// if ( !Gia_ObjFailed( p, iObj ) )
+// Abc_Print( 1, "Gia_ManCheckRefinements(): Failed equivalence is not marked as failed!\n" );
+// Gia_ObjSetFailed( p, iRepr );
+// Gia_ObjSetFailed( p, iObj );
+// if ( fRings )
+// Cec_ManSimClassRemoveOne( pSim, iRepr );
+ Cec_ManSimClassRemoveOne( pSim, iObj );
+ continue;
+ }
+ }
+// if ( Counter )
+// Abc_Print( 1, "Gia_ManCheckRefinements(): Could not refine %d nodes.\n", Counter );
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates the AIG in the DFS order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Gia_ManCorrReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+ Gia_Obj_t * pRepr;
+ if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) )
+ {
+ Gia_ManCorrReduce_rec( pNew, p, pRepr );
+ pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) );
+ return;
+ }
+ if ( ~pObj->Value )
+ return;
+ assert( Gia_ObjIsAnd(pObj) );
+ Gia_ManCorrReduce_rec( pNew, p, Gia_ObjFanin0(pObj) );
+ Gia_ManCorrReduce_rec( pNew, p, Gia_ObjFanin1(pObj) );
+ pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reduces AIG using equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManCorrReduce( Gia_Man_t * p )
+{
+ Gia_Man_t * pNew;
+ Gia_Obj_t * pObj;
+ int i;
+ Gia_ManSetPhase( p );
+ pNew = Gia_ManStart( Gia_ManObjNum(p) );
+ pNew->pName = Abc_UtilStrsav( p->pName );
+ Gia_ManFillValue( p );
+ Gia_ManConst0(p)->Value = 0;
+ Gia_ManForEachCi( p, pObj, i )
+ pObj->Value = Gia_ManAppendCi(pNew);
+ Gia_ManHashAlloc( pNew );
+ Gia_ManForEachCo( p, pObj, i )
+ Gia_ManCorrReduce_rec( pNew, p, Gia_ObjFanin0(pObj) );
+ Gia_ManForEachCo( p, pObj, i )
+ Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+ Gia_ManHashStop( pNew );
+ Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+ return pNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints statistics during solving.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManRefinedClassPrintStats( Gia_Man_t * p, Vec_Str_t * vStatus, int iIter, int Time )
+{
+ int nLits, CounterX = 0, Counter0 = 0, Counter = 0;
+ int i, Entry, nProve = 0, nDispr = 0, nFail = 0;
+ for ( i = 1; i < Gia_ManObjNum(p); i++ )
+ {
+ if ( Gia_ObjIsNone(p, i) )
+ CounterX++;
+ else if ( Gia_ObjIsConst(p, i) )
+ Counter0++;
+ else if ( Gia_ObjIsHead(p, i) )
+ Counter++;
+ }
+ CounterX -= Gia_ManCoNum(p);
+ nLits = Gia_ManCiNum(p) + Gia_ManAndNum(p) - Counter - CounterX;
+ if ( iIter == -1 )
+ Abc_Print( 1, "BMC : " );
+ else
+ Abc_Print( 1, "%3d : ", iIter );
+ Abc_Print( 1, "c =%8d cl =%7d lit =%8d ", Counter0, Counter, nLits );
+ if ( vStatus )
+ Vec_StrForEachEntry( vStatus, Entry, i )
+ {
+ if ( Entry == 1 )
+ nProve++;
+ else if ( Entry == 0 )
+ nDispr++;
+ else if ( Entry == -1 )
+ nFail++;
+ }
+ Abc_Print( 1, "p =%6d d =%6d f =%6d ", nProve, nDispr, nFail );
+ Abc_PrintTime( 1, "T", Time );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Runs BMC for the equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManLSCorrespondenceBmc( Gia_Man_t * pAig, Cec_ParCor_t * pPars, int nPrefs )
+{
+ Cec_ParSim_t ParsSim, * pParsSim = &ParsSim;
+ Cec_ParSat_t ParsSat, * pParsSat = &ParsSat;
+ Vec_Str_t * vStatus;
+ Vec_Int_t * vOutputs;
+ Vec_Int_t * vCexStore;
+ Cec_ManSim_t * pSim;
+ Gia_Man_t * pSrm;
+ int fChanges, RetValue;
+ // prepare simulation manager
+ Cec_ManSimSetDefaultParams( pParsSim );
+ pParsSim->nWords = pPars->nWords;
+ pParsSim->nFrames = pPars->nRounds;
+ pParsSim->fVerbose = pPars->fVerbose;
+ pParsSim->fLatchCorr = pPars->fLatchCorr;
+ pParsSim->fSeqSimulate = 1;
+ pSim = Cec_ManSimStart( pAig, pParsSim );
+ // prepare SAT solving
+ Cec_ManSatSetDefaultParams( pParsSat );
+ pParsSat->nBTLimit = pPars->nBTLimit;
+ pParsSat->fVerbose = pPars->fVerbose;
+ fChanges = 1;
+ while ( fChanges )
+ {
+ int clkBmc = clock();
+ fChanges = 0;
+ pSrm = Gia_ManCorrSpecReduceInit( pAig, pPars->nFrames, nPrefs, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings );
+ if ( Gia_ManPoNum(pSrm) == 0 )
+ {
+ Gia_ManStop( pSrm );
+ Vec_IntFree( vOutputs );
+ break;
+ }
+ pParsSat->nBTLimit *= 10;
+ if ( pPars->fUseCSat )
+ vCexStore = Tas_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0 );
+ else
+ vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus );
+ // refine classes with these counter-examples
+ if ( Vec_IntSize(vCexStore) )
+ {
+ RetValue = Cec_ManResimulateCounterExamples( pSim, vCexStore, pPars->nFrames + 1 + nPrefs );
+ Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings );
+ fChanges = 1;
+ }
+ if ( pPars->fVerbose )
+ Cec_ManRefinedClassPrintStats( pAig, vStatus, -1, clock() - clkBmc );
+ // recycle
+ Vec_IntFree( vCexStore );
+ Vec_StrFree( vStatus );
+ Gia_ManStop( pSrm );
+ Vec_IntFree( vOutputs );
+ }
+ Cec_ManSimStop( pSim );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Internal procedure for register correspondence.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars )
+{
+ int nIterMax = 100000;
+ int nAddFrames = 1; // additional timeframes to simulate
+ int fRunBmcFirst = 1;
+ Vec_Str_t * vStatus;
+ Vec_Int_t * vOutputs;
+ Vec_Int_t * vCexStore;
+ Cec_ParSim_t ParsSim, * pParsSim = &ParsSim;
+ Cec_ParSat_t ParsSat, * pParsSat = &ParsSat;
+ Cec_ManSim_t * pSim;
+ Gia_Man_t * pSrm;
+ int r, RetValue, clkTotal = clock();
+ int clkSat = 0, clkSim = 0, clkSrm = 0;
+ int clk2, clk = clock();
+ if ( Gia_ManRegNum(pAig) == 0 )
+ {
+ Abc_Print( 1, "Cec_ManLatchCorrespondence(): Not a sequential AIG.\n" );
+ return 0;
+ }
+ Gia_ManRandom( 1 );
+ // prepare simulation manager
+ Cec_ManSimSetDefaultParams( pParsSim );
+ pParsSim->nWords = pPars->nWords;
+ pParsSim->nFrames = pPars->nFrames;
+ pParsSim->fVerbose = pPars->fVerbose;
+ pParsSim->fLatchCorr = pPars->fLatchCorr;
+ pParsSim->fConstCorr = pPars->fConstCorr;
+ pParsSim->fSeqSimulate = 1;
+ // create equivalence classes of registers
+ pSim = Cec_ManSimStart( pAig, pParsSim );
+ if ( pAig->pReprs == NULL )
+ {
+ Cec_ManSimClassesPrepare( pSim, pPars->nLevelMax );
+ Cec_ManSimClassesRefine( pSim );
+ }
+ // prepare SAT solving
+ Cec_ManSatSetDefaultParams( pParsSat );
+ pParsSat->nBTLimit = pPars->nBTLimit;
+ pParsSat->fVerbose = pPars->fVerbose;
+ if ( pPars->fVerbose )
+ {
+ Abc_Print( 1, "Obj = %7d. And = %7d. Conf = %5d. Fr = %d. Lcorr = %d. Ring = %d. CSat = %d.\n",
+ Gia_ManObjNum(pAig), Gia_ManAndNum(pAig),
+ pPars->nBTLimit, pPars->nFrames, pPars->fLatchCorr, pPars->fUseRings, pPars->fUseCSat );
+ Cec_ManRefinedClassPrintStats( pAig, NULL, 0, clock() - clk );
+ }
+ // check the base case
+ if ( fRunBmcFirst && (!pPars->fLatchCorr || pPars->nFrames > 1) )
+ Cec_ManLSCorrespondenceBmc( pAig, pPars, 0 );
+ if ( pPars->pFunc )
+ {
+ ((int (*)(void *))pPars->pFunc)( pPars->pData );
+ ((int (*)(void *))pPars->pFunc)( pPars->pData );
+ }
+ if ( pPars->nStepsMax == 0 )
+ {
+ Abc_Print( 1, "Stopped signal correspondence after BMC.\n" );
+ Cec_ManSimStop( pSim );
+ return 1;
+ }
+ // perform refinement of equivalence classes
+ for ( r = 0; r < nIterMax; r++ )
+ {
+ if ( pPars->nStepsMax == r )
+ {
+ Cec_ManSimStop( pSim );
+ Abc_Print( 1, "Stopped signal correspondence after %d refiment iterations.\n", r );
+ return 1;
+ }
+ clk = clock();
+ // perform speculative reduction
+ clk2 = clock();
+ pSrm = Gia_ManCorrSpecReduce( pAig, pPars->nFrames, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings );
+ assert( Gia_ManRegNum(pSrm) == 0 && Gia_ManPiNum(pSrm) == Gia_ManRegNum(pAig)+(pPars->nFrames+!pPars->fLatchCorr)*Gia_ManPiNum(pAig) );
+ clkSrm += clock() - clk2;
+ if ( Gia_ManCoNum(pSrm) == 0 )
+ {
+ Vec_IntFree( vOutputs );
+ Gia_ManStop( pSrm );
+ break;
+ }
+//Gia_DumpAiger( pSrm, "corrsrm", r, 2 );
+ // found counter-examples to speculation
+ clk2 = clock();
+ if ( pPars->fUseCSat )
+ vCexStore = Cbs_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0 );
+ else
+ vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus );
+ Gia_ManStop( pSrm );
+ clkSat += clock() - clk2;
+ if ( Vec_IntSize(vCexStore) == 0 )
+ {
+ Vec_IntFree( vCexStore );
+ Vec_StrFree( vStatus );
+ Vec_IntFree( vOutputs );
+ break;
+ }
+ // refine classes with these counter-examples
+ clk2 = clock();
+ RetValue = Cec_ManResimulateCounterExamples( pSim, vCexStore, pPars->nFrames + 1 + nAddFrames );
+ Vec_IntFree( vCexStore );
+ clkSim += clock() - clk2;
+ Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings );
+ if ( pPars->fVerbose )
+ Cec_ManRefinedClassPrintStats( pAig, vStatus, r+1, clock() - clk );
+ Vec_StrFree( vStatus );
+ Vec_IntFree( vOutputs );
+//Gia_ManEquivPrintClasses( pAig, 1, 0 );
+ if ( pPars->pFunc )
+ ((int (*)(void *))pPars->pFunc)( pPars->pData );
+ }
+ if ( pPars->fVerbose )
+ Cec_ManRefinedClassPrintStats( pAig, NULL, r+1, clock() - clk );
+ // check the overflow
+ if ( r == nIterMax )
+ Abc_Print( 1, "The refinement was not finished. The result may be incorrect.\n" );
+ Cec_ManSimStop( pSim );
+ // check the base case
+ if ( !fRunBmcFirst && (!pPars->fLatchCorr || pPars->nFrames > 1) )
+ Cec_ManLSCorrespondenceBmc( pAig, pPars, 0 );
+ clkTotal = clock() - clkTotal;
+ // report the results
+ if ( pPars->fVerbose )
+ {
+ ABC_PRTP( "Srm ", clkSrm, clkTotal );
+ ABC_PRTP( "Sat ", clkSat, clkTotal );
+ ABC_PRTP( "Sim ", clkSim, clkTotal );
+ ABC_PRTP( "Other", clkTotal-clkSat-clkSrm-clkSim, clkTotal );
+ Abc_PrintTime( 1, "TOTAL", clkTotal );
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes new initial state.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Cec_ManComputeInitState( Gia_Man_t * pAig, int nFrames )
+{
+ Gia_Obj_t * pObj, * pObjRo, * pObjRi;
+ unsigned * pInitState;
+ int i, f;
+ Gia_ManRandom( 1 );
+// Abc_Print( 1, "Simulating %d timeframes.\n", nFrames );
+ Gia_ManForEachRo( pAig, pObj, i )
+ pObj->fMark1 = 0;
+ for ( f = 0; f < nFrames; f++ )
+ {
+ Gia_ManConst0(pAig)->fMark1 = 0;
+ Gia_ManForEachPi( pAig, pObj, i )
+ pObj->fMark1 = Gia_ManRandom(0) & 1;
+ Gia_ManForEachAnd( pAig, pObj, i )
+ pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) &
+ (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj));
+ Gia_ManForEachRi( pAig, pObj, i )
+ pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj));
+ Gia_ManForEachRiRo( pAig, pObjRi, pObjRo, i )
+ pObjRo->fMark1 = pObjRi->fMark1;
+ }
+ pInitState = ABC_CALLOC( unsigned, Abc_BitWordNum(Gia_ManRegNum(pAig)) );
+ Gia_ManForEachRo( pAig, pObj, i )
+ {
+ if ( pObj->fMark1 )
+ Abc_InfoSetBit( pInitState, i );
+// Abc_Print( 1, "%d", pObj->fMark1 );
+ }
+// Abc_Print( 1, "\n" );
+ Gia_ManCleanMark1( pAig );
+ return pInitState;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints flop equivalences.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManPrintFlopEquivs( Gia_Man_t * p )
+{
+ Gia_Obj_t * pObj, * pRepr;
+ int i;
+ assert( p->vNamesIn != NULL );
+ Gia_ManForEachRo( p, pObj, i )
+ {
+ if ( Gia_ObjIsConst(p, Gia_ObjId(p, pObj)) )
+ Abc_Print( 1, "Original flop %s is proved equivalent to constant.\n", Vec_PtrEntry(p->vNamesIn, Gia_ObjCioId(pObj)) );
+ else if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) )
+ {
+ if ( Gia_ObjIsCi(pRepr) )
+ Abc_Print( 1, "Original flop %s is proved equivalent to flop %s.\n",
+ Vec_PtrEntry( p->vNamesIn, Gia_ObjCioId(pObj) ),
+ Vec_PtrEntry( p->vNamesIn, Gia_ObjCioId(pRepr) ) );
+ else
+ Abc_Print( 1, "Original flop %s is proved equivalent to internal node %d.\n",
+ Vec_PtrEntry( p->vNamesIn, Gia_ObjCioId(pObj) ), Gia_ObjId(p, pRepr) );
+ }
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Top-level procedure for register correspondence.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Gia_Man_t * Cec_ManLSCorrespondence( Gia_Man_t * pAig, Cec_ParCor_t * pPars )
+{
+ Gia_Man_t * pNew, * pTemp;
+ unsigned * pInitState;
+ int RetValue;
+ ABC_FREE( pAig->pReprs );
+ ABC_FREE( pAig->pNexts );
+ if ( pPars->nPrefix == 0 )
+ RetValue = Cec_ManLSCorrespondenceClasses( pAig, pPars );
+ else
+ {
+ // compute the cycles AIG
+ pInitState = Cec_ManComputeInitState( pAig, pPars->nPrefix );
+ pTemp = Gia_ManDupFlip( pAig, (int *)pInitState );
+ ABC_FREE( pInitState );
+ // compute classes of this AIG
+ RetValue = Cec_ManLSCorrespondenceClasses( pTemp, pPars );
+ // transfer the class info
+ pAig->pReprs = pTemp->pReprs; pTemp->pReprs = NULL;
+ pAig->pNexts = pTemp->pNexts; pTemp->pNexts = NULL;
+ // perform additional BMC
+ pPars->fUseCSat = 0;
+ pPars->nBTLimit = Abc_MaxInt( pPars->nBTLimit, 1000 );
+ Cec_ManLSCorrespondenceBmc( pAig, pPars, pPars->nPrefix );
+/*
+ // transfer the class info back
+ pTemp->pReprs = pAig->pReprs; pAig->pReprs = NULL;
+ pTemp->pNexts = pAig->pNexts; pAig->pNexts = NULL;
+ // continue refining
+ RetValue = Cec_ManLSCorrespondenceClasses( pTemp, pPars );
+ // transfer the class info
+ pAig->pReprs = pTemp->pReprs; pTemp->pReprs = NULL;
+ pAig->pNexts = pTemp->pNexts; pTemp->pNexts = NULL;
+*/
+ Gia_ManStop( pTemp );
+ }
+ // derive reduced AIG
+ if ( pPars->fMakeChoices )
+ {
+ pNew = Gia_ManEquivToChoices( pAig, 1 );
+ Gia_ManHasChoices( pNew );
+ }
+ else
+ {
+// Gia_ManEquivImprove( pAig );
+ pNew = Gia_ManCorrReduce( pAig );
+ pNew = Gia_ManSeqCleanup( pTemp = pNew );
+ Gia_ManStop( pTemp );
+ //Gia_WriteAiger( pNew, "reduced.aig", 0, 0 );
+ }
+ // report the results
+ if ( pPars->fVerbose )
+ {
+ Abc_Print( 1, "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n",
+ Gia_ManAndNum(pAig), Gia_ManAndNum(pNew),
+ 100.0*(Gia_ManAndNum(pAig)-Gia_ManAndNum(pNew))/(Gia_ManAndNum(pAig)?Gia_ManAndNum(pAig):1),
+ Gia_ManRegNum(pAig), Gia_ManRegNum(pNew),
+ 100.0*(Gia_ManRegNum(pAig)-Gia_ManRegNum(pNew))/(Gia_ManRegNum(pAig)?Gia_ManRegNum(pAig):1) );
+ }
+ if ( pPars->nPrefix && (Gia_ManAndNum(pNew) < Gia_ManAndNum(pAig) || Gia_ManRegNum(pNew) < Gia_ManRegNum(pAig)) )
+ Abc_Print( 1, "The reduced AIG was produced using %d-th invariants and will not verify.\n", pPars->nPrefix );
+ // print verbose info about equivalences
+ if ( pPars->fVerboseFlops )
+ {
+ if ( pAig->vNamesIn == NULL )
+ Abc_Print( 1, "Flop output names are not available. Use command \"&get -n\".\n" );
+ else
+ Cec_ManPrintFlopEquivs( pAig );
+ }
+ return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/cec/cecCorr_updated.c b/src/proof/cec/cecCorr_updated.c
new file mode 100644
index 00000000..1db30705
--- /dev/null
+++ b/src/proof/cec/cecCorr_updated.c
@@ -0,0 +1,1027 @@
+/**CFile****************************************************************
+
+ FileName [cecCorr.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Combinational equivalence checking.]
+
+ Synopsis [Latch/signal correspondence computation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cecCorr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Gia_ManCorrSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes the real value of the literal w/o spec reduction.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Gia_ManCorrSpecReal( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix )
+{
+ if ( Gia_ObjIsAnd(pObj) )
+ {
+ Gia_ManCorrSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj), f, nPrefix );
+ Gia_ManCorrSpecReduce_rec( pNew, p, Gia_ObjFanin1(pObj), f, nPrefix );
+ return Gia_ManHashAnd( pNew, Gia_ObjFanin0CopyF(p, f, pObj), Gia_ObjFanin1CopyF(p, f, pObj) );
+ }
+ if ( f == 0 )
+ {
+ assert( Gia_ObjIsRo(p, pObj) );
+ return Gia_ObjCopyF(p, f, pObj);
+ }
+ assert( f && Gia_ObjIsRo(p, pObj) );
+ pObj = Gia_ObjRoToRi( p, pObj );
+ Gia_ManCorrSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj), f-1, nPrefix );
+ return Gia_ObjFanin0CopyF( p, f-1, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively performs speculative reduction for the object.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Gia_ManCorrSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int f, int nPrefix )
+{
+ Gia_Obj_t * pRepr;
+ int iLitNew;
+ if ( ~Gia_ObjCopyF(p, f, pObj) )
+ return;
+ if ( f >= nPrefix && (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) )
+ {
+ Gia_ManCorrSpecReduce_rec( pNew, p, pRepr, f, nPrefix );
+ iLitNew = Gia_LitNotCond( Gia_ObjCopyF(p, f, pRepr), Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) );
+ Gia_ObjSetCopyF( p, f, pObj, iLitNew );
+ return;
+ }
+ assert( Gia_ObjIsCand(pObj) );
+ iLitNew = Gia_ManCorrSpecReal( pNew, p, pObj, f, nPrefix );
+ Gia_ObjSetCopyF( p, f, pObj, iLitNew );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives SRM for signal correspondence.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManCorrSpecReduce( Gia_Man_t * p, int nFrames, int fScorr, Vec_Int_t ** pvOutputs, int fRings )
+{
+ Gia_Man_t * pNew, * pTemp;
+ Gia_Obj_t * pObj, * pRepr;
+ Vec_Int_t * vXorLits;
+ int f, i, iPrev, iObj, iPrevNew, iObjNew;
+ assert( nFrames > 0 );
+ assert( Gia_ManRegNum(p) > 0 );
+ assert( p->pReprs != NULL );
+ p->pCopies = ABC_FALLOC( int, (nFrames+fScorr)*Gia_ManObjNum(p) );
+ Gia_ManSetPhase( p );
+ pNew = Gia_ManStart( nFrames * Gia_ManObjNum(p) );
+ pNew->pName = Gia_UtilStrsav( p->pName );
+ Gia_ManHashAlloc( pNew );
+ Gia_ObjSetCopyF( p, 0, Gia_ManConst0(p), 0 );
+ Gia_ManForEachRo( p, pObj, i )
+ Gia_ObjSetCopyF( p, 0, pObj, Gia_ManAppendCi(pNew) );
+ Gia_ManForEachRo( p, pObj, i )
+ if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) )
+ Gia_ObjSetCopyF( p, 0, pObj, Gia_ObjCopyF(p, 0, pRepr) );
+ for ( f = 0; f < nFrames+fScorr; f++ )
+ {
+ Gia_ObjSetCopyF( p, f, Gia_ManConst0(p), 0 );
+ Gia_ManForEachPi( p, pObj, i )
+ Gia_ObjSetCopyF( p, f, pObj, Gia_ManAppendCi(pNew) );
+ }
+ *pvOutputs = Vec_IntAlloc( 1000 );
+ vXorLits = Vec_IntAlloc( 1000 );
+ if ( fRings )
+ {
+ Gia_ManForEachObj1( p, pObj, i )
+ {
+ if ( Gia_ObjIsConst( p, i ) )
+ {
+ iObjNew = Gia_ManCorrSpecReal( pNew, p, pObj, nFrames, 0 );
+ iObjNew = Gia_LitNotCond( iObjNew, Gia_ObjPhase(pObj) );
+ if ( iObjNew != 0 )
+ {
+ Vec_IntPush( *pvOutputs, 0 );
+ Vec_IntPush( *pvOutputs, i );
+ Vec_IntPush( vXorLits, iObjNew );
+ }
+ }
+ else if ( Gia_ObjIsHead( p, i ) )
+ {
+ iPrev = i;
+ Gia_ClassForEachObj1( p, i, iObj )
+ {
+ iPrevNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iPrev), nFrames, 0 );
+ iObjNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iObj), nFrames, 0 );
+ iPrevNew = Gia_LitNotCond( iPrevNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) );
+ iObjNew = Gia_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) );
+ if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 )
+ {
+ Vec_IntPush( *pvOutputs, iPrev );
+ Vec_IntPush( *pvOutputs, iObj );
+ Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Gia_LitNot(iObjNew)) );
+ }
+ iPrev = iObj;
+ }
+ iObj = i;
+ iPrevNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iPrev), nFrames, 0 );
+ iObjNew = Gia_ManCorrSpecReal( pNew, p, Gia_ManObj(p, iObj), nFrames, 0 );
+ iPrevNew = Gia_LitNotCond( iPrevNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iPrev)) );
+ iObjNew = Gia_LitNotCond( iObjNew, Gia_ObjPhase(pObj) ^ Gia_ObjPhase(Gia_ManObj(p, iObj)) );
+ if ( iPrevNew != iObjNew && iPrevNew != 0 && iObjNew != 1 )
+ {
+ Vec_IntPush( *pvOutputs, iPrev );
+ Vec_IntPush( *pvOutputs, iObj );
+ Vec_IntPush( vXorLits, Gia_ManHashAnd(pNew, iPrevNew, Gia_LitNot(iObjNew)) );
+ }
+ }
+ }
+ }
+ else
+ {
+ Gia_ManForEachObj1( p, pObj, i )
+ {
+ pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) );
+ if ( pRepr == NULL )
+ continue;
+ iPrevNew = Gia_ObjIsConst(p, i)? 0 : Gia_ManCorrSpecReal( pNew, p, pRepr, nFrames, 0 );
+ iObjNew = Gia_ManCorrSpecReal( pNew, p, pObj, nFrames, 0 );
+ iObjNew = Gia_LitNotCond( iObjNew, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) );
+ if ( iPrevNew != iObjNew )
+ {
+ Vec_IntPush( *pvOutputs, Gia_ObjId(p, pRepr) );
+ Vec_IntPush( *pvOutputs, Gia_ObjId(p, pObj) );
+ Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, iPrevNew, iObjNew) );
+ }
+ }
+ }
+ Vec_IntForEachEntry( vXorLits, iObjNew, i )
+ Gia_ManAppendCo( pNew, iObjNew );
+ Vec_IntFree( vXorLits );
+ Gia_ManHashStop( pNew );
+ ABC_FREE( p->pCopies );
+//printf( "Before sweeping = %d\n", Gia_ManAndNum(pNew) );
+ pNew = Gia_ManCleanup( pTemp = pNew );
+//printf( "After sweeping = %d\n", Gia_ManAndNum(pNew) );
+ Gia_ManStop( pTemp );
+ return pNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Derives SRM for signal correspondence.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManCorrSpecReduceInit( Gia_Man_t * p, int nFrames, int nPrefix, int fScorr, Vec_Int_t ** pvOutputs, int fRings )
+{
+ Gia_Man_t * pNew, * pTemp;
+ Gia_Obj_t * pObj, * pRepr;
+ Vec_Int_t * vXorLits;
+ int f, i, iPrevNew, iObjNew;
+ assert( (!fScorr && nFrames > 1) || (fScorr && nFrames > 0) || nPrefix );
+ assert( Gia_ManRegNum(p) > 0 );
+ assert( p->pReprs != NULL );
+ p->pCopies = ABC_FALLOC( int, (nFrames+nPrefix+fScorr)*Gia_ManObjNum(p) );
+ Gia_ManSetPhase( p );
+ pNew = Gia_ManStart( (nFrames+nPrefix) * Gia_ManObjNum(p) );
+ pNew->pName = Gia_UtilStrsav( p->pName );
+ Gia_ManHashAlloc( pNew );
+ Gia_ManForEachRo( p, pObj, i )
+ {
+ Gia_ManAppendCi(pNew);
+ Gia_ObjSetCopyF( p, 0, pObj, 0 );
+ }
+ for ( f = 0; f < nFrames+nPrefix+fScorr; f++ )
+ {
+ Gia_ObjSetCopyF( p, f, Gia_ManConst0(p), 0 );
+ Gia_ManForEachPi( p, pObj, i )
+ Gia_ObjSetCopyF( p, f, pObj, Gia_ManAppendCi(pNew) );
+ }
+ *pvOutputs = Vec_IntAlloc( 1000 );
+ vXorLits = Vec_IntAlloc( 1000 );
+ for ( f = nPrefix; f < nFrames+nPrefix; f++ )
+ {
+ Gia_ManForEachObj1( p, pObj, i )
+ {
+ pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) );
+ if ( pRepr == NULL )
+ continue;
+ iPrevNew = Gia_ObjIsConst(p, i)? 0 : Gia_ManCorrSpecReal( pNew, p, pRepr, f, nPrefix );
+ iObjNew = Gia_ManCorrSpecReal( pNew, p, pObj, f, nPrefix );
+ iObjNew = Gia_LitNotCond( iObjNew, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) );
+ if ( iPrevNew != iObjNew )
+ {
+ Vec_IntPush( *pvOutputs, Gia_ObjId(p, pRepr) );
+ Vec_IntPush( *pvOutputs, Gia_ObjId(p, pObj) );
+ Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, iPrevNew, iObjNew) );
+ }
+ }
+ }
+ Vec_IntForEachEntry( vXorLits, iObjNew, i )
+ Gia_ManAppendCo( pNew, iObjNew );
+ Vec_IntFree( vXorLits );
+ Gia_ManHashStop( pNew );
+ ABC_FREE( p->pCopies );
+//printf( "Before sweeping = %d\n", Gia_ManAndNum(pNew) );
+ pNew = Gia_ManCleanup( pTemp = pNew );
+//printf( "After sweeping = %d\n", Gia_ManAndNum(pNew) );
+ Gia_ManStop( pTemp );
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Initializes simulation info for lcorr/scorr counter-examples.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManStartSimInfo( Vec_Ptr_t * vInfo, int nFlops, int * pInitState )
+{
+ unsigned * pInfo;
+ int k, w, nWords;
+ nWords = Vec_PtrReadWordsSimInfo( vInfo );
+ assert( nFlops <= Vec_PtrSize(vInfo) );
+ for ( k = 0; k < nFlops; k++ )
+ {
+ pInfo = Vec_PtrEntry( vInfo, k );
+ if ( pInitState && Gia_InfoHasBit(pInitState, k) )
+ {
+ for ( w = 0; w < nWords; w++ )
+ pInfo[w] = ~0;
+// pInfo[0] <<= 1;
+ }
+ else
+ {
+ for ( w = 0; w < nWords; w++ )
+ pInfo[w] = 0;
+ }
+ }
+ for ( k = nFlops; k < Vec_PtrSize(vInfo); k++ )
+ {
+ pInfo = Vec_PtrEntry( vInfo, k );
+ for ( w = 0; w < nWords; w++ )
+ pInfo[w] = Gia_ManRandom( 0 );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Remaps simulation info from SRM to the original AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Gia_ManCorrRemapSimInfo( Gia_Man_t * p, Vec_Ptr_t * vInfo )
+{
+ Gia_Obj_t * pObj, * pRepr;
+ unsigned * pInfoObj, * pInfoRepr;
+ int i, w, nWords;
+ nWords = Vec_PtrReadWordsSimInfo( vInfo );
+ Gia_ManForEachRo( p, pObj, i )
+ {
+ // skip ROs without representatives
+ pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) );
+ if ( pRepr == NULL || Gia_ObjFailed(p, Gia_ObjId(p,pObj)) )
+ continue;
+ pInfoObj = Vec_PtrEntry( vInfo, i );
+ for ( w = 0; w < nWords; w++ )
+ assert( pInfoObj[w] == 0 );
+ // skip ROs with constant representatives
+ if ( Gia_ObjIsConst0(pRepr) )
+ continue;
+ assert( Gia_ObjIsRo(p, pRepr) );
+// printf( "%d -> %d ", i, Gia_ObjId(p, pRepr) );
+ // transfer info from the representative
+ pInfoRepr = Vec_PtrEntry( vInfo, Gia_ObjCioId(pRepr) - Gia_ManPiNum(p) );
+ for ( w = 0; w < nWords; w++ )
+ pInfoObj[w] = pInfoRepr[w];
+ }
+// printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects information about remapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Gia_ManCorrCreateRemapping( Gia_Man_t * p )
+{
+ Vec_Int_t * vPairs;
+ Gia_Obj_t * pObj, * pRepr;
+ int i;
+ vPairs = Vec_IntAlloc( 100 );
+ Gia_ManForEachRo( p, pObj, i )
+ {
+ // skip ROs without representatives
+ pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) );
+ if ( pRepr == NULL || Gia_ObjIsConst0(pRepr) || Gia_ObjFailed(p, Gia_ObjId(p,pObj)) )
+// if ( pRepr == NULL || Gia_ObjIsConst0(pRepr) || Gia_ObjIsFailedPair(p, Gia_ObjId(p, pRepr), Gia_ObjId(p, pObj)) )
+ continue;
+ assert( Gia_ObjIsRo(p, pRepr) );
+// printf( "%d -> %d ", Gia_ObjId(p,pObj), Gia_ObjId(p, pRepr) );
+ // remember the pair
+ Vec_IntPush( vPairs, Gia_ObjCioId(pRepr) - Gia_ManPiNum(p) );
+ Vec_IntPush( vPairs, i );
+ }
+ return vPairs;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Remaps simulation info from SRM to the original AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Gia_ManCorrPerformRemapping( Vec_Int_t * vPairs, Vec_Ptr_t * vInfo, int * pInitState )
+{
+ unsigned * pInfoObj, * pInfoRepr;
+ int w, i, iObj, iRepr, nWords;
+ nWords = Vec_PtrReadWordsSimInfo( vInfo );
+ Vec_IntForEachEntry( vPairs, iRepr, i )
+ {
+ iObj = Vec_IntEntry( vPairs, ++i );
+ pInfoObj = Vec_PtrEntry( vInfo, iObj );
+ pInfoRepr = Vec_PtrEntry( vInfo, iRepr );
+ for ( w = 0; w < nWords; w++ )
+ {
+ assert( pInitState || pInfoObj[w] == 0 );
+ pInfoObj[w] = pInfoRepr[w];
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Packs one counter-examples into the array of simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+*************************************`**********************************/
+int Cec_ManLoadCounterExamplesTry( Vec_Ptr_t * vInfo, Vec_Ptr_t * vPres, int iBit, int * pLits, int nLits )
+{
+ unsigned * pInfo, * pPres;
+ int i;
+ for ( i = 0; i < nLits; i++ )
+ {
+ pInfo = Vec_PtrEntry(vInfo, Gia_Lit2Var(pLits[i]));
+ pPres = Vec_PtrEntry(vPres, Gia_Lit2Var(pLits[i]));
+ if ( Gia_InfoHasBit( pPres, iBit ) &&
+ Gia_InfoHasBit( pInfo, iBit ) == Gia_LitIsCompl(pLits[i]) )
+ return 0;
+ }
+ for ( i = 0; i < nLits; i++ )
+ {
+ pInfo = Vec_PtrEntry(vInfo, Gia_Lit2Var(pLits[i]));
+ pPres = Vec_PtrEntry(vPres, Gia_Lit2Var(pLits[i]));
+ Gia_InfoSetBit( pPres, iBit );
+ if ( Gia_InfoHasBit( pInfo, iBit ) == Gia_LitIsCompl(pLits[i]) )
+ Gia_InfoXorBit( pInfo, iBit );
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs bitpacking of counter-examples.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManLoadCounterExamples( Vec_Ptr_t * vInfo, Vec_Int_t * vCexStore, int iStart )
+{
+ Vec_Int_t * vPat;
+ Vec_Ptr_t * vPres;
+ int nWords = Vec_PtrReadWordsSimInfo(vInfo);
+ int nBits = 32 * nWords;
+ int k, nSize, iBit = 1, kMax = 0;
+ vPat = Vec_IntAlloc( 100 );
+ vPres = Vec_PtrAllocSimInfo( Vec_PtrSize(vInfo), nWords );
+ Vec_PtrCleanSimInfo( vPres, 0, nWords );
+ while ( iStart < Vec_IntSize(vCexStore) )
+ {
+ // skip the output number
+ iStart++;
+ // get the number of items
+ nSize = Vec_IntEntry( vCexStore, iStart++ );
+ if ( nSize <= 0 )
+ continue;
+ // extract pattern
+ Vec_IntClear( vPat );
+ for ( k = 0; k < nSize; k++ )
+ Vec_IntPush( vPat, Vec_IntEntry( vCexStore, iStart++ ) );
+ // add pattern to storage
+ for ( k = 1; k < nBits; k++ )
+ if ( Cec_ManLoadCounterExamplesTry( vInfo, vPres, k, (int *)Vec_IntArray(vPat), Vec_IntSize(vPat) ) )
+ break;
+ kMax = Abc_MaxInt( kMax, k );
+ if ( k == nBits-1 )
+ break;
+ }
+ Vec_PtrFree( vPres );
+ Vec_IntFree( vPat );
+ return iStart;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs bitpacking of counter-examples.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManLoadCounterExamples2( Vec_Ptr_t * vInfo, Vec_Int_t * vCexStore, int iStart )
+{
+ unsigned * pInfo;
+ int nBits = 32 * Vec_PtrReadWordsSimInfo(vInfo);
+ int k, iLit, nLits, Out, iBit = 1;
+ while ( iStart < Vec_IntSize(vCexStore) )
+ {
+ // skip the output number
+// iStart++;
+ Out = Vec_IntEntry( vCexStore, iStart++ );
+// printf( "iBit = %d. Out = %d.\n", iBit, Out );
+ // get the number of items
+ nLits = Vec_IntEntry( vCexStore, iStart++ );
+ if ( nLits <= 0 )
+ continue;
+ // add pattern to storage
+ for ( k = 0; k < nLits; k++ )
+ {
+ iLit = Vec_IntEntry( vCexStore, iStart++ );
+ pInfo = Vec_PtrEntry( vInfo, Gia_Lit2Var(iLit) );
+ if ( Gia_InfoHasBit( pInfo, iBit ) == Gia_LitIsCompl(iLit) )
+ Gia_InfoXorBit( pInfo, iBit );
+ }
+ if ( ++iBit == nBits )
+ break;
+ }
+// printf( "added %d bits\n", iBit-1 );
+ return iStart;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resimulates counter-examples derived by the SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManResimulateCounterExamples( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore, int nFrames, int * pInitState )
+{
+ Vec_Int_t * vPairs;
+ Vec_Ptr_t * vSimInfo;
+ int RetValue = 0, iStart = 0;
+ vPairs = Gia_ManCorrCreateRemapping( pSim->pAig );
+ Gia_ManSetRefs( pSim->pAig );
+// pSim->pPars->nWords = 63;
+ pSim->pPars->nRounds = nFrames;
+ vSimInfo = Vec_PtrAllocSimInfo( Gia_ManRegNum(pSim->pAig) + Gia_ManPiNum(pSim->pAig) * nFrames, pSim->pPars->nWords );
+ while ( iStart < Vec_IntSize(vCexStore) )
+ {
+ Cec_ManStartSimInfo( vSimInfo, Gia_ManRegNum(pSim->pAig), pInitState );
+ iStart = Cec_ManLoadCounterExamples( vSimInfo, vCexStore, iStart );
+// iStart = Cec_ManLoadCounterExamples2( vSimInfo, vCexStore, iStart );
+// Gia_ManCorrRemapSimInfo( pSim->pAig, vSimInfo );
+ Gia_ManCorrPerformRemapping( vPairs, vSimInfo, pInitState );
+ RetValue |= Cec_ManSeqResimulate( pSim, vSimInfo );
+// Cec_ManSeqResimulateInfo( pSim->pAig, vSimInfo, NULL );
+ }
+//Gia_ManEquivPrintOne( pSim->pAig, 85, 0 );
+ assert( iStart == Vec_IntSize(vCexStore) );
+ Vec_PtrFree( vSimInfo );
+ Vec_IntFree( vPairs );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resimulates counter-examples derived by the SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManResimulateCounterExamplesComb( Cec_ManSim_t * pSim, Vec_Int_t * vCexStore )
+{
+ Vec_Ptr_t * vSimInfo;
+ int RetValue = 0, iStart = 0;
+ Gia_ManSetRefs( pSim->pAig );
+ pSim->pPars->nRounds = 1;
+ vSimInfo = Vec_PtrAllocSimInfo( Gia_ManCiNum(pSim->pAig), pSim->pPars->nWords );
+ while ( iStart < Vec_IntSize(vCexStore) )
+ {
+ Cec_ManStartSimInfo( vSimInfo, 0, NULL );
+ iStart = Cec_ManLoadCounterExamples( vSimInfo, vCexStore, iStart );
+ RetValue |= Cec_ManSeqResimulate( pSim, vSimInfo );
+ }
+ assert( iStart == Vec_IntSize(vCexStore) );
+ Vec_PtrFree( vSimInfo );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates equivalence classes by marking those that timed out.]
+
+ Description [Returns 1 if all ndoes are proved.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Gia_ManCheckRefinements( Gia_Man_t * p, Vec_Str_t * vStatus, Vec_Int_t * vOutputs, Cec_ManSim_t * pSim, int fRings )
+{
+ int i, status, iRepr, iObj;
+ int Counter = 0;
+ assert( 2 * Vec_StrSize(vStatus) == Vec_IntSize(vOutputs) );
+ Vec_StrForEachEntry( vStatus, status, i )
+ {
+ iRepr = Vec_IntEntry( vOutputs, 2*i );
+ iObj = Vec_IntEntry( vOutputs, 2*i+1 );
+ if ( status == 1 )
+ continue;
+ if ( status == 0 )
+ {
+ if ( Gia_ObjHasSameRepr(p, iRepr, iObj) )
+ Counter++;
+// if ( Gia_ObjHasSameRepr(p, iRepr, iObj) )
+// printf( "Gia_ManCheckRefinements(): Disproved equivalence (%d,%d) is not refined!\n", iRepr, iObj );
+// if ( Gia_ObjHasSameRepr(p, iRepr, iObj) )
+// Cec_ManSimClassRemoveOne( pSim, iObj );
+ continue;
+ }
+ if ( status == -1 )
+ {
+// if ( !Gia_ObjFailed( p, iObj ) )
+// printf( "Gia_ManCheckRefinements(): Failed equivalence is not marked as failed!\n" );
+// Gia_ObjSetFailed( p, iRepr );
+// Gia_ObjSetFailed( p, iObj );
+// if ( fRings )
+// Cec_ManSimClassRemoveOne( pSim, iRepr );
+ Cec_ManSimClassRemoveOne( pSim, iObj );
+ continue;
+ }
+ }
+// if ( Counter )
+// printf( "Gia_ManCheckRefinements(): Could not refine %d nodes.\n", Counter );
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates the AIG in the DFS order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Gia_ManCorrReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+ Gia_Obj_t * pRepr;
+ if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) )
+ {
+ Gia_ManCorrReduce_rec( pNew, p, pRepr );
+ pObj->Value = Gia_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) );
+ return;
+ }
+ if ( ~pObj->Value )
+ return;
+ assert( Gia_ObjIsAnd(pObj) );
+ Gia_ManCorrReduce_rec( pNew, p, Gia_ObjFanin0(pObj) );
+ Gia_ManCorrReduce_rec( pNew, p, Gia_ObjFanin1(pObj) );
+ pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reduces AIG using equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManCorrReduce( Gia_Man_t * p )
+{
+ Gia_Man_t * pNew;
+ Gia_Obj_t * pObj;
+ int i;
+ Gia_ManSetPhase( p );
+ pNew = Gia_ManStart( Gia_ManObjNum(p) );
+ pNew->pName = Gia_UtilStrsav( p->pName );
+ Gia_ManFillValue( p );
+ Gia_ManConst0(p)->Value = 0;
+ Gia_ManForEachCi( p, pObj, i )
+ pObj->Value = Gia_ManAppendCi(pNew);
+ Gia_ManHashAlloc( pNew );
+ Gia_ManForEachCo( p, pObj, i )
+ Gia_ManCorrReduce_rec( pNew, p, Gia_ObjFanin0(pObj) );
+ Gia_ManForEachCo( p, pObj, i )
+ Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+ Gia_ManHashStop( pNew );
+ Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
+ return pNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints statistics during solving.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManRefinedClassPrintStats( Gia_Man_t * p, Vec_Str_t * vStatus, int iIter, int Time )
+{
+ int nLits, CounterX = 0, Counter0 = 0, Counter = 0;
+ int i, Entry, nProve = 0, nDispr = 0, nFail = 0;
+ for ( i = 1; i < Gia_ManObjNum(p); i++ )
+ {
+ if ( Gia_ObjIsNone(p, i) )
+ CounterX++;
+ else if ( Gia_ObjIsConst(p, i) )
+ Counter0++;
+ else if ( Gia_ObjIsHead(p, i) )
+ Counter++;
+ }
+ CounterX -= Gia_ManCoNum(p);
+ nLits = Gia_ManCiNum(p) + Gia_ManAndNum(p) - Counter - CounterX;
+ if ( iIter == -1 )
+ printf( "BMC : " );
+ else
+ printf( "%3d : ", iIter );
+ printf( "c =%8d cl =%7d lit =%8d ", Counter0, Counter, nLits );
+ if ( vStatus )
+ Vec_StrForEachEntry( vStatus, Entry, i )
+ {
+ if ( Entry == 1 )
+ nProve++;
+ else if ( Entry == 0 )
+ nDispr++;
+ else if ( Entry == -1 )
+ nFail++;
+ }
+ printf( "p =%6d d =%6d f =%6d ", nProve, nDispr, nFail );
+ ABC_PRT( "T", Time );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes new initial state.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Cec_ManComputeInitState( Gia_Man_t * pAig, int nFrames )
+{
+ Gia_Obj_t * pObj, * pObjRo, * pObjRi;
+ unsigned * pInitState;
+ int i, f;
+ printf( "Simulating %d timeframes.\n", nFrames );
+ Gia_ManForEachRo( pAig, pObj, i )
+ pObj->fMark1 = 0;
+ for ( f = 0; f < nFrames; f++ )
+ {
+ Gia_ManConst0(pAig)->fMark1 = 0;
+ Gia_ManForEachPi( pAig, pObj, i )
+ pObj->fMark1 = Gia_ManRandom(0) & 1;
+// pObj->fMark1 = 1;
+ Gia_ManForEachAnd( pAig, pObj, i )
+ pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) &
+ (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj));
+ Gia_ManForEachRi( pAig, pObj, i )
+ pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj));
+ Gia_ManForEachRiRo( pAig, pObjRi, pObjRo, i )
+ pObjRo->fMark1 = pObjRi->fMark1;
+ }
+ pInitState = ABC_CALLOC( unsigned, Gia_BitWordNum(Gia_ManRegNum(pAig)) );
+ Gia_ManForEachRo( pAig, pObj, i )
+ {
+ if ( pObj->fMark1 )
+ Gia_InfoSetBit( pInitState, i );
+// printf( "%d", pObj->fMark1 );
+ }
+// printf( "\n" );
+ Gia_ManCleanMark1( pAig );
+ return pInitState;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Internal procedure for register correspondence.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManLSCorrespondenceClasses( Gia_Man_t * pAig, Cec_ParCor_t * pPars )
+{
+ int nIterMax = 100000;
+ int nAddFrames = 1; // additional timeframes to simulate
+ Vec_Str_t * vStatus;
+ Vec_Int_t * vOutputs;
+ Vec_Int_t * vCexStore;
+ Cec_ParSim_t ParsSim, * pParsSim = &ParsSim;
+ Cec_ParSat_t ParsSat, * pParsSat = &ParsSat;
+ Cec_ManSim_t * pSim;
+ Gia_Man_t * pSrm;
+ unsigned * pInitState = NULL;
+ int r, RetValue, clkTotal = clock();
+ int clkSat = 0, clkSim = 0, clkSrm = 0;
+ int clk2, clk = clock();
+ ABC_FREE( pAig->pReprs );
+ ABC_FREE( pAig->pNexts );
+ if ( Gia_ManRegNum(pAig) == 0 )
+ {
+ printf( "Cec_ManLatchCorrespondence(): Not a sequential AIG.\n" );
+ return 0;
+ }
+ Gia_ManRandom( 1 );
+ // derive initial state for resimulation
+ if ( pPars->nPrefix )
+// pInitState = Cec_ManComputeInitState( pAig, 5+(1<<20)/Gia_ManAndNum(pAig) );
+ pInitState = Cec_ManComputeInitState( pAig, 100 );
+ // prepare simulation manager
+ Cec_ManSimSetDefaultParams( pParsSim );
+ pParsSim->nWords = pPars->nWords;
+ pParsSim->nRounds = pPars->nRounds;
+ pParsSim->fVerbose = pPars->fVerbose;
+ pParsSim->fLatchCorr = pPars->fLatchCorr;
+ pParsSim->fSeqSimulate = 1;
+ // create equivalence classes of registers
+ pSim = Cec_ManSimStart( pAig, pParsSim, pInitState );
+ Cec_ManSimClassesPrepare( pSim );
+ Cec_ManSimClassesRefine( pSim );
+ // prepare SAT solving
+ Cec_ManSatSetDefaultParams( pParsSat );
+ pParsSat->nBTLimit = pPars->nBTLimit;
+ pParsSat->fVerbose = pPars->fVerbose;
+ if ( pPars->fVerbose )
+ {
+ printf( "Obj = %7d. And = %7d. Conf = %5d. Fr = %d. Lcorr = %d. Ring = %d. CSat = %d.\n",
+ Gia_ManObjNum(pAig), Gia_ManAndNum(pAig),
+ pPars->nBTLimit, pPars->nFrames, pPars->fLatchCorr, pPars->fUseRings, pPars->fUseCSat );
+ Cec_ManRefinedClassPrintStats( pAig, NULL, 0, clock() - clk );
+ }
+ // perform refinement of equivalence classes
+ for ( r = 0; r < nIterMax; r++ )
+ {
+ clk = clock();
+ // perform speculative reduction
+ clk2 = clock();
+ pSrm = Gia_ManCorrSpecReduce( pAig, pPars->nFrames, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings );
+ assert( Gia_ManRegNum(pSrm) == 0 && Gia_ManPiNum(pSrm) == Gia_ManRegNum(pAig)+(pPars->nFrames+!pPars->fLatchCorr)*Gia_ManPiNum(pAig) );
+ clkSrm += clock() - clk2;
+ if ( Gia_ManCoNum(pSrm) == 0 )
+ {
+ Vec_IntFree( vOutputs );
+ Gia_ManStop( pSrm );
+ break;
+ }
+//Gia_DumpAiger( pSrm, "corrsrm", r, 2 );
+ // found counter-examples to speculation
+ clk2 = clock();
+ if ( pPars->fUseCSat )
+ vCexStore = Cbs_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0 );
+ else
+ vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus );
+ Gia_ManStop( pSrm );
+ clkSat += clock() - clk2;
+ if ( Vec_IntSize(vCexStore) == 0 )
+ {
+ Vec_IntFree( vCexStore );
+ Vec_StrFree( vStatus );
+ Vec_IntFree( vOutputs );
+ break;
+ }
+ // refine classes with these counter-examples
+ clk2 = clock();
+ RetValue = Cec_ManResimulateCounterExamples( pSim, vCexStore, pPars->nFrames + 1 + nAddFrames, pInitState );
+ Vec_IntFree( vCexStore );
+ clkSim += clock() - clk2;
+ Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings );
+ if ( pPars->fVerbose )
+ Cec_ManRefinedClassPrintStats( pAig, vStatus, r+1, clock() - clk );
+ Vec_StrFree( vStatus );
+ Vec_IntFree( vOutputs );
+//Gia_ManEquivPrintClasses( pAig, 1, 0 );
+ }
+ ABC_FREE( pInitState );
+ // check the base case
+ if ( (!pPars->fLatchCorr || pPars->nFrames > 1) || pPars->nPrefix )
+ {
+ int fChanges = 1;
+ while ( fChanges )
+ {
+ int clkBmc = clock();
+ fChanges = 0;
+ pSrm = Gia_ManCorrSpecReduceInit( pAig, pPars->nFrames, pPars->nPrefix, !pPars->fLatchCorr, &vOutputs, pPars->fUseRings );
+ if ( Gia_ManPoNum(pSrm) == 0 )
+ {
+ Gia_ManStop( pSrm );
+ Vec_IntFree( vOutputs );
+ break;
+ }
+ pParsSat->nBTLimit *= 10;
+ if ( pPars->nPrefix )
+ {
+ pParsSat->nBTLimit = 10000;
+ vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus );
+ }
+ else if ( pPars->fUseCSat )
+ vCexStore = Cbs_ManSolveMiterNc( pSrm, pPars->nBTLimit, &vStatus, 0 );
+ else
+ vCexStore = Cec_ManSatSolveMiter( pSrm, pParsSat, &vStatus );
+ // refine classes with these counter-examples
+ if ( Vec_IntSize(vCexStore) )
+ {
+ clk2 = clock();
+ RetValue = Cec_ManResimulateCounterExamples( pSim, vCexStore, pPars->nFrames + 1 + nAddFrames + pPars->nPrefix, NULL );
+ clkSim += clock() - clk2;
+ Gia_ManCheckRefinements( pAig, vStatus, vOutputs, pSim, pPars->fUseRings );
+ fChanges = 1;
+ }
+ if ( pPars->fVerbose )
+ Cec_ManRefinedClassPrintStats( pAig, vStatus, -1, clock() - clkBmc );
+ // recycle
+ Vec_IntFree( vCexStore );
+ Vec_StrFree( vStatus );
+ Gia_ManStop( pSrm );
+ Vec_IntFree( vOutputs );
+ }
+ }
+ else
+ {
+ if ( pPars->fVerbose )
+ Cec_ManRefinedClassPrintStats( pAig, NULL, r+1, clock() - clk );
+ }
+ // check the overflow
+ if ( r == nIterMax )
+ printf( "The refinement was not finished. The result may be incorrect.\n" );
+ Cec_ManSimStop( pSim );
+ clkTotal = clock() - clkTotal;
+ // report the results
+ if ( pPars->fVerbose )
+ {
+ ABC_PRTP( "Srm ", clkSrm, clkTotal );
+ ABC_PRTP( "Sat ", clkSat, clkTotal );
+ ABC_PRTP( "Sim ", clkSim, clkTotal );
+ ABC_PRTP( "Other", clkTotal-clkSat-clkSrm-clkSim, clkTotal );
+ ABC_PRT( "TOTAL", clkTotal );
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Top-level procedure for register correspondence.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Gia_Man_t * Cec_ManLSCorrespondence( Gia_Man_t * pAig, Cec_ParCor_t * pPars )
+{
+ Gia_Man_t * pNew, * pTemp;
+ int RetValue;
+ RetValue = Cec_ManLSCorrespondenceClasses( pAig, pPars );
+ // derive reduced AIG
+ if ( pPars->fMakeChoices )
+ {
+ pNew = Gia_ManEquivToChoices( pAig, 1 );
+ Gia_ManHasChoices( pNew );
+ }
+ else
+ {
+ Gia_ManEquivImprove( pAig );
+ pNew = Gia_ManCorrReduce( pAig );
+ pNew = Gia_ManSeqCleanup( pTemp = pNew );
+ Gia_ManStop( pTemp );
+ //Gia_WriteAiger( pNew, "reduced.aig", 0, 0 );
+ }
+ // report the results
+ if ( pPars->fVerbose )
+ {
+ printf( "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n",
+ Gia_ManAndNum(pAig), Gia_ManAndNum(pNew),
+ 100.0*(Gia_ManAndNum(pAig)-Gia_ManAndNum(pNew))/(Gia_ManAndNum(pAig)?Gia_ManAndNum(pAig):1),
+ Gia_ManRegNum(pAig), Gia_ManRegNum(pNew),
+ 100.0*(Gia_ManRegNum(pAig)-Gia_ManRegNum(pNew))/(Gia_ManRegNum(pAig)?Gia_ManRegNum(pAig):1) );
+ }
+ return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/cec/cecInt.h b/src/proof/cec/cecInt.h
new file mode 100644
index 00000000..371dedda
--- /dev/null
+++ b/src/proof/cec/cecInt.h
@@ -0,0 +1,225 @@
+/**CFile****************************************************************
+
+ FileName [cecInt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Combinational equivalence checking.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cecInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__cec__cecInt_h
+#define ABC__aig__cec__cecInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include "src/sat/bsat/satSolver.h"
+#include "src/misc/bar/bar.h"
+#include "src/aig/gia/gia.h"
+#include "cec.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+// simulation pattern manager
+typedef struct Cec_ManPat_t_ Cec_ManPat_t;
+struct Cec_ManPat_t_
+{
+ Vec_Int_t * vPattern1; // pattern in terms of primary inputs
+ Vec_Int_t * vPattern2; // pattern in terms of primary inputs
+ Vec_Str_t * vStorage; // storage for compressed patterns
+ int iStart; // position in the array where recent patterns begin
+ int nPats; // total number of recent patterns
+ int nPatsAll; // total number of all patterns
+ int nPatLits; // total number of literals in recent patterns
+ int nPatLitsAll; // total number of literals in all patterns
+ int nPatLitsMin; // total number of literals in minimized recent patterns
+ int nPatLitsMinAll; // total number of literals in minimized all patterns
+ int nSeries; // simulation series
+ int fVerbose; // verbose stats
+ // runtime statistics
+ int timeFind; // detecting the pattern
+ int timeShrink; // minimizing the pattern
+ int timeVerify; // verifying the result of minimisation
+ int timeSort; // sorting literals
+ int timePack; // packing into sim info structures
+ int timeTotal; // total runtime
+ int timeTotalSave; // total runtime for saving
+};
+
+// SAT solving manager
+typedef struct Cec_ManSat_t_ Cec_ManSat_t;
+struct Cec_ManSat_t_
+{
+ // parameters
+ Cec_ParSat_t * pPars;
+ // AIGs used in the package
+ Gia_Man_t * pAig; // the AIG whose outputs are considered
+ Vec_Int_t * vStatus; // status for each output
+ // SAT solving
+ sat_solver * pSat; // recyclable SAT solver
+ int nSatVars; // the counter of SAT variables
+ int * pSatVars; // mapping of each node into its SAT var
+ Vec_Ptr_t * vUsedNodes; // nodes whose SAT vars are assigned
+ int nRecycles; // the number of times SAT solver was recycled
+ int nCallsSince; // the number of calls since the last recycle
+ Vec_Ptr_t * vFanins; // fanins of the CNF node
+ // counter-examples
+ Vec_Int_t * vCex; // the latest counter-example
+ Vec_Int_t * vVisits; // temporary array for visited nodes
+ // SAT calls statistics
+ int nSatUnsat; // the number of proofs
+ int nSatSat; // the number of failure
+ int nSatUndec; // the number of timeouts
+ int nSatTotal; // the number of calls
+ int nCexLits;
+ // conflicts
+ int nConfUnsat; // conflicts in unsat problems
+ int nConfSat; // conflicts in sat problems
+ int nConfUndec; // conflicts in undec problems
+ // runtime stats
+ int timeSatUnsat; // unsat
+ int timeSatSat; // sat
+ int timeSatUndec; // undecided
+ int timeTotal; // total runtime
+};
+
+// combinational simulation manager
+typedef struct Cec_ManSim_t_ Cec_ManSim_t;
+struct Cec_ManSim_t_
+{
+ // parameters
+ Gia_Man_t * pAig; // the AIG to be used for simulation
+ Cec_ParSim_t * pPars; // simulation parameters
+ int nWords; // the number of simulation words
+ // recycable memory
+ int * pSimInfo; // simulation information offsets
+ unsigned * pMems; // allocated simulaton memory
+ int nWordsAlloc; // the number of allocated entries
+ int nMems; // the number of used entries
+ int nMemsMax; // the max number of used entries
+ int MemFree; // next free entry
+ int nWordsOld; // the number of simulation words after previous relink
+ // internal simulation info
+ Vec_Ptr_t * vCiSimInfo; // CI simulation info
+ Vec_Ptr_t * vCoSimInfo; // CO simulation info
+ // counter examples
+ void ** pCexes; // counter-examples for each output
+ int iOut; // first failed output
+ int nOuts; // the number of failed outputs
+ Abc_Cex_t * pCexComb; // counter-example for the first failed output
+ Abc_Cex_t * pBestState; // the state that led to most of the refinements
+ // scoring simulation patterns
+ int * pScores; // counters of refinement for each pattern
+ // temporaries
+ Vec_Int_t * vClassOld; // old class numbers
+ Vec_Int_t * vClassNew; // new class numbers
+ Vec_Int_t * vClassTemp; // temporary storage
+ Vec_Int_t * vRefinedC; // refined const reprs
+};
+
+// combinational simulation manager
+typedef struct Cec_ManFra_t_ Cec_ManFra_t;
+struct Cec_ManFra_t_
+{
+ // parameters
+ Gia_Man_t * pAig; // the AIG to be used for simulation
+ Cec_ParFra_t * pPars; // SAT sweeping parameters
+ // simulation patterns
+ Vec_Int_t * vXorNodes; // nodes used in speculative reduction
+ int nAllProved; // total number of proved nodes
+ int nAllDisproved; // total number of disproved nodes
+ int nAllFailed; // total number of failed nodes
+ // runtime stats
+ int timeSim; // unsat
+ int timePat; // unsat
+ int timeSat; // sat
+ int timeTotal; // total runtime
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== cecCorr.c ============================================================*/
+extern void Cec_ManRefinedClassPrintStats( Gia_Man_t * p, Vec_Str_t * vStatus, int iIter, int Time );
+/*=== cecClass.c ============================================================*/
+extern int Cec_ManSimClassRemoveOne( Cec_ManSim_t * p, int i );
+extern int Cec_ManSimClassesPrepare( Cec_ManSim_t * p, int LevelMax );
+extern int Cec_ManSimClassesRefine( Cec_ManSim_t * p );
+extern int Cec_ManSimSimulateRound( Cec_ManSim_t * p, Vec_Ptr_t * vInfoCis, Vec_Ptr_t * vInfoCos );
+/*=== cecIso.c ============================================================*/
+extern int * Cec_ManDetectIsomorphism( Gia_Man_t * p );
+/*=== cecMan.c ============================================================*/
+extern Cec_ManSat_t * Cec_ManSatCreate( Gia_Man_t * pAig, Cec_ParSat_t * pPars );
+extern void Cec_ManSatPrintStats( Cec_ManSat_t * p );
+extern void Cec_ManSatStop( Cec_ManSat_t * p );
+extern Cec_ManPat_t * Cec_ManPatStart();
+extern void Cec_ManPatPrintStats( Cec_ManPat_t * p );
+extern void Cec_ManPatStop( Cec_ManPat_t * p );
+extern Cec_ManSim_t * Cec_ManSimStart( Gia_Man_t * pAig, Cec_ParSim_t * pPars );
+extern void Cec_ManSimStop( Cec_ManSim_t * p );
+extern Cec_ManFra_t * Cec_ManFraStart( Gia_Man_t * pAig, Cec_ParFra_t * pPars );
+extern void Cec_ManFraStop( Cec_ManFra_t * p );
+/*=== cecPat.c ============================================================*/
+extern void Cec_ManPatSavePattern( Cec_ManPat_t * pPat, Cec_ManSat_t * p, Gia_Obj_t * pObj );
+extern Vec_Ptr_t * Cec_ManPatCollectPatterns( Cec_ManPat_t * pMan, int nInputs, int nWords );
+extern Vec_Ptr_t * Cec_ManPatPackPatterns( Vec_Int_t * vCexStore, int nInputs, int nRegs, int nWordsInit );
+/*=== cecSeq.c ============================================================*/
+extern int Cec_ManSeqResimulate( Cec_ManSim_t * p, Vec_Ptr_t * vInfo );
+extern int Cec_ManSeqResimulateInfo( Gia_Man_t * pAig, Vec_Ptr_t * vSimInfo, Abc_Cex_t * pBestState, int fCheckMiter );
+extern void Cec_ManSeqDeriveInfoInitRandom( Vec_Ptr_t * vInfo, Gia_Man_t * pAig, Abc_Cex_t * pCex );
+extern int Cec_ManCountNonConstOutputs( Gia_Man_t * pAig );
+extern int Cec_ManCheckNonTrivialCands( Gia_Man_t * pAig );
+/*=== cecSolve.c ============================================================*/
+extern int Cec_ObjSatVarValue( Cec_ManSat_t * p, Gia_Obj_t * pObj );
+extern void Cec_ManSatSolve( Cec_ManPat_t * pPat, Gia_Man_t * pAig, Cec_ParSat_t * pPars );
+extern Vec_Str_t * Cec_ManSatSolveSeq( Vec_Ptr_t * vPatts, Gia_Man_t * pAig, Cec_ParSat_t * pPars, int nRegs, int * pnPats );
+extern Vec_Int_t * Cec_ManSatSolveMiter( Gia_Man_t * pAig, Cec_ParSat_t * pPars, Vec_Str_t ** pvStatus );
+extern int Cec_ManSatCheckNode( Cec_ManSat_t * p, Gia_Obj_t * pObj );
+extern int Cec_ManSatCheckNodeTwo( Cec_ManSat_t * p, Gia_Obj_t * pObj1, Gia_Obj_t * pObj2 );
+extern void Cec_ManSavePattern( Cec_ManSat_t * p, Gia_Obj_t * pObj1, Gia_Obj_t * pObj2 );
+extern Vec_Int_t * Cec_ManSatReadCex( Cec_ManSat_t * p );
+/*=== ceFraeep.c ============================================================*/
+extern Gia_Man_t * Cec_ManFraSpecReduction( Cec_ManFra_t * p );
+extern int Cec_ManFraClassesUpdate( Cec_ManFra_t * p, Cec_ManSim_t * pSim, Cec_ManPat_t * pPat, Gia_Man_t * pNew );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/proof/cec/cecIso.c b/src/proof/cec/cecIso.c
new file mode 100644
index 00000000..f1ca2ff7
--- /dev/null
+++ b/src/proof/cec/cecIso.c
@@ -0,0 +1,375 @@
+/**CFile****************************************************************
+
+ FileName [cecIso.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Combinational equivalence checking.]
+
+ Synopsis [Detection of structural isomorphism.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cecIso.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static inline unsigned * Cec_ManIsoInfo( unsigned * pStore, int nWords, int Id ) { return pStore + nWords * Id; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes simulation info for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Gia_ManIsoSimulate( Gia_Obj_t * pObj, int Id, unsigned * pStore, int nWords )
+{
+ unsigned * pInfo = Cec_ManIsoInfo( pStore, nWords, Id );
+ unsigned * pInfo0 = Cec_ManIsoInfo( pStore, nWords, Gia_ObjFaninId0(pObj, Id) );
+ unsigned * pInfo1 = Cec_ManIsoInfo( pStore, nWords, Gia_ObjFaninId1(pObj, Id) );
+ int w;
+ if ( Gia_ObjFaninC0(pObj) )
+ {
+ if ( Gia_ObjFaninC1(pObj) )
+ for ( w = 0; w < nWords; w++ )
+ pInfo[w] = ~(pInfo0[w] | pInfo1[w]);
+ else
+ for ( w = 0; w < nWords; w++ )
+ pInfo[w] = ~pInfo0[w] & pInfo1[w];
+ }
+ else
+ {
+ if ( Gia_ObjFaninC1(pObj) )
+ for ( w = 0; w < nWords; w++ )
+ pInfo[w] = pInfo0[w] & ~pInfo1[w];
+ else
+ for ( w = 0; w < nWords; w++ )
+ pInfo[w] = pInfo0[w] & pInfo1[w];
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Copies simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Gia_ManIsoCopy( int IdDest, int IdSour, unsigned * pStore, int nWords )
+{
+ unsigned * pInfo0 = Cec_ManIsoInfo( pStore, nWords, IdDest );
+ unsigned * pInfo1 = Cec_ManIsoInfo( pStore, nWords, IdSour );
+ int w;
+ for ( w = 0; w < nWords; w++ )
+ pInfo0[w] = pInfo1[w];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares simulation info of two nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Gia_ManIsoEqual( int Id0, int Id1, unsigned * pStore, int nWords )
+{
+ unsigned * pInfo0 = Cec_ManIsoInfo( pStore, nWords, Id0 );
+ unsigned * pInfo1 = Cec_ManIsoInfo( pStore, nWords, Id1 );
+ int w;
+ for ( w = 0; w < nWords; w++ )
+ if ( pInfo0[w] != pInfo1[w] )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Generates random simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Gia_ManIsoRandom( int Id, unsigned * pStore, int nWords )
+{
+ unsigned * pInfo0 = Cec_ManIsoInfo( pStore, nWords, Id );
+ int w;
+ for ( w = 0; w < nWords; w++ )
+ pInfo0[w] = Gia_ManRandom( 0 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes hash key of the simuation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Gia_ManIsoHashKey( int Id, unsigned * pStore, int nWords, int nTableSize )
+{
+ static int s_Primes[16] = {
+ 1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177,
+ 4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 };
+ unsigned * pInfo0 = Cec_ManIsoInfo( pStore, nWords, Id );
+ unsigned uHash = 0;
+ int i;
+ for ( i = 0; i < nWords; i++ )
+ uHash ^= pInfo0[i] * s_Primes[i & 0xf];
+ return (int)(uHash % nTableSize);
+
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds node to the hash table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Gia_ManIsoTableAdd( Gia_Man_t * p, int Id, unsigned * pStore, int nWords, int * pTable, int nTableSize )
+{
+ Gia_Obj_t * pTemp;
+ int Key, Ent, Counter = 0, Color = Gia_ObjColors( p, Id );
+ assert( Color == 1 || Color == 2 );
+ Key = Gia_ManIsoHashKey( Id, pStore, nWords, nTableSize );
+ for ( Ent = pTable[Key], pTemp = (Ent ? Gia_ManObj(p, Ent) : NULL); pTemp;
+ Ent = pTemp->Value, pTemp = (Ent ? Gia_ManObj(p, Ent) : NULL) )
+ {
+ if ( Gia_ObjColors( p, Ent ) != Color )
+ continue;
+ if ( !Gia_ManIsoEqual( Id, Ent, pStore, nWords ) )
+ continue;
+ // found node with the same color and signature - mark it and do not add new node
+ pTemp->fMark0 = 1;
+ return;
+ }
+ // did not find the node with the same color and signature - add new node
+ pTemp = Gia_ManObj( p, Id );
+ assert( pTemp->Value == 0 );
+ assert( pTemp->fMark0 == 0 );
+ pTemp->Value = pTable[Key];
+ pTable[Key] = Id;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Extracts equivalence class candidates from one bin.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Gia_ManIsoExtractClasses( Gia_Man_t * p, int Bin, unsigned * pStore, int nWords, Vec_Int_t * vNodesA, Vec_Int_t * vNodesB )
+{
+ Gia_Obj_t * pTemp;
+ int Ent;
+ Vec_IntClear( vNodesA );
+ Vec_IntClear( vNodesB );
+ for ( Ent = Bin, pTemp = (Ent ? Gia_ManObj(p, Ent) : NULL); pTemp;
+ Ent = pTemp->Value, pTemp = (Ent ? Gia_ManObj(p, Ent) : NULL) )
+ {
+ if ( pTemp->fMark0 )
+ {
+ pTemp->fMark0 = 0;
+ continue;
+ }
+ if ( Gia_ObjColors( p, Ent ) == 1 )
+ Vec_IntPush( vNodesA, Ent );
+ else
+ Vec_IntPush( vNodesB, Ent );
+ }
+ return Vec_IntSize(vNodesA) > 0 && Vec_IntSize(vNodesB) > 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Matches nodes in the extacted classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Gia_ManIsoMatchNodes( int * pIso, unsigned * pStore, int nWords, Vec_Int_t * vNodesA, Vec_Int_t * vNodesB )
+{
+ int k0, k1, IdA, IdB;
+ Vec_IntForEachEntry( vNodesA, IdA, k0 )
+ Vec_IntForEachEntry( vNodesB, IdB, k1 )
+ {
+ if ( Gia_ManIsoEqual( IdA, IdB, pStore, nWords ) )
+ {
+ assert( pIso[IdA] == 0 );
+ assert( pIso[IdB] == 0 );
+ assert( IdA != IdB );
+ pIso[IdA] = IdB;
+ pIso[IdB] = IdA;
+ continue;
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transforms iso into equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManTransformClasses( Gia_Man_t * p )
+{
+ Gia_Obj_t * pObj;
+ int i;
+ assert( p->pReprs && p->pNexts && p->pIso );
+ memset( p->pReprs, 0, sizeof(int) * Gia_ManObjNum(p) );
+ memset( p->pNexts, 0, sizeof(int) * Gia_ManObjNum(p) );
+ Gia_ManForEachObj( p, pObj, i )
+ {
+ p->pReprs[i].iRepr = GIA_VOID;
+ if ( p->pIso[i] && p->pIso[i] < i )
+ {
+ p->pReprs[i].iRepr = p->pIso[i];
+ p->pNexts[p->pIso[i]] = i;
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds node correspondences in the miter.]
+
+ Description [Assumes that the colors are assigned.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int * Cec_ManDetectIsomorphism( Gia_Man_t * p )
+{
+ int nWords = 2;
+ Gia_Obj_t * pObj;
+ Vec_Int_t * vNodesA, * vNodesB;
+ unsigned * pStore, Counter;
+ int i, * pIso, * pTable, nTableSize;
+ // start equivalence classes
+ pIso = ABC_CALLOC( int, Gia_ManObjNum(p) );
+ Gia_ManForEachObj( p, pObj, i )
+ {
+ if ( Gia_ObjIsCo(pObj) )
+ {
+ assert( Gia_ObjColors(p, i) == 0 );
+ continue;
+ }
+ assert( Gia_ObjColors(p, i) );
+ if ( Gia_ObjColors(p, i) == 3 )
+ pIso[i] = i;
+ }
+ // start simulation info
+ pStore = ABC_ALLOC( unsigned, Gia_ManObjNum(p) * nWords );
+ // simulate and create table
+ nTableSize = Abc_PrimeCudd( 100 + Gia_ManObjNum(p)/2 );
+ pTable = ABC_CALLOC( int, nTableSize );
+ Gia_ManCleanValue( p );
+ Gia_ManForEachObj1( p, pObj, i )
+ {
+ if ( Gia_ObjIsCo(pObj) )
+ continue;
+ if ( pIso[i] == 0 ) // simulate
+ Gia_ManIsoSimulate( pObj, i, pStore, nWords );
+ else if ( pIso[i] < i ) // copy
+ Gia_ManIsoCopy( i, pIso[i], pStore, nWords );
+ else // generate
+ Gia_ManIsoRandom( i, pStore, nWords );
+ if ( pIso[i] == 0 )
+ Gia_ManIsoTableAdd( p, i, pStore, nWords, pTable, nTableSize );
+ }
+ // create equivalence classes
+ vNodesA = Vec_IntAlloc( 100 );
+ vNodesB = Vec_IntAlloc( 100 );
+ for ( i = 0; i < nTableSize; i++ )
+ if ( Gia_ManIsoExtractClasses( p, pTable[i], pStore, nWords, vNodesA, vNodesB ) )
+ Gia_ManIsoMatchNodes( pIso, pStore, nWords, vNodesA, vNodesB );
+ Vec_IntFree( vNodesA );
+ Vec_IntFree( vNodesB );
+ // collect info
+ Counter = 0;
+ Gia_ManForEachObj1( p, pObj, i )
+ {
+ Counter += (pIso[i] && pIso[i] < i);
+/*
+ if ( pIso[i] && pIso[i] < i )
+ {
+ if ( (Gia_ObjIsHead(p,pIso[i]) && Gia_ObjRepr(p,i)==pIso[i]) ||
+ (Gia_ObjIsClass(p,pIso[i]) && Gia_ObjRepr(p,i)==Gia_ObjRepr(p,pIso[i])) )
+ Abc_Print( 1, "1" );
+ else
+ Abc_Print( 1, "0" );
+ }
+*/
+ }
+ Abc_Print( 1, "Computed %d pairs of structurally equivalent nodes.\n", Counter );
+// p->pIso = pIso;
+// Cec_ManTransformClasses( p );
+
+ ABC_FREE( pTable );
+ ABC_FREE( pStore );
+ return pIso;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/cec/cecMan.c b/src/proof/cec/cecMan.c
new file mode 100644
index 00000000..f03ec701
--- /dev/null
+++ b/src/proof/cec/cecMan.c
@@ -0,0 +1,297 @@
+/**CFile****************************************************************
+
+ FileName [cecMan.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Combinational equivalence checking.]
+
+ Synopsis [Manager procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cecMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Creates the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cec_ManSat_t * Cec_ManSatCreate( Gia_Man_t * pAig, Cec_ParSat_t * pPars )
+{
+ Cec_ManSat_t * p;
+ // create interpolation manager
+ p = ABC_ALLOC( Cec_ManSat_t, 1 );
+ memset( p, 0, sizeof(Cec_ManSat_t) );
+ p->pPars = pPars;
+ p->pAig = pAig;
+ // SAT solving
+ p->nSatVars = 1;
+ p->pSatVars = ABC_CALLOC( int, Gia_ManObjNum(pAig) );
+ p->vUsedNodes = Vec_PtrAlloc( 1000 );
+ p->vFanins = Vec_PtrAlloc( 100 );
+ p->vCex = Vec_IntAlloc( 100 );
+ p->vVisits = Vec_IntAlloc( 100 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints statistics of the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManSatPrintStats( Cec_ManSat_t * p )
+{
+ Abc_Print( 1, "CO = %8d ", Gia_ManCoNum(p->pAig) );
+ Abc_Print( 1, "AND = %8d ", Gia_ManAndNum(p->pAig) );
+ Abc_Print( 1, "Conf = %5d ", p->pPars->nBTLimit );
+ Abc_Print( 1, "MinVar = %5d ", p->pPars->nSatVarMax );
+ Abc_Print( 1, "MinCalls = %5d\n", p->pPars->nCallsRecycle );
+ Abc_Print( 1, "Unsat calls %6d (%6.2f %%) Ave conf = %8.1f ",
+ p->nSatUnsat, p->nSatTotal? 100.0*p->nSatUnsat/p->nSatTotal : 0.0, p->nSatUnsat? 1.0*p->nConfUnsat/p->nSatUnsat :0.0 );
+ Abc_PrintTimeP( 1, "Time", p->timeSatUnsat, p->timeTotal );
+ Abc_Print( 1, "Sat calls %6d (%6.2f %%) Ave conf = %8.1f ",
+ p->nSatSat, p->nSatTotal? 100.0*p->nSatSat/p->nSatTotal : 0.0, p->nSatSat? 1.0*p->nConfSat/p->nSatSat : 0.0 );
+ Abc_PrintTimeP( 1, "Time", p->timeSatSat, p->timeTotal );
+ Abc_Print( 1, "Undef calls %6d (%6.2f %%) Ave conf = %8.1f ",
+ p->nSatUndec, p->nSatTotal? 100.0*p->nSatUndec/p->nSatTotal : 0.0, p->nSatUndec? 1.0*p->nConfUndec/p->nSatUndec : 0.0 );
+ Abc_PrintTimeP( 1, "Time", p->timeSatUndec, p->timeTotal );
+ Abc_PrintTime( 1, "Total time", p->timeTotal );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManSatStop( Cec_ManSat_t * p )
+{
+ if ( p->pSat )
+ sat_solver_delete( p->pSat );
+ Vec_IntFree( p->vCex );
+ Vec_IntFree( p->vVisits );
+ Vec_PtrFree( p->vUsedNodes );
+ Vec_PtrFree( p->vFanins );
+ ABC_FREE( p->pSatVars );
+ ABC_FREE( p );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Creates AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cec_ManPat_t * Cec_ManPatStart()
+{
+ Cec_ManPat_t * p;
+ p = ABC_CALLOC( Cec_ManPat_t, 1 );
+ p->vStorage = Vec_StrAlloc( 1<<20 );
+ p->vPattern1 = Vec_IntAlloc( 1000 );
+ p->vPattern2 = Vec_IntAlloc( 1000 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManPatPrintStats( Cec_ManPat_t * p )
+{
+ Abc_Print( 1, "Latest: P = %8d. L = %10d. Lm = %10d. Ave = %6.1f. MEM =%6.2f Mb\n",
+ p->nPats, p->nPatLits, p->nPatLitsMin, 1.0 * p->nPatLitsMin/p->nPats,
+ 1.0*(Vec_StrSize(p->vStorage)-p->iStart)/(1<<20) );
+ Abc_Print( 1, "Total: P = %8d. L = %10d. Lm = %10d. Ave = %6.1f. MEM =%6.2f Mb\n",
+ p->nPatsAll, p->nPatLitsAll, p->nPatLitsMinAll, 1.0 * p->nPatLitsMinAll/p->nPatsAll,
+ 1.0*Vec_StrSize(p->vStorage)/(1<<20) );
+ Abc_PrintTimeP( 1, "Finding ", p->timeFind, p->timeTotal );
+ Abc_PrintTimeP( 1, "Shrinking", p->timeShrink, p->timeTotal );
+ Abc_PrintTimeP( 1, "Verifying", p->timeVerify, p->timeTotal );
+ Abc_PrintTimeP( 1, "Sorting ", p->timeSort, p->timeTotal );
+ Abc_PrintTimeP( 1, "Packing ", p->timePack, p->timeTotal );
+ Abc_PrintTime( 1, "TOTAL ", p->timeTotal );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deletes AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManPatStop( Cec_ManPat_t * p )
+{
+ Vec_StrFree( p->vStorage );
+ Vec_IntFree( p->vPattern1 );
+ Vec_IntFree( p->vPattern2 );
+ ABC_FREE( p );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Creates AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cec_ManSim_t * Cec_ManSimStart( Gia_Man_t * pAig, Cec_ParSim_t * pPars )
+{
+ Cec_ManSim_t * p;
+ p = ABC_ALLOC( Cec_ManSim_t, 1 );
+ memset( p, 0, sizeof(Cec_ManSim_t) );
+ p->pAig = pAig;
+ p->pPars = pPars;
+ p->nWords = pPars->nWords;
+ p->pSimInfo = ABC_CALLOC( int, Gia_ManObjNum(pAig) );
+ p->vClassOld = Vec_IntAlloc( 1000 );
+ p->vClassNew = Vec_IntAlloc( 1000 );
+ p->vClassTemp = Vec_IntAlloc( 1000 );
+ p->vRefinedC = Vec_IntAlloc( 10000 );
+ p->vCiSimInfo = Vec_PtrAllocSimInfo( Gia_ManCiNum(p->pAig), pPars->nWords );
+ if ( pPars->fCheckMiter || Gia_ManRegNum(p->pAig) )
+ {
+ p->vCoSimInfo = Vec_PtrAllocSimInfo( Gia_ManCoNum(p->pAig), pPars->nWords );
+ Vec_PtrCleanSimInfo( p->vCoSimInfo, 0, pPars->nWords );
+ }
+ p->iOut = -1;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deletes AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManSimStop( Cec_ManSim_t * p )
+{
+ Vec_IntFree( p->vClassOld );
+ Vec_IntFree( p->vClassNew );
+ Vec_IntFree( p->vClassTemp );
+ Vec_IntFree( p->vRefinedC );
+ if ( p->vCiSimInfo )
+ Vec_PtrFree( p->vCiSimInfo );
+ if ( p->vCoSimInfo )
+ Vec_PtrFree( p->vCoSimInfo );
+ ABC_FREE( p->pScores );
+ ABC_FREE( p->pCexComb );
+ ABC_FREE( p->pCexes );
+ ABC_FREE( p->pMems );
+ ABC_FREE( p->pSimInfo );
+ ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Creates AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cec_ManFra_t * Cec_ManFraStart( Gia_Man_t * pAig, Cec_ParFra_t * pPars )
+{
+ Cec_ManFra_t * p;
+ p = ABC_ALLOC( Cec_ManFra_t, 1 );
+ memset( p, 0, sizeof(Cec_ManFra_t) );
+ p->pAig = pAig;
+ p->pPars = pPars;
+ p->vXorNodes = Vec_IntAlloc( 1000 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deletes AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManFraStop( Cec_ManFra_t * p )
+{
+ Vec_IntFree( p->vXorNodes );
+ ABC_FREE( p );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/cec/cecPat.c b/src/proof/cec/cecPat.c
new file mode 100644
index 00000000..cb1dae46
--- /dev/null
+++ b/src/proof/cec/cecPat.c
@@ -0,0 +1,569 @@
+/**CFile****************************************************************
+
+ FileName [cecPat.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Combinational equivalence checking.]
+
+ Synopsis [Simulation pattern manager.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cecPat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Cec_ManPatStoreNum( Cec_ManPat_t * p, int Num )
+{
+ unsigned x = (unsigned)Num;
+ assert( Num >= 0 );
+ while ( x & ~0x7f )
+ {
+ Vec_StrPush( p->vStorage, (char)((x & 0x7f) | 0x80) );
+ x >>= 7;
+ }
+ Vec_StrPush( p->vStorage, (char)x );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Cec_ManPatRestoreNum( Cec_ManPat_t * p )
+{
+ int ch, i, x = 0;
+ for ( i = 0; (ch = Vec_StrEntry(p->vStorage, p->iStart++)) & 0x80; i++ )
+ x |= (ch & 0x7f) << (7 * i);
+ return x | (ch << (7 * i));
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Cec_ManPatStore( Cec_ManPat_t * p, Vec_Int_t * vPat )
+{
+ int i, Number, NumberPrev;
+ assert( Vec_IntSize(vPat) > 0 );
+ Cec_ManPatStoreNum( p, Vec_IntSize(vPat) );
+ NumberPrev = Vec_IntEntry( vPat, 0 );
+ Cec_ManPatStoreNum( p, NumberPrev );
+ Vec_IntForEachEntryStart( vPat, Number, i, 1 )
+ {
+ assert( NumberPrev < Number );
+ Cec_ManPatStoreNum( p, Number - NumberPrev );
+ NumberPrev = Number;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Cec_ManPatRestore( Cec_ManPat_t * p, Vec_Int_t * vPat )
+{
+ int i, Size, Number;
+ Vec_IntClear( vPat );
+ Size = Cec_ManPatRestoreNum( p );
+ Number = Cec_ManPatRestoreNum( p );
+ Vec_IntPush( vPat, Number );
+ for ( i = 1; i < Size; i++ )
+ {
+ Number += Cec_ManPatRestoreNum( p );
+ Vec_IntPush( vPat, Number );
+ }
+ assert( Vec_IntSize(vPat) == Size );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Derives satisfying assignment.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManPatComputePattern_rec( Cec_ManSat_t * pSat, Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+ int Counter = 0;
+ if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+ return 0;
+ Gia_ObjSetTravIdCurrent(p, pObj);
+ if ( Gia_ObjIsCi(pObj) )
+ {
+ pObj->fMark1 = Cec_ObjSatVarValue( pSat, pObj );
+ return 1;
+ }
+ assert( Gia_ObjIsAnd(pObj) );
+ Counter += Cec_ManPatComputePattern_rec( pSat, p, Gia_ObjFanin0(pObj) );
+ Counter += Cec_ManPatComputePattern_rec( pSat, p, Gia_ObjFanin1(pObj) );
+ pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) &
+ (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj));
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives satisfying assignment.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManPatComputePattern1_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vPat )
+{
+ if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+ return;
+ Gia_ObjSetTravIdCurrent(p, pObj);
+ if ( Gia_ObjIsCi(pObj) )
+ {
+ Vec_IntPush( vPat, Abc_Var2Lit( Gia_ObjCioId(pObj), pObj->fMark1==0 ) );
+ return;
+ }
+ assert( Gia_ObjIsAnd(pObj) );
+ if ( pObj->fMark1 == 1 )
+ {
+ Cec_ManPatComputePattern1_rec( p, Gia_ObjFanin0(pObj), vPat );
+ Cec_ManPatComputePattern1_rec( p, Gia_ObjFanin1(pObj), vPat );
+ }
+ else
+ {
+ assert( (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) == 0 ||
+ (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj)) == 0 );
+ if ( (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) == 0 )
+ Cec_ManPatComputePattern1_rec( p, Gia_ObjFanin0(pObj), vPat );
+ else
+ Cec_ManPatComputePattern1_rec( p, Gia_ObjFanin1(pObj), vPat );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives satisfying assignment.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManPatComputePattern2_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vPat )
+{
+ if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+ return;
+ Gia_ObjSetTravIdCurrent(p, pObj);
+ if ( Gia_ObjIsCi(pObj) )
+ {
+ Vec_IntPush( vPat, Abc_Var2Lit( Gia_ObjCioId(pObj), pObj->fMark1==0 ) );
+ return;
+ }
+ assert( Gia_ObjIsAnd(pObj) );
+ if ( pObj->fMark1 == 1 )
+ {
+ Cec_ManPatComputePattern2_rec( p, Gia_ObjFanin0(pObj), vPat );
+ Cec_ManPatComputePattern2_rec( p, Gia_ObjFanin1(pObj), vPat );
+ }
+ else
+ {
+ assert( (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) == 0 ||
+ (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj)) == 0 );
+ if ( (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj)) == 0 )
+ Cec_ManPatComputePattern2_rec( p, Gia_ObjFanin1(pObj), vPat );
+ else
+ Cec_ManPatComputePattern2_rec( p, Gia_ObjFanin0(pObj), vPat );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives satisfying assignment.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManPatComputePattern3_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+ int Value0, Value1, Value;
+ if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+ return (pObj->fMark1 << 1) | pObj->fMark0;
+ Gia_ObjSetTravIdCurrent(p, pObj);
+ if ( Gia_ObjIsCi(pObj) )
+ {
+ pObj->fMark0 = 1;
+ pObj->fMark1 = 1;
+ return GIA_UND;
+ }
+ assert( Gia_ObjIsAnd(pObj) );
+ Value0 = Cec_ManPatComputePattern3_rec( p, Gia_ObjFanin0(pObj) );
+ Value1 = Cec_ManPatComputePattern3_rec( p, Gia_ObjFanin1(pObj) );
+ Value = Gia_XsimAndCond( Value0, Gia_ObjFaninC0(pObj), Value1, Gia_ObjFaninC1(pObj) );
+ pObj->fMark0 = (Value & 1);
+ pObj->fMark1 = ((Value >> 1) & 1);
+ return Value;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives satisfying assignment.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManPatVerifyPattern( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vPat )
+{
+ Gia_Obj_t * pTemp;
+ int i, Value;
+ Gia_ManIncrementTravId( p );
+ Vec_IntForEachEntry( vPat, Value, i )
+ {
+ pTemp = Gia_ManCi( p, Abc_Lit2Var(Value) );
+// assert( Abc_LitIsCompl(Value) != (int)pTemp->fMark1 );
+ if ( pTemp->fMark1 )
+ {
+ pTemp->fMark0 = 0;
+ pTemp->fMark1 = 1;
+ }
+ else
+ {
+ pTemp->fMark0 = 1;
+ pTemp->fMark1 = 0;
+ }
+ Gia_ObjSetTravIdCurrent( p, pTemp );
+ }
+ Value = Cec_ManPatComputePattern3_rec( p, Gia_ObjFanin0(pObj) );
+ Value = Gia_XsimNotCond( Value, Gia_ObjFaninC0(pObj) );
+ if ( Value != GIA_ONE )
+ Abc_Print( 1, "Cec_ManPatVerifyPattern(): Verification failed.\n" );
+ assert( Value == GIA_ONE );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManPatComputePattern4_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+ if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+ return;
+ Gia_ObjSetTravIdCurrent(p, pObj);
+ pObj->fMark0 = 0;
+ if ( Gia_ObjIsCi(pObj) )
+ return;
+ assert( Gia_ObjIsAnd(pObj) );
+ Cec_ManPatComputePattern4_rec( p, Gia_ObjFanin0(pObj) );
+ Cec_ManPatComputePattern4_rec( p, Gia_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManPatCleanMark0( Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+ assert( Gia_ObjIsCo(pObj) );
+ Gia_ManIncrementTravId( p );
+ Cec_ManPatComputePattern4_rec( p, Gia_ObjFanin0(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManPatSavePattern( Cec_ManPat_t * pMan, Cec_ManSat_t * p, Gia_Obj_t * pObj )
+{
+ Vec_Int_t * vPat;
+ int nPatLits, clk, clkTotal = clock();
+ assert( Gia_ObjIsCo(pObj) );
+ pMan->nPats++;
+ pMan->nPatsAll++;
+ // compute values in the cone of influence
+clk = clock();
+ Gia_ManIncrementTravId( p->pAig );
+ nPatLits = Cec_ManPatComputePattern_rec( p, p->pAig, Gia_ObjFanin0(pObj) );
+ assert( (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) == 1 );
+ pMan->nPatLits += nPatLits;
+ pMan->nPatLitsAll += nPatLits;
+pMan->timeFind += clock() - clk;
+ // compute sensitizing path
+clk = clock();
+ Vec_IntClear( pMan->vPattern1 );
+ Gia_ManIncrementTravId( p->pAig );
+ Cec_ManPatComputePattern1_rec( p->pAig, Gia_ObjFanin0(pObj), pMan->vPattern1 );
+ // compute sensitizing path
+ Vec_IntClear( pMan->vPattern2 );
+ Gia_ManIncrementTravId( p->pAig );
+ Cec_ManPatComputePattern2_rec( p->pAig, Gia_ObjFanin0(pObj), pMan->vPattern2 );
+ // compare patterns
+ vPat = Vec_IntSize(pMan->vPattern1) < Vec_IntSize(pMan->vPattern2) ? pMan->vPattern1 : pMan->vPattern2;
+ pMan->nPatLitsMin += Vec_IntSize(vPat);
+ pMan->nPatLitsMinAll += Vec_IntSize(vPat);
+pMan->timeShrink += clock() - clk;
+ // verify pattern using ternary simulation
+clk = clock();
+ Cec_ManPatVerifyPattern( p->pAig, pObj, vPat );
+pMan->timeVerify += clock() - clk;
+ // sort pattern
+clk = clock();
+ Vec_IntSort( vPat, 0 );
+pMan->timeSort += clock() - clk;
+ // save pattern
+ Cec_ManPatStore( pMan, vPat );
+ pMan->timeTotal += clock() - clkTotal;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Packs patterns into array of simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+*************************************`**********************************/
+int Cec_ManPatCollectTry( Vec_Ptr_t * vInfo, Vec_Ptr_t * vPres, int iBit, int * pLits, int nLits )
+{
+ unsigned * pInfo, * pPres;
+ int i;
+ for ( i = 0; i < nLits; i++ )
+ {
+ pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i]));
+ pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i]));
+ if ( Abc_InfoHasBit( pPres, iBit ) &&
+ Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) )
+ return 0;
+ }
+ for ( i = 0; i < nLits; i++ )
+ {
+ pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i]));
+ pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i]));
+ Abc_InfoSetBit( pPres, iBit );
+ if ( Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) )
+ Abc_InfoXorBit( pInfo, iBit );
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Packs patterns into array of simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Cec_ManPatCollectPatterns( Cec_ManPat_t * pMan, int nInputs, int nWordsInit )
+{
+ Vec_Int_t * vPat = pMan->vPattern1;
+ Vec_Ptr_t * vInfo, * vPres;
+ int k, kMax = -1, nPatterns = 0;
+ int iStartOld = pMan->iStart;
+ int nWords = nWordsInit;
+ int nBits = 32 * nWords;
+ int clk = clock();
+ vInfo = Vec_PtrAllocSimInfo( nInputs, nWords );
+ Gia_ManRandomInfo( vInfo, 0, 0, nWords );
+ vPres = Vec_PtrAllocSimInfo( nInputs, nWords );
+ Vec_PtrCleanSimInfo( vPres, 0, nWords );
+ while ( pMan->iStart < Vec_StrSize(pMan->vStorage) )
+ {
+ nPatterns++;
+ Cec_ManPatRestore( pMan, vPat );
+ for ( k = 1; k < nBits; k++, k += ((k % (32 * nWordsInit)) == 0) )
+ if ( Cec_ManPatCollectTry( vInfo, vPres, k, (int *)Vec_IntArray(vPat), Vec_IntSize(vPat) ) )
+ break;
+ kMax = Abc_MaxInt( kMax, k );
+ if ( k == nBits-1 )
+ {
+ Vec_PtrReallocSimInfo( vInfo );
+ Gia_ManRandomInfo( vInfo, 0, nWords, 2*nWords );
+ Vec_PtrReallocSimInfo( vPres );
+ Vec_PtrCleanSimInfo( vPres, nWords, 2*nWords );
+ nWords *= 2;
+ nBits *= 2;
+ }
+ }
+ Vec_PtrFree( vPres );
+ pMan->nSeries = Vec_PtrReadWordsSimInfo(vInfo) / nWordsInit;
+ pMan->timePack += clock() - clk;
+ pMan->timeTotal += clock() - clk;
+ pMan->iStart = iStartOld;
+ if ( pMan->fVerbose )
+ {
+ Abc_Print( 1, "Total = %5d. Max used = %5d. Full = %5d. Series = %d. ",
+ nPatterns, kMax, nWordsInit*32, pMan->nSeries );
+ ABC_PRT( "Time", clock() - clk );
+ Cec_ManPatPrintStats( pMan );
+ }
+ return vInfo;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Packs patterns into array of simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Cec_ManPatPackPatterns( Vec_Int_t * vCexStore, int nInputs, int nRegs, int nWordsInit )
+{
+ Vec_Int_t * vPat;
+ Vec_Ptr_t * vInfo, * vPres;
+ int k, nSize, iStart, kMax = 0, nPatterns = 0;
+ int nWords = nWordsInit;
+ int nBits = 32 * nWords;
+// int RetValue;
+ assert( nRegs <= nInputs );
+ vPat = Vec_IntAlloc( 100 );
+
+ vInfo = Vec_PtrAllocSimInfo( nInputs, nWords );
+ Vec_PtrCleanSimInfo( vInfo, 0, nWords );
+ Gia_ManRandomInfo( vInfo, nRegs, 0, nWords );
+
+ vPres = Vec_PtrAllocSimInfo( nInputs, nWords );
+ Vec_PtrCleanSimInfo( vPres, 0, nWords );
+ iStart = 0;
+ while ( iStart < Vec_IntSize(vCexStore) )
+ {
+ nPatterns++;
+ // skip the output number
+ iStart++;
+ // get the number of items
+ nSize = Vec_IntEntry( vCexStore, iStart++ );
+ if ( nSize <= 0 )
+ continue;
+ // extract pattern
+ Vec_IntClear( vPat );
+ for ( k = 0; k < nSize; k++ )
+ Vec_IntPush( vPat, Vec_IntEntry( vCexStore, iStart++ ) );
+ // add pattern to storage
+ for ( k = 1; k < nBits; k++, k += ((k % (32 * nWordsInit)) == 0) )
+ if ( Cec_ManPatCollectTry( vInfo, vPres, k, (int *)Vec_IntArray(vPat), Vec_IntSize(vPat) ) )
+ break;
+
+// k = kMax + 1;
+// RetValue = Cec_ManPatCollectTry( vInfo, vPres, k, (int *)Vec_IntArray(vPat), Vec_IntSize(vPat) );
+// assert( RetValue == 1 );
+
+ kMax = Abc_MaxInt( kMax, k );
+ if ( k == nBits-1 )
+ {
+ Vec_PtrReallocSimInfo( vInfo );
+ Vec_PtrCleanSimInfo( vInfo, nWords, 2*nWords );
+ Gia_ManRandomInfo( vInfo, nRegs, nWords, 2*nWords );
+
+ Vec_PtrReallocSimInfo( vPres );
+ Vec_PtrCleanSimInfo( vPres, nWords, 2*nWords );
+ nWords *= 2;
+ nBits *= 2;
+ }
+ }
+// Abc_Print( 1, "packed %d patterns into %d vectors (out of %d)\n", nPatterns, kMax, nBits );
+ Vec_PtrFree( vPres );
+ Vec_IntFree( vPat );
+ return vInfo;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/cec/cecSeq.c b/src/proof/cec/cecSeq.c
new file mode 100644
index 00000000..21ed8656
--- /dev/null
+++ b/src/proof/cec/cecSeq.c
@@ -0,0 +1,448 @@
+/**CFile****************************************************************
+
+ FileName [cecSeq.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Combinational equivalence checking.]
+
+ Synopsis [Refinement of sequential equivalence classes.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cecSeq.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Sets register values from the counter-example.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManSeqDeriveInfoFromCex( Vec_Ptr_t * vInfo, Gia_Man_t * pAig, Abc_Cex_t * pCex )
+{
+ unsigned * pInfo;
+ int k, i, w, nWords;
+ assert( pCex->nBits == pCex->nRegs + pCex->nPis * (pCex->iFrame + 1) );
+ assert( pCex->nBits - pCex->nRegs + Gia_ManRegNum(pAig) <= Vec_PtrSize(vInfo) );
+ nWords = Vec_PtrReadWordsSimInfo( vInfo );
+/*
+ // user register values
+ assert( pCex->nRegs == Gia_ManRegNum(pAig) );
+ for ( k = 0; k < pCex->nRegs; k++ )
+ {
+ pInfo = (unsigned *)Vec_PtrEntry( vInfo, k );
+ for ( w = 0; w < nWords; w++ )
+ pInfo[w] = Abc_InfoHasBit( pCex->pData, k )? ~0 : 0;
+ }
+*/
+ // print warning about register values
+ for ( k = 0; k < pCex->nRegs; k++ )
+ if ( Abc_InfoHasBit( pCex->pData, k ) )
+ break;
+ if ( k < pCex->nRegs )
+ Abc_Print( 0, "The CEX has flop values different from 0, but they are currently not used by \"resim\".\n" );
+
+ // assign zero register values
+ for ( k = 0; k < Gia_ManRegNum(pAig); k++ )
+ {
+ pInfo = (unsigned *)Vec_PtrEntry( vInfo, k );
+ for ( w = 0; w < nWords; w++ )
+ pInfo[w] = 0;
+ }
+ for ( i = pCex->nRegs; i < pCex->nBits; i++ )
+ {
+ pInfo = (unsigned *)Vec_PtrEntry( vInfo, k++ );
+ for ( w = 0; w < nWords; w++ )
+ pInfo[w] = Gia_ManRandom(0);
+ // set simulation pattern and make sure it is second (first will be erased during simulation)
+ pInfo[0] = (pInfo[0] << 1) | Abc_InfoHasBit( pCex->pData, i );
+ pInfo[0] <<= 1;
+ }
+ for ( ; k < Vec_PtrSize(vInfo); k++ )
+ {
+ pInfo = (unsigned *)Vec_PtrEntry( vInfo, k );
+ for ( w = 0; w < nWords; w++ )
+ pInfo[w] = Gia_ManRandom(0);
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets register values from the counter-example.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManSeqDeriveInfoInitRandom( Vec_Ptr_t * vInfo, Gia_Man_t * pAig, Abc_Cex_t * pCex )
+{
+ unsigned * pInfo;
+ int k, w, nWords;
+ nWords = Vec_PtrReadWordsSimInfo( vInfo );
+ assert( pCex == NULL || Gia_ManRegNum(pAig) == pCex->nRegs );
+ assert( Gia_ManRegNum(pAig) <= Vec_PtrSize(vInfo) );
+ for ( k = 0; k < Gia_ManRegNum(pAig); k++ )
+ {
+ pInfo = (unsigned *)Vec_PtrEntry( vInfo, k );
+ for ( w = 0; w < nWords; w++ )
+ pInfo[w] = (pCex && Abc_InfoHasBit(pCex->pData, k))? ~0 : 0;
+ }
+
+ for ( ; k < Vec_PtrSize(vInfo); k++ )
+ {
+ pInfo = (unsigned *)Vec_PtrEntry( vInfo, k );
+ for ( w = 0; w < nWords; w++ )
+ pInfo[w] = Gia_ManRandom( 0 );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resimulates the classes using sequential simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManSeqResimulate( Cec_ManSim_t * p, Vec_Ptr_t * vInfo )
+{
+ unsigned * pInfo0, * pInfo1;
+ int f, i, k, w;
+// assert( Gia_ManRegNum(p->pAig) > 0 );
+ assert( Vec_PtrSize(vInfo) == Gia_ManRegNum(p->pAig) + Gia_ManPiNum(p->pAig) * p->pPars->nFrames );
+ for ( k = 0; k < Gia_ManRegNum(p->pAig); k++ )
+ {
+ pInfo0 = (unsigned *)Vec_PtrEntry( vInfo, k );
+ pInfo1 = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, Gia_ManPoNum(p->pAig) + k );
+ for ( w = 0; w < p->nWords; w++ )
+ pInfo1[w] = pInfo0[w];
+ }
+ for ( f = 0; f < p->pPars->nFrames; f++ )
+ {
+ for ( i = 0; i < Gia_ManPiNum(p->pAig); i++ )
+ {
+ pInfo0 = (unsigned *)Vec_PtrEntry( vInfo, k++ );
+ pInfo1 = (unsigned *)Vec_PtrEntry( p->vCiSimInfo, i );
+ for ( w = 0; w < p->nWords; w++ )
+ pInfo1[w] = pInfo0[w];
+ }
+ for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ )
+ {
+ pInfo0 = (unsigned *)Vec_PtrEntry( p->vCoSimInfo, Gia_ManPoNum(p->pAig) + i );
+ pInfo1 = (unsigned *)Vec_PtrEntry( p->vCiSimInfo, Gia_ManPiNum(p->pAig) + i );
+ for ( w = 0; w < p->nWords; w++ )
+ pInfo1[w] = pInfo0[w];
+ }
+ if ( Cec_ManSimSimulateRound( p, p->vCiSimInfo, p->vCoSimInfo ) )
+ return 1;
+ }
+ assert( k == Vec_PtrSize(vInfo) );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resimulates information to refine equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManSeqResimulateInfo( Gia_Man_t * pAig, Vec_Ptr_t * vSimInfo, Abc_Cex_t * pBestState, int fCheckMiter )
+{
+ Cec_ParSim_t ParsSim, * pParsSim = &ParsSim;
+ Cec_ManSim_t * pSim;
+ int RetValue, clkTotal = clock();
+ assert( (Vec_PtrSize(vSimInfo) - Gia_ManRegNum(pAig)) % Gia_ManPiNum(pAig) == 0 );
+ Cec_ManSimSetDefaultParams( pParsSim );
+ pParsSim->nFrames = (Vec_PtrSize(vSimInfo) - Gia_ManRegNum(pAig)) / Gia_ManPiNum(pAig);
+ pParsSim->nWords = Vec_PtrReadWordsSimInfo( vSimInfo );
+ pParsSim->fCheckMiter = fCheckMiter;
+ Gia_ManSetRefs( pAig );
+ pSim = Cec_ManSimStart( pAig, pParsSim );
+ if ( pBestState )
+ pSim->pBestState = pBestState;
+ RetValue = Cec_ManSeqResimulate( pSim, vSimInfo );
+ pSim->pBestState = NULL;
+ Cec_ManSimStop( pSim );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resimuates one counter-example to refine equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManSeqResimulateCounter( Gia_Man_t * pAig, Cec_ParSim_t * pPars, Abc_Cex_t * pCex )
+{
+ Vec_Ptr_t * vSimInfo;
+ int RetValue, clkTotal = clock();
+ if ( pCex == NULL )
+ {
+ Abc_Print( 1, "Cec_ManSeqResimulateCounter(): Counter-example is not available.\n" );
+ return -1;
+ }
+ if ( pAig->pReprs == NULL )
+ {
+ Abc_Print( 1, "Cec_ManSeqResimulateCounter(): Equivalence classes are not available.\n" );
+ return -1;
+ }
+ if ( Gia_ManRegNum(pAig) == 0 )
+ {
+ Abc_Print( 1, "Cec_ManSeqResimulateCounter(): Not a sequential AIG.\n" );
+ return -1;
+ }
+// if ( Gia_ManRegNum(pAig) != pCex->nRegs || Gia_ManPiNum(pAig) != pCex->nPis )
+ if ( Gia_ManPiNum(pAig) != pCex->nPis )
+ {
+ Abc_Print( 1, "Cec_ManSeqResimulateCounter(): The number of PIs in the AIG and the counter-example differ.\n" );
+ return -1;
+ }
+ if ( pPars->fVerbose )
+ Abc_Print( 1, "Resimulating %d timeframes.\n", pPars->nFrames + pCex->iFrame + 1 );
+ Gia_ManRandom( 1 );
+ vSimInfo = Vec_PtrAllocSimInfo( Gia_ManRegNum(pAig) +
+ Gia_ManPiNum(pAig) * (pPars->nFrames + pCex->iFrame + 1), 1 );
+ Cec_ManSeqDeriveInfoFromCex( vSimInfo, pAig, pCex );
+ if ( pPars->fVerbose )
+ Gia_ManEquivPrintClasses( pAig, 0, 0 );
+ RetValue = Cec_ManSeqResimulateInfo( pAig, vSimInfo, NULL, pPars->fCheckMiter );
+ if ( pPars->fVerbose )
+ Gia_ManEquivPrintClasses( pAig, 0, 0 );
+ Vec_PtrFree( vSimInfo );
+ if ( pPars->fVerbose )
+ ABC_PRT( "Time", clock() - clkTotal );
+// if ( RetValue && pPars->fCheckMiter )
+// Abc_Print( 1, "Cec_ManSeqResimulateCounter(): An output of the miter is asserted!\n" );
+ return RetValue;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of POs that are not const0 cands.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManCountNonConstOutputs( Gia_Man_t * pAig )
+{
+ Gia_Obj_t * pObj;
+ int i, Counter = 0;
+ if ( pAig->pReprs == NULL )
+ return -1;
+ Gia_ManForEachPo( pAig, pObj, i )
+ if ( !Gia_ObjIsConst( pAig, Gia_ObjFaninId0p(pAig, pObj) ) )
+ Counter++;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of POs that are not const0 cands.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManCheckNonTrivialCands( Gia_Man_t * pAig )
+{
+ Gia_Obj_t * pObj;
+ int i, RetValue = 0;
+ if ( pAig->pReprs == NULL )
+ return 0;
+ // label internal nodes driving POs
+ Gia_ManForEachPo( pAig, pObj, i )
+ Gia_ObjFanin0(pObj)->fMark0 = 1;
+ // check if there are non-labled equivs
+ Gia_ManForEachObj( pAig, pObj, i )
+ if ( Gia_ObjIsCand(pObj) && !pObj->fMark0 && Gia_ObjRepr(pAig, i) != GIA_VOID )
+ {
+ RetValue = 1;
+ break;
+ }
+ // clean internal nodes driving POs
+ Gia_ManForEachPo( pAig, pObj, i )
+ Gia_ObjFanin0(pObj)->fMark0 = 0;
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs semiformal refinement of equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManSeqSemiformal( Gia_Man_t * pAig, Cec_ParSmf_t * pPars )
+{
+ int nAddFrames = 16; // additional timeframes to simulate
+ int nCountNoRef = 0;
+ int nFramesReal;
+ Cec_ParSat_t ParsSat, * pParsSat = &ParsSat;
+ Vec_Ptr_t * vSimInfo;
+ Vec_Str_t * vStatus;
+ Abc_Cex_t * pState;
+ Gia_Man_t * pSrm, * pReduce, * pAux;
+ int r, nPats, RetValue = 0;
+ if ( pAig->pReprs == NULL )
+ {
+ Abc_Print( 1, "Cec_ManSeqSemiformal(): Equivalence classes are not available.\n" );
+ return -1;
+ }
+ if ( Gia_ManRegNum(pAig) == 0 )
+ {
+ Abc_Print( 1, "Cec_ManSeqSemiformal(): Not a sequential AIG.\n" );
+ return -1;
+ }
+ Gia_ManRandom( 1 );
+ // prepare starting pattern
+ pState = Abc_CexAlloc( Gia_ManRegNum(pAig), 0, 0 );
+ pState->iFrame = -1;
+ pState->iPo = -1;
+ // prepare SAT solving
+ Cec_ManSatSetDefaultParams( pParsSat );
+ pParsSat->nBTLimit = pPars->nBTLimit;
+ pParsSat->fVerbose = pPars->fVerbose;
+ if ( pParsSat->fVerbose )
+ {
+ Abc_Print( 1, "Starting: " );
+ Gia_ManEquivPrintClasses( pAig, 0, 0 );
+ }
+ // perform the given number of BMC rounds
+ Gia_ManCleanMark0( pAig );
+ for ( r = 0; r < pPars->nRounds; r++ )
+ {
+ if ( !Cec_ManCheckNonTrivialCands(pAig) )
+ {
+ Abc_Print( 1, "Cec_ManSeqSemiformal: There are only trivial equiv candidates left (PO drivers). Quitting.\n" );
+ break;
+ }
+// Abc_CexPrint( pState );
+ // derive speculatively reduced model
+// pSrm = Gia_ManSpecReduceInit( pAig, pState, pPars->nFrames, pPars->fDualOut );
+ pSrm = Gia_ManSpecReduceInitFrames( pAig, pState, pPars->nFrames, &nFramesReal, pPars->fDualOut, pPars->nMinOutputs );
+ if ( pSrm == NULL )
+ {
+ Abc_Print( 1, "Quitting refinement because miter could not be unrolled.\n" );
+ break;
+ }
+ assert( Gia_ManRegNum(pSrm) == 0 && Gia_ManPiNum(pSrm) == (Gia_ManPiNum(pAig) * nFramesReal) );
+ if ( pPars->fVerbose )
+ Abc_Print( 1, "Unrolled for %d frames.\n", nFramesReal );
+ // allocate room for simulation info
+ vSimInfo = Vec_PtrAllocSimInfo( Gia_ManRegNum(pAig) +
+ Gia_ManPiNum(pAig) * (nFramesReal + nAddFrames), pPars->nWords );
+ Cec_ManSeqDeriveInfoInitRandom( vSimInfo, pAig, pState );
+ // fill in simulation info with counter-examples
+ vStatus = Cec_ManSatSolveSeq( vSimInfo, pSrm, pParsSat, Gia_ManRegNum(pAig), &nPats );
+ Vec_StrFree( vStatus );
+ Gia_ManStop( pSrm );
+ // resimulate and refine the classes
+ RetValue = Cec_ManSeqResimulateInfo( pAig, vSimInfo, pState, pPars->fCheckMiter );
+ Vec_PtrFree( vSimInfo );
+ assert( pState->iPo >= 0 ); // hit counter
+ pState->iPo = -1;
+ if ( pPars->fVerbose )
+ {
+ Abc_Print( 1, "BMC = %3d ", nPats );
+ Gia_ManEquivPrintClasses( pAig, 0, 0 );
+ }
+
+ // write equivalence classes
+ Gia_WriteAiger( pAig, "gore.aig", 0, 0 );
+ // reduce the model
+ pReduce = Gia_ManSpecReduce( pAig, 0, 0, 1, 0, 0 );
+ if ( pReduce )
+ {
+ pReduce = Gia_ManSeqStructSweep( pAux = pReduce, 1, 1, 0 );
+ Gia_ManStop( pAux );
+ Gia_WriteAiger( pReduce, "gsrm.aig", 0, 0 );
+// Abc_Print( 1, "Speculatively reduced model was written into file \"%s\".\n", "gsrm.aig" );
+// Gia_ManPrintStatsShort( pReduce );
+ Gia_ManStop( pReduce );
+ }
+
+ if ( RetValue )
+ {
+ Abc_Print( 1, "Cec_ManSeqSemiformal(): An output of the miter is asserted. Refinement stopped.\n" );
+ break;
+ }
+ // decide when to stop
+ if ( nPats > 0 )
+ nCountNoRef = 0;
+ else if ( ++nCountNoRef == pPars->nNonRefines )
+ break;
+ }
+ ABC_FREE( pState );
+ 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 );
+ }
+ return RetValue;
+}
+
+//&r s13207.aig; &ps; &equiv; &ps; &semi -R 2 -vm
+//&r bug/50/temp.aig; &ps; &equiv -smv; &semi -v
+//r mentor/1_05c.blif; st; &get; &ps; &equiv -smv; &semi -mv
+//&r bug/50/hdl1.aig; &ps; &equiv -smv; &semi -mv; &srm; &r gsrm.aig; &ps
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/cec/cecSim.c b/src/proof/cec/cecSim.c
new file mode 100644
index 00000000..92f8fc2e
--- /dev/null
+++ b/src/proof/cec/cecSim.c
@@ -0,0 +1,53 @@
+/**CFile****************************************************************
+
+ FileName [cecSim.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Combinational equivalence checking.]
+
+ Synopsis [Simulation manager.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cecSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/cec/cecSolve.c b/src/proof/cec/cecSolve.c
new file mode 100644
index 00000000..bd7202e4
--- /dev/null
+++ b/src/proof/cec/cecSolve.c
@@ -0,0 +1,1023 @@
+/**CFile****************************************************************
+
+ FileName [cecSolve.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Combinational equivalence checking.]
+
+ Synopsis [Performs one round of SAT solving.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cecSolve.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int Cec_ObjSatNum( Cec_ManSat_t * p, Gia_Obj_t * pObj ) { return p->pSatVars[Gia_ObjId(p->pAig,pObj)]; }
+static inline void Cec_ObjSetSatNum( Cec_ManSat_t * p, Gia_Obj_t * pObj, int Num ) { p->pSatVars[Gia_ObjId(p->pAig,pObj)] = Num; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Returns value of the SAT variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ObjSatVarValue( Cec_ManSat_t * p, Gia_Obj_t * pObj )
+{
+ return sat_solver_var_value( p->pSat, Cec_ObjSatNum(p, pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Addes clauses to the solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_AddClausesMux( Cec_ManSat_t * p, Gia_Obj_t * pNode )
+{
+ Gia_Obj_t * pNodeI, * pNodeT, * pNodeE;
+ int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE;
+
+ assert( !Gia_IsComplement( pNode ) );
+ assert( Gia_ObjIsMuxType( pNode ) );
+ // get nodes (I = if, T = then, E = else)
+ pNodeI = Gia_ObjRecognizeMux( pNode, &pNodeT, &pNodeE );
+ // get the variable numbers
+ VarF = Cec_ObjSatNum(p,pNode);
+ VarI = Cec_ObjSatNum(p,pNodeI);
+ VarT = Cec_ObjSatNum(p,Gia_Regular(pNodeT));
+ VarE = Cec_ObjSatNum(p,Gia_Regular(pNodeE));
+ // get the complementation flags
+ fCompT = Gia_IsComplement(pNodeT);
+ fCompE = Gia_IsComplement(pNodeE);
+
+ // f = ITE(i, t, e)
+
+ // i' + t' + f
+ // i' + t + f'
+ // i + e' + f
+ // i + e + f'
+
+ // create four clauses
+ pLits[0] = toLitCond(VarI, 1);
+ pLits[1] = toLitCond(VarT, 1^fCompT);
+ pLits[2] = toLitCond(VarF, 0);
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( Gia_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+ pLits[0] = toLitCond(VarI, 1);
+ pLits[1] = toLitCond(VarT, 0^fCompT);
+ pLits[2] = toLitCond(VarF, 1);
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( Gia_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+ pLits[0] = toLitCond(VarI, 0);
+ pLits[1] = toLitCond(VarE, 1^fCompE);
+ pLits[2] = toLitCond(VarF, 0);
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+ pLits[0] = toLitCond(VarI, 0);
+ pLits[1] = toLitCond(VarE, 0^fCompE);
+ pLits[2] = toLitCond(VarF, 1);
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+
+ // two additional clauses
+ // t' & e' -> f'
+ // t & e -> f
+
+ // t + e + f'
+ // t' + e' + f
+
+ if ( VarT == VarE )
+ {
+// assert( fCompT == !fCompE );
+ return;
+ }
+
+ pLits[0] = toLitCond(VarT, 0^fCompT);
+ pLits[1] = toLitCond(VarE, 0^fCompE);
+ pLits[2] = toLitCond(VarF, 1);
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( Gia_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+ pLits[0] = toLitCond(VarT, 1^fCompT);
+ pLits[1] = toLitCond(VarE, 1^fCompE);
+ pLits[2] = toLitCond(VarF, 0);
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( Gia_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Addes clauses to the solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_AddClausesSuper( Cec_ManSat_t * p, Gia_Obj_t * pNode, Vec_Ptr_t * vSuper )
+{
+ Gia_Obj_t * pFanin;
+ int * pLits, nLits, RetValue, i;
+ assert( !Gia_IsComplement(pNode) );
+ assert( Gia_ObjIsAnd( pNode ) );
+ // create storage for literals
+ nLits = Vec_PtrSize(vSuper) + 1;
+ pLits = ABC_ALLOC( int, nLits );
+ // suppose AND-gate is A & B = C
+ // add !A => !C or A + !C
+ Vec_PtrForEachEntry( Gia_Obj_t *, vSuper, pFanin, i )
+ {
+ pLits[0] = toLitCond(Cec_ObjSatNum(p,Gia_Regular(pFanin)), Gia_IsComplement(pFanin));
+ pLits[1] = toLitCond(Cec_ObjSatNum(p,pNode), 1);
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( Gia_Regular(pFanin)->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( pNode->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+ assert( RetValue );
+ }
+ // add A & B => C or !A + !B + C
+ Vec_PtrForEachEntry( Gia_Obj_t *, vSuper, pFanin, i )
+ {
+ pLits[i] = toLitCond(Cec_ObjSatNum(p,Gia_Regular(pFanin)), !Gia_IsComplement(pFanin));
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( Gia_Regular(pFanin)->fPhase ) pLits[i] = lit_neg( pLits[i] );
+ }
+ }
+ pLits[nLits-1] = toLitCond(Cec_ObjSatNum(p,pNode), 0);
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( pNode->fPhase ) pLits[nLits-1] = lit_neg( pLits[nLits-1] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits );
+ assert( RetValue );
+ ABC_FREE( pLits );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_CollectSuper_rec( Gia_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes )
+{
+ // if the new node is complemented or a PI, another gate begins
+ if ( Gia_IsComplement(pObj) || Gia_ObjIsCi(pObj) ||
+ (!fFirst && Gia_ObjValue(pObj) > 1) ||
+ (fUseMuxes && Gia_ObjIsMuxType(pObj)) )
+ {
+ Vec_PtrPushUnique( vSuper, pObj );
+ return;
+ }
+ // go through the branches
+ Cec_CollectSuper_rec( Gia_ObjChild0(pObj), vSuper, 0, fUseMuxes );
+ Cec_CollectSuper_rec( Gia_ObjChild1(pObj), vSuper, 0, fUseMuxes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_CollectSuper( Gia_Obj_t * pObj, int fUseMuxes, Vec_Ptr_t * vSuper )
+{
+ assert( !Gia_IsComplement(pObj) );
+ assert( !Gia_ObjIsCi(pObj) );
+ Vec_PtrClear( vSuper );
+ Cec_CollectSuper_rec( pObj, vSuper, 1, fUseMuxes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the solver clause database.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ObjAddToFrontier( Cec_ManSat_t * p, Gia_Obj_t * pObj, Vec_Ptr_t * vFrontier )
+{
+ assert( !Gia_IsComplement(pObj) );
+ if ( Cec_ObjSatNum(p,pObj) )
+ return;
+ assert( Cec_ObjSatNum(p,pObj) == 0 );
+ if ( Gia_ObjIsConst0(pObj) )
+ return;
+ Vec_PtrPush( p->vUsedNodes, pObj );
+ Cec_ObjSetSatNum( p, pObj, p->nSatVars++ );
+ if ( Gia_ObjIsAnd(pObj) )
+ Vec_PtrPush( vFrontier, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the solver clause database.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_CnfNodeAddToSolver( Cec_ManSat_t * p, Gia_Obj_t * pObj )
+{
+ Vec_Ptr_t * vFrontier;
+ Gia_Obj_t * pNode, * pFanin;
+ int i, k, fUseMuxes = 1;
+ // quit if CNF is ready
+ if ( Cec_ObjSatNum(p,pObj) )
+ return;
+ if ( Gia_ObjIsCi(pObj) )
+ {
+ Vec_PtrPush( p->vUsedNodes, pObj );
+ Cec_ObjSetSatNum( p, pObj, p->nSatVars++ );
+ sat_solver_setnvars( p->pSat, p->nSatVars );
+ return;
+ }
+ assert( Gia_ObjIsAnd(pObj) );
+ // start the frontier
+ vFrontier = Vec_PtrAlloc( 100 );
+ Cec_ObjAddToFrontier( p, pObj, vFrontier );
+ // explore nodes in the frontier
+ Vec_PtrForEachEntry( Gia_Obj_t *, vFrontier, pNode, i )
+ {
+ // create the supergate
+ assert( Cec_ObjSatNum(p,pNode) );
+ if ( fUseMuxes && Gia_ObjIsMuxType(pNode) )
+ {
+ Vec_PtrClear( p->vFanins );
+ Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin0( Gia_ObjFanin0(pNode) ) );
+ Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin0( Gia_ObjFanin1(pNode) ) );
+ Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin1( Gia_ObjFanin0(pNode) ) );
+ Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin1( Gia_ObjFanin1(pNode) ) );
+ Vec_PtrForEachEntry( Gia_Obj_t *, p->vFanins, pFanin, k )
+ Cec_ObjAddToFrontier( p, Gia_Regular(pFanin), vFrontier );
+ Cec_AddClausesMux( p, pNode );
+ }
+ else
+ {
+ Cec_CollectSuper( pNode, fUseMuxes, p->vFanins );
+ Vec_PtrForEachEntry( Gia_Obj_t *, p->vFanins, pFanin, k )
+ Cec_ObjAddToFrontier( p, Gia_Regular(pFanin), vFrontier );
+ Cec_AddClausesSuper( p, pNode, p->vFanins );
+ }
+ assert( Vec_PtrSize(p->vFanins) > 1 );
+ }
+ Vec_PtrFree( vFrontier );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Recycles the SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManSatSolverRecycle( Cec_ManSat_t * p )
+{
+ int Lit;
+ if ( p->pSat )
+ {
+ Gia_Obj_t * pObj;
+ int i;
+ Vec_PtrForEachEntry( Gia_Obj_t *, p->vUsedNodes, pObj, i )
+ Cec_ObjSetSatNum( p, pObj, 0 );
+ Vec_PtrClear( p->vUsedNodes );
+// memset( p->pSatVars, 0, sizeof(int) * Gia_ManObjNumMax(p->pAigTotal) );
+ sat_solver_delete( p->pSat );
+ }
+ p->pSat = sat_solver_new();
+ p->pSat->factors = ABC_CALLOC( double, 1 );
+ sat_solver_setnvars( p->pSat, 1000 );
+ // var 0 is not used
+ // var 1 is reserved for const0 node - add the clause
+ p->nSatVars = 1;
+// p->nSatVars = 0;
+ Lit = toLitCond( p->nSatVars, 1 );
+ if ( p->pPars->fPolarFlip )
+ Lit = lit_neg( Lit );
+ sat_solver_addclause( p->pSat, &Lit, &Lit + 1 );
+ Cec_ObjSetSatNum( p, Gia_ManConst0(p->pAig), p->nSatVars++ );
+
+ p->nRecycles++;
+ p->nCallsSince = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets variable activities in the cone.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_SetActivityFactors_rec( Cec_ManSat_t * p, Gia_Obj_t * pObj, int LevelMin, int LevelMax )
+{
+ float dActConeBumpMax = 20.0;
+ int iVar;
+ // skip visited variables
+ if ( Gia_ObjIsTravIdCurrent(p->pAig, pObj) )
+ return;
+ Gia_ObjSetTravIdCurrent(p->pAig, pObj);
+ // add the PI to the list
+ if ( Gia_ObjLevel(p->pAig, pObj) <= LevelMin || Gia_ObjIsCi(pObj) )
+ return;
+ // set the factor of this variable
+ // (LevelMax-LevelMin) / (pObj->Level-LevelMin) = p->pPars->dActConeBumpMax / ThisBump
+ if ( (iVar = Cec_ObjSatNum(p,pObj)) )
+ {
+ p->pSat->factors[iVar] = dActConeBumpMax * (Gia_ObjLevel(p->pAig, pObj) - LevelMin)/(LevelMax - LevelMin);
+ veci_push(&p->pSat->act_vars, iVar);
+ }
+ // explore the fanins
+ Cec_SetActivityFactors_rec( p, Gia_ObjFanin0(pObj), LevelMin, LevelMax );
+ Cec_SetActivityFactors_rec( p, Gia_ObjFanin1(pObj), LevelMin, LevelMax );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets variable activities in the cone.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_SetActivityFactors( Cec_ManSat_t * p, Gia_Obj_t * pObj )
+{
+ float dActConeRatio = 0.5;
+ int LevelMin, LevelMax;
+ // reset the active variables
+ veci_resize(&p->pSat->act_vars, 0);
+ // prepare for traversal
+ Gia_ManIncrementTravId( p->pAig );
+ // determine the min and max level to visit
+ assert( dActConeRatio > 0 && dActConeRatio < 1 );
+ LevelMax = Gia_ObjLevel(p->pAig,pObj);
+ LevelMin = (int)(LevelMax * (1.0 - dActConeRatio));
+ // traverse
+ Cec_SetActivityFactors_rec( p, pObj, LevelMin, LevelMax );
+//Cec_PrintActivity( p );
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Runs equivalence test for the two nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManSatCheckNode( Cec_ManSat_t * p, Gia_Obj_t * pObj )
+{
+ Gia_Obj_t * pObjR = Gia_Regular(pObj);
+ int nBTLimit = p->pPars->nBTLimit;
+ int Lit, RetValue, status, clk, clk2, nConflicts;
+
+ if ( pObj == Gia_ManConst0(p->pAig) )
+ return 1;
+ if ( pObj == Gia_ManConst1(p->pAig) )
+ {
+ assert( 0 );
+ return 0;
+ }
+
+ p->nCallsSince++; // experiment with this!!!
+ p->nSatTotal++;
+
+ // check if SAT solver needs recycling
+ if ( p->pSat == NULL ||
+ (p->pPars->nSatVarMax &&
+ p->nSatVars > p->pPars->nSatVarMax &&
+ p->nCallsSince > p->pPars->nCallsRecycle) )
+ Cec_ManSatSolverRecycle( p );
+
+ // if the nodes do not have SAT variables, allocate them
+clk2 = clock();
+ Cec_CnfNodeAddToSolver( p, pObjR );
+//ABC_PRT( "cnf", clock() - clk2 );
+//Abc_Print( 1, "%d \n", p->pSat->size );
+
+clk2 = clock();
+// Cec_SetActivityFactors( p, pObjR );
+//ABC_PRT( "act", clock() - clk2 );
+
+ // propage unit clauses
+ if ( p->pSat->qtail != p->pSat->qhead )
+ {
+ status = sat_solver_simplify(p->pSat);
+ assert( status != 0 );
+ assert( p->pSat->qtail == p->pSat->qhead );
+ }
+
+ // solve under assumptions
+ // A = 1; B = 0 OR A = 1; B = 1
+ Lit = toLitCond( Cec_ObjSatNum(p,pObjR), Gia_IsComplement(pObj) );
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( pObjR->fPhase ) Lit = lit_neg( Lit );
+ }
+//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 );
+clk = clock();
+ nConflicts = p->pSat->stats.conflicts;
+
+clk2 = clock();
+ RetValue = sat_solver_solve( p->pSat, &Lit, &Lit + 1,
+ (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+//ABC_PRT( "sat", clock() - clk2 );
+
+ if ( RetValue == l_False )
+ {
+p->timeSatUnsat += clock() - clk;
+ Lit = lit_neg( Lit );
+ RetValue = sat_solver_addclause( p->pSat, &Lit, &Lit + 1 );
+ assert( RetValue );
+ p->nSatUnsat++;
+ p->nConfUnsat += p->pSat->stats.conflicts - nConflicts;
+//Abc_Print( 1, "UNSAT after %d conflicts\n", p->pSat->stats.conflicts - nConflicts );
+ return 1;
+ }
+ else if ( RetValue == l_True )
+ {
+p->timeSatSat += clock() - clk;
+ p->nSatSat++;
+ p->nConfSat += p->pSat->stats.conflicts - nConflicts;
+//Abc_Print( 1, "SAT after %d conflicts\n", p->pSat->stats.conflicts - nConflicts );
+ return 0;
+ }
+ else // if ( RetValue == l_Undef )
+ {
+p->timeSatUndec += clock() - clk;
+ p->nSatUndec++;
+ p->nConfUndec += p->pSat->stats.conflicts - nConflicts;
+//Abc_Print( 1, "UNDEC after %d conflicts\n", p->pSat->stats.conflicts - nConflicts );
+ return -1;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Runs equivalence test for the two nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManSatCheckNodeTwo( Cec_ManSat_t * p, Gia_Obj_t * pObj1, Gia_Obj_t * pObj2 )
+{
+ Gia_Obj_t * pObjR1 = Gia_Regular(pObj1);
+ Gia_Obj_t * pObjR2 = Gia_Regular(pObj2);
+ int nBTLimit = p->pPars->nBTLimit;
+ int Lits[2], RetValue, status, clk, clk2, nConflicts;
+
+ if ( pObj1 == Gia_ManConst0(p->pAig) || pObj2 == Gia_ManConst0(p->pAig) || pObj1 == Gia_Not(pObj2) )
+ return 1;
+ if ( pObj1 == Gia_ManConst1(p->pAig) && (pObj2 == NULL || pObj2 == Gia_ManConst1(p->pAig)) )
+ {
+ assert( 0 );
+ return 0;
+ }
+
+ p->nCallsSince++; // experiment with this!!!
+ p->nSatTotal++;
+
+ // check if SAT solver needs recycling
+ if ( p->pSat == NULL ||
+ (p->pPars->nSatVarMax &&
+ p->nSatVars > p->pPars->nSatVarMax &&
+ p->nCallsSince > p->pPars->nCallsRecycle) )
+ Cec_ManSatSolverRecycle( p );
+
+ // if the nodes do not have SAT variables, allocate them
+clk2 = clock();
+ Cec_CnfNodeAddToSolver( p, pObjR1 );
+ Cec_CnfNodeAddToSolver( p, pObjR2 );
+//ABC_PRT( "cnf", clock() - clk2 );
+//Abc_Print( 1, "%d \n", p->pSat->size );
+
+clk2 = clock();
+// Cec_SetActivityFactors( p, pObjR1 );
+// Cec_SetActivityFactors( p, pObjR2 );
+//ABC_PRT( "act", clock() - clk2 );
+
+ // propage unit clauses
+ if ( p->pSat->qtail != p->pSat->qhead )
+ {
+ status = sat_solver_simplify(p->pSat);
+ assert( status != 0 );
+ assert( p->pSat->qtail == p->pSat->qhead );
+ }
+
+ // solve under assumptions
+ // A = 1; B = 0 OR A = 1; B = 1
+ Lits[0] = toLitCond( Cec_ObjSatNum(p,pObjR1), Gia_IsComplement(pObj1) );
+ Lits[1] = toLitCond( Cec_ObjSatNum(p,pObjR2), Gia_IsComplement(pObj2) );
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( pObjR1->fPhase ) Lits[0] = lit_neg( Lits[0] );
+ if ( pObjR2->fPhase ) Lits[1] = lit_neg( Lits[1] );
+ }
+//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 );
+clk = clock();
+ nConflicts = p->pSat->stats.conflicts;
+
+clk2 = clock();
+ RetValue = sat_solver_solve( p->pSat, Lits, Lits + 2,
+ (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+//ABC_PRT( "sat", clock() - clk2 );
+
+ if ( RetValue == l_False )
+ {
+p->timeSatUnsat += clock() - clk;
+ Lits[0] = lit_neg( Lits[0] );
+ Lits[1] = lit_neg( Lits[1] );
+ RetValue = sat_solver_addclause( p->pSat, Lits, Lits + 2 );
+ assert( RetValue );
+ p->nSatUnsat++;
+ p->nConfUnsat += p->pSat->stats.conflicts - nConflicts;
+//Abc_Print( 1, "UNSAT after %d conflicts\n", p->pSat->stats.conflicts - nConflicts );
+ return 1;
+ }
+ else if ( RetValue == l_True )
+ {
+p->timeSatSat += clock() - clk;
+ p->nSatSat++;
+ p->nConfSat += p->pSat->stats.conflicts - nConflicts;
+//Abc_Print( 1, "SAT after %d conflicts\n", p->pSat->stats.conflicts - nConflicts );
+ return 0;
+ }
+ else // if ( RetValue == l_Undef )
+ {
+p->timeSatUndec += clock() - clk;
+ p->nSatUndec++;
+ p->nConfUndec += p->pSat->stats.conflicts - nConflicts;
+//Abc_Print( 1, "UNDEC after %d conflicts\n", p->pSat->stats.conflicts - nConflicts );
+ return -1;
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs one round of solving for the POs of the AIG.]
+
+ Description [Labels the nodes that have been proved (pObj->fMark1)
+ and returns the set of satisfying assignments.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManSatSolve( Cec_ManPat_t * pPat, Gia_Man_t * pAig, Cec_ParSat_t * pPars )
+{
+ Bar_Progress_t * pProgress = NULL;
+ Cec_ManSat_t * p;
+ Gia_Obj_t * pObj;
+ int i, status, clk = clock(), clk2;
+ // reset the manager
+ if ( pPat )
+ {
+ pPat->iStart = Vec_StrSize(pPat->vStorage);
+ pPat->nPats = 0;
+ pPat->nPatLits = 0;
+ pPat->nPatLitsMin = 0;
+ }
+ Gia_ManSetPhase( pAig );
+ Gia_ManLevelNum( pAig );
+ Gia_ManIncrementTravId( pAig );
+ p = Cec_ManSatCreate( pAig, pPars );
+ pProgress = Bar_ProgressStart( stdout, Gia_ManPoNum(pAig) );
+ Gia_ManForEachCo( pAig, pObj, i )
+ {
+ if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) )
+ {
+ pObj->fMark0 = 0;
+ pObj->fMark1 = 1;
+ continue;
+ }
+ Bar_ProgressUpdate( pProgress, i, "SAT..." );
+clk2 = clock();
+ status = Cec_ManSatCheckNode( p, Gia_ObjChild0(pObj) );
+ pObj->fMark0 = (status == 0);
+ pObj->fMark1 = (status == 1);
+/*
+ if ( status == -1 )
+ {
+ Gia_Man_t * pTemp = Gia_ManDupDfsCone( pAig, pObj );
+ Gia_WriteAiger( pTemp, "gia_hard.aig", 0, 0 );
+ Gia_ManStop( pTemp );
+ Abc_Print( 1, "Dumping hard cone into file \"%s\".\n", "gia_hard.aig" );
+ }
+*/
+ if ( status != 0 )
+ continue;
+ // save the pattern
+ if ( pPat )
+ {
+ int clk3 = clock();
+ Cec_ManPatSavePattern( pPat, p, pObj );
+ pPat->timeTotalSave += clock() - clk3;
+ }
+ // quit if one of them is solved
+ if ( pPars->fCheckMiter )
+ break;
+ }
+ p->timeTotal = clock() - clk;
+ Bar_ProgressStop( pProgress );
+ if ( pPars->fVerbose )
+ Cec_ManSatPrintStats( p );
+ Cec_ManSatStop( p );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns the pattern stored.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Cec_ManSatReadCex( Cec_ManSat_t * pSat )
+{
+ return pSat->vCex;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Save values in the cone of influence.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManSatSolveSeq_rec( Cec_ManSat_t * pSat, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Ptr_t * vInfo, int iPat, int nRegs )
+{
+ if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+ return;
+ Gia_ObjSetTravIdCurrent(p, pObj);
+ if ( Gia_ObjIsCi(pObj) )
+ {
+ unsigned * pInfo = (unsigned *)Vec_PtrEntry( vInfo, nRegs + Gia_ObjCioId(pObj) );
+ if ( Cec_ObjSatVarValue( pSat, pObj ) != Abc_InfoHasBit( pInfo, iPat ) )
+ Abc_InfoXorBit( pInfo, iPat );
+ pSat->nCexLits++;
+// Vec_IntPush( pSat->vCex, Abc_Var2Lit( Gia_ObjCioId(pObj), !Cec_ObjSatVarValue(pSat, pObj) ) );
+ return;
+ }
+ assert( Gia_ObjIsAnd(pObj) );
+ Cec_ManSatSolveSeq_rec( pSat, p, Gia_ObjFanin0(pObj), vInfo, iPat, nRegs );
+ Cec_ManSatSolveSeq_rec( pSat, p, Gia_ObjFanin1(pObj), vInfo, iPat, nRegs );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs one round of solving for the POs of the AIG.]
+
+ Description [Labels the nodes that have been proved (pObj->fMark1)
+ and returns the set of satisfying assignments.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Str_t * Cec_ManSatSolveSeq( Vec_Ptr_t * vPatts, Gia_Man_t * pAig, Cec_ParSat_t * pPars, int nRegs, int * pnPats )
+{
+ Bar_Progress_t * pProgress = NULL;
+ Vec_Str_t * vStatus;
+ Cec_ManSat_t * p;
+ Gia_Obj_t * pObj;
+ int iPat = 0, nPatsInit, nPats;
+ int i, status, clk = clock();
+ nPatsInit = nPats = 32 * Vec_PtrReadWordsSimInfo(vPatts);
+ Gia_ManSetPhase( pAig );
+ Gia_ManLevelNum( pAig );
+ Gia_ManIncrementTravId( pAig );
+ p = Cec_ManSatCreate( pAig, pPars );
+ vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) );
+ pProgress = Bar_ProgressStart( stdout, Gia_ManPoNum(pAig) );
+ Gia_ManForEachCo( pAig, pObj, i )
+ {
+ Bar_ProgressUpdate( pProgress, i, "SAT..." );
+ if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) )
+ {
+ if ( Gia_ObjFaninC0(pObj) )
+ {
+// Abc_Print( 1, "Constant 1 output of SRM!!!\n" );
+ Vec_StrPush( vStatus, 0 );
+ }
+ else
+ {
+// Abc_Print( 1, "Constant 0 output of SRM!!!\n" );
+ Vec_StrPush( vStatus, 1 );
+ }
+ continue;
+ }
+ status = Cec_ManSatCheckNode( p, Gia_ObjChild0(pObj) );
+//Abc_Print( 1, "output %d status = %d\n", i, status );
+ Vec_StrPush( vStatus, (char)status );
+ if ( status != 0 )
+ continue;
+ // resize storage
+ if ( iPat == nPats )
+ {
+ int nWords = Vec_PtrReadWordsSimInfo(vPatts);
+ Vec_PtrReallocSimInfo( vPatts );
+ Vec_PtrCleanSimInfo( vPatts, nWords, 2*nWords );
+ nPats = 32 * Vec_PtrReadWordsSimInfo(vPatts);
+ }
+ if ( iPat % nPatsInit == 0 )
+ iPat++;
+ // save the pattern
+ Gia_ManIncrementTravId( pAig );
+// Vec_IntClear( p->vCex );
+ Cec_ManSatSolveSeq_rec( p, pAig, Gia_ObjFanin0(pObj), vPatts, iPat++, nRegs );
+// Gia_SatVerifyPattern( pAig, pObj, p->vCex, p->vVisits );
+// Cec_ManSatAddToStore( p->vCexStore, p->vCex );
+// if ( iPat == nPats )
+// break;
+ // quit if one of them is solved
+// if ( pPars->fFirstStop )
+// break;
+// if ( iPat == 32 * 15 * 16 - 1 )
+// break;
+ }
+ p->timeTotal = clock() - clk;
+ Bar_ProgressStop( pProgress );
+ if ( pPars->fVerbose )
+ Cec_ManSatPrintStats( p );
+// Abc_Print( 1, "Total number of cex literals = %d. (Ave = %d)\n", p->nCexLits, p->nCexLits/p->nSatSat );
+ Cec_ManSatStop( p );
+ if ( pnPats )
+ *pnPats = iPat-1;
+ return vStatus;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Save values in the cone of influence.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out )
+{
+ int i, Entry;
+ Vec_IntPush( vCexStore, Out );
+ if ( vCex == NULL ) // timeout
+ {
+ Vec_IntPush( vCexStore, -1 );
+ return;
+ }
+ // write the counter-example
+ Vec_IntPush( vCexStore, Vec_IntSize(vCex) );
+ Vec_IntForEachEntry( vCex, Entry, i )
+ Vec_IntPush( vCexStore, Entry );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Save values in the cone of influence.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManSatSolveMiter_rec( Cec_ManSat_t * pSat, Gia_Man_t * p, Gia_Obj_t * pObj )
+{
+ if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+ return;
+ Gia_ObjSetTravIdCurrent(p, pObj);
+ if ( Gia_ObjIsCi(pObj) )
+ {
+ pSat->nCexLits++;
+ Vec_IntPush( pSat->vCex, Abc_Var2Lit( Gia_ObjCioId(pObj), !Cec_ObjSatVarValue(pSat, pObj) ) );
+ return;
+ }
+ assert( Gia_ObjIsAnd(pObj) );
+ Cec_ManSatSolveMiter_rec( pSat, p, Gia_ObjFanin0(pObj) );
+ Cec_ManSatSolveMiter_rec( pSat, p, Gia_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Save patterns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManSavePattern( Cec_ManSat_t * p, Gia_Obj_t * pObj1, Gia_Obj_t * pObj2 )
+{
+ Vec_IntClear( p->vCex );
+ Gia_ManIncrementTravId( p->pAig );
+ Cec_ManSatSolveMiter_rec( p, p->pAig, Gia_Regular(pObj1) );
+ if ( pObj2 )
+ Cec_ManSatSolveMiter_rec( p, p->pAig, Gia_Regular(pObj2) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs one round of solving for the POs of the AIG.]
+
+ Description [Labels the nodes that have been proved (pObj->fMark1)
+ and returns the set of satisfying assignments.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Cec_ManSatSolveMiter( Gia_Man_t * pAig, Cec_ParSat_t * pPars, Vec_Str_t ** pvStatus )
+{
+ Bar_Progress_t * pProgress = NULL;
+ Vec_Int_t * vCexStore;
+ Vec_Str_t * vStatus;
+ Cec_ManSat_t * p;
+ Gia_Obj_t * pObj;
+ int i, status, clk = clock();
+ // prepare AIG
+ Gia_ManSetPhase( pAig );
+ Gia_ManLevelNum( pAig );
+ Gia_ManIncrementTravId( pAig );
+ // create resulting data-structures
+ vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) );
+ vCexStore = Vec_IntAlloc( 10000 );
+ // perform solving
+ p = Cec_ManSatCreate( pAig, pPars );
+ pProgress = Bar_ProgressStart( stdout, Gia_ManPoNum(pAig) );
+ Gia_ManForEachCo( pAig, pObj, i )
+ {
+ Vec_IntClear( p->vCex );
+ Bar_ProgressUpdate( pProgress, i, "SAT..." );
+ if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) )
+ {
+ if ( Gia_ObjFaninC0(pObj) )
+ {
+// Abc_Print( 1, "Constant 1 output of SRM!!!\n" );
+ Cec_ManSatAddToStore( vCexStore, p->vCex, i ); // trivial counter-example
+ Vec_StrPush( vStatus, 0 );
+ }
+ else
+ {
+// Abc_Print( 1, "Constant 0 output of SRM!!!\n" );
+ Vec_StrPush( vStatus, 1 );
+ }
+ continue;
+ }
+ status = Cec_ManSatCheckNode( p, Gia_ObjChild0(pObj) );
+ Vec_StrPush( vStatus, (char)status );
+ if ( status == -1 )
+ {
+ Cec_ManSatAddToStore( vCexStore, NULL, i ); // timeout
+ continue;
+ }
+ if ( status == 1 )
+ continue;
+ assert( status == 0 );
+ // save the pattern
+// Gia_ManIncrementTravId( pAig );
+// Cec_ManSatSolveMiter_rec( p, pAig, Gia_ObjFanin0(pObj) );
+ Cec_ManSavePattern( p, Gia_ObjFanin0(pObj), NULL );
+// Gia_SatVerifyPattern( pAig, pObj, p->vCex, p->vVisits );
+ Cec_ManSatAddToStore( vCexStore, p->vCex, i );
+ }
+ p->timeTotal = clock() - clk;
+ Bar_ProgressStop( pProgress );
+// if ( pPars->fVerbose )
+// Cec_ManSatPrintStats( p );
+ Cec_ManSatStop( p );
+ *pvStatus = vStatus;
+ return vCexStore;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/cec/cecSweep.c b/src/proof/cec/cecSweep.c
new file mode 100644
index 00000000..4523810e
--- /dev/null
+++ b/src/proof/cec/cecSweep.c
@@ -0,0 +1,299 @@
+/**CFile****************************************************************
+
+ FileName [cecSweep.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Combinational equivalence checking.]
+
+ Synopsis [SAT sweeping manager.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cecSweep.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs limited speculative reduction.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Gia_Man_t * Cec_ManFraSpecReduction( Cec_ManFra_t * p )
+{
+ Gia_Man_t * pNew, * pTemp;
+ Gia_Obj_t * pObj, * pRepr = NULL;
+ int iRes0, iRes1, iRepr, iNode, iMiter;
+ int i, fCompl, * piCopies, * pDepths;
+ Gia_ManSetPhase( p->pAig );
+ Vec_IntClear( p->vXorNodes );
+ if ( p->pPars->nLevelMax )
+ Gia_ManLevelNum( p->pAig );
+ pNew = Gia_ManStart( Gia_ManObjNum(p->pAig) );
+ pNew->pName = Abc_UtilStrsav( p->pAig->pName );
+ Gia_ManHashAlloc( pNew );
+ piCopies = ABC_FALLOC( int, Gia_ManObjNum(p->pAig) );
+ pDepths = ABC_CALLOC( int, Gia_ManObjNum(p->pAig) );
+ piCopies[0] = 0;
+ Gia_ManForEachObj1( p->pAig, pObj, i )
+ {
+ if ( Gia_ObjIsCi(pObj) )
+ {
+ piCopies[i] = Gia_ManAppendCi( pNew );
+ continue;
+ }
+ if ( Gia_ObjIsCo(pObj) )
+ continue;
+ if ( piCopies[Gia_ObjFaninId0(pObj,i)] == -1 ||
+ piCopies[Gia_ObjFaninId1(pObj,i)] == -1 )
+ continue;
+ iRes0 = Abc_LitNotCond( piCopies[Gia_ObjFaninId0(pObj,i)], Gia_ObjFaninC0(pObj) );
+ iRes1 = Abc_LitNotCond( piCopies[Gia_ObjFaninId1(pObj,i)], Gia_ObjFaninC1(pObj) );
+ iNode = piCopies[i] = Gia_ManHashAnd( pNew, iRes0, iRes1 );
+ pDepths[i] = Abc_MaxInt( pDepths[Gia_ObjFaninId0(pObj,i)], pDepths[Gia_ObjFaninId1(pObj,i)] );
+ if ( Gia_ObjRepr(p->pAig, i) == GIA_VOID || Gia_ObjFailed(p->pAig, i) )
+ continue;
+ assert( Gia_ObjRepr(p->pAig, i) < i );
+ iRepr = piCopies[Gia_ObjRepr(p->pAig, i)];
+ if ( iRepr == -1 )
+ continue;
+ if ( Abc_LitRegular(iNode) == Abc_LitRegular(iRepr) )
+ continue;
+ if ( p->pPars->nLevelMax &&
+ (Gia_ObjLevel(p->pAig, pObj) > p->pPars->nLevelMax ||
+ Gia_ObjLevel(p->pAig, pRepr) > p->pPars->nLevelMax) )
+ continue;
+ if ( p->pPars->fDualOut )
+ {
+// if ( i % 1000 == 0 && Gia_ObjRepr(p->pAig, i) )
+// Gia_ManEquivPrintOne( p->pAig, Gia_ObjRepr(p->pAig, i), 0 );
+ if ( p->pPars->fColorDiff )
+ {
+ if ( !Gia_ObjDiffColors( p->pAig, Gia_ObjRepr(p->pAig, i), i ) )
+ continue;
+ }
+ else
+ {
+ if ( !Gia_ObjDiffColors2( p->pAig, Gia_ObjRepr(p->pAig, i), i ) )
+ continue;
+ }
+ }
+ pRepr = Gia_ManObj( p->pAig, Gia_ObjRepr(p->pAig, i) );
+ fCompl = Gia_ObjPhaseReal(pObj) ^ Gia_ObjPhaseReal(pRepr);
+ piCopies[i] = Abc_LitNotCond( iRepr, fCompl );
+ if ( Gia_ObjProved(p->pAig, i) )
+ continue;
+ // produce speculative miter
+ iMiter = Gia_ManHashXor( pNew, iNode, piCopies[i] );
+ Gia_ManAppendCo( pNew, iMiter );
+ Vec_IntPush( p->vXorNodes, Gia_ObjRepr(p->pAig, i) );
+ Vec_IntPush( p->vXorNodes, i );
+ // add to the depth of this node
+ pDepths[i] = 1 + Abc_MaxInt( pDepths[i], pDepths[Gia_ObjRepr(p->pAig, i)] );
+ if ( p->pPars->nDepthMax && pDepths[i] >= p->pPars->nDepthMax )
+ piCopies[i] = -1;
+ }
+ ABC_FREE( piCopies );
+ ABC_FREE( pDepths );
+ Gia_ManHashStop( pNew );
+ Gia_ManSetRegNum( pNew, 0 );
+ pNew = Gia_ManCleanup( pTemp = pNew );
+ Gia_ManStop( pTemp );
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManFraClassesUpdate_rec( Gia_Obj_t * pObj )
+{
+ int Result;
+ if ( pObj->fMark0 )
+ return 1;
+ if ( Gia_ObjIsCi(pObj) || Gia_ObjIsConst0(pObj) )
+ return 0;
+ Result = (Cec_ManFraClassesUpdate_rec( Gia_ObjFanin0(pObj) ) |
+ Cec_ManFraClassesUpdate_rec( Gia_ObjFanin1(pObj) ));
+ return pObj->fMark0 = Result;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates simulation info for this round.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_ManFraCreateInfo( Cec_ManSim_t * p, Vec_Ptr_t * vCiInfo, Vec_Ptr_t * vInfo, int nSeries )
+{
+ unsigned * pRes0, * pRes1;
+ int i, w;
+ for ( i = 0; i < Gia_ManCiNum(p->pAig); i++ )
+ {
+ pRes0 = (unsigned *)Vec_PtrEntry( vCiInfo, i );
+ pRes1 = (unsigned *)Vec_PtrEntry( vInfo, i );
+ pRes1 += p->nWords * nSeries;
+ for ( w = 0; w < p->nWords; w++ )
+ pRes0[w] = pRes1[w];
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates equivalence classes using the patterns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_ManFraClassesUpdate( Cec_ManFra_t * p, Cec_ManSim_t * pSim, Cec_ManPat_t * pPat, Gia_Man_t * pNew )
+{
+ Vec_Ptr_t * vInfo;
+ Gia_Obj_t * pObj, * pObjOld, * pReprOld;
+ int i, k, iRepr, iNode, clk;
+clk = clock();
+ vInfo = Cec_ManPatCollectPatterns( pPat, Gia_ManCiNum(p->pAig), pSim->nWords );
+p->timePat += clock() - clk;
+clk = clock();
+ if ( vInfo != NULL )
+ {
+ Gia_ManSetRefs( p->pAig );
+ for ( i = 0; i < pPat->nSeries; i++ )
+ {
+ Cec_ManFraCreateInfo( pSim, pSim->vCiSimInfo, vInfo, i );
+ if ( Cec_ManSimSimulateRound( pSim, pSim->vCiSimInfo, pSim->vCoSimInfo ) )
+ {
+ Vec_PtrFree( vInfo );
+ return 1;
+ }
+ }
+ Vec_PtrFree( vInfo );
+ }
+p->timeSim += clock() - clk;
+ assert( Vec_IntSize(p->vXorNodes) == 2*Gia_ManCoNum(pNew) );
+ // mark the transitive fanout of failed nodes
+ if ( p->pPars->nDepthMax != 1 )
+ {
+ Gia_ManCleanMark0( p->pAig );
+ Gia_ManCleanMark1( p->pAig );
+ Gia_ManForEachCo( pNew, pObj, k )
+ {
+ iRepr = Vec_IntEntry( p->vXorNodes, 2*k );
+ iNode = Vec_IntEntry( p->vXorNodes, 2*k+1 );
+ if ( pObj->fMark0 == 0 && pObj->fMark1 == 1 ) // proved
+ continue;
+// Gia_ManObj(p->pAig, iRepr)->fMark0 = 1;
+ Gia_ManObj(p->pAig, iNode)->fMark0 = 1;
+ }
+ // mark the nodes reachable through the failed nodes
+ Gia_ManForEachAnd( p->pAig, pObjOld, k )
+ pObjOld->fMark0 |= (Gia_ObjFanin0(pObjOld)->fMark0 | Gia_ObjFanin1(pObjOld)->fMark0);
+ // unmark the disproved nodes
+ Gia_ManForEachCo( pNew, pObj, k )
+ {
+ iRepr = Vec_IntEntry( p->vXorNodes, 2*k );
+ iNode = Vec_IntEntry( p->vXorNodes, 2*k+1 );
+ if ( pObj->fMark0 == 0 && pObj->fMark1 == 1 ) // proved
+ continue;
+ pObjOld = Gia_ManObj(p->pAig, iNode);
+ assert( pObjOld->fMark0 == 1 );
+ if ( Gia_ObjFanin0(pObjOld)->fMark0 == 0 && Gia_ObjFanin1(pObjOld)->fMark0 == 0 )
+ pObjOld->fMark1 = 1;
+ }
+ // clean marks
+ Gia_ManForEachAnd( p->pAig, pObjOld, k )
+ if ( pObjOld->fMark1 )
+ {
+ pObjOld->fMark0 = 0;
+ pObjOld->fMark1 = 0;
+ }
+ }
+ // set the results
+ p->nAllProved = p->nAllDisproved = p->nAllFailed = 0;
+ Gia_ManForEachCo( pNew, pObj, k )
+ {
+ iRepr = Vec_IntEntry( p->vXorNodes, 2*k );
+ iNode = Vec_IntEntry( p->vXorNodes, 2*k+1 );
+ pReprOld = Gia_ManObj(p->pAig, iRepr);
+ pObjOld = Gia_ManObj(p->pAig, iNode);
+ if ( pObj->fMark1 )
+ { // proved
+ assert( pObj->fMark0 == 0 );
+ assert( !Gia_ObjProved(p->pAig, iNode) );
+ if ( pReprOld->fMark0 == 0 && pObjOld->fMark0 == 0 )
+// if ( pObjOld->fMark0 == 0 )
+ {
+ assert( iRepr == Gia_ObjRepr(p->pAig, iNode) );
+ Gia_ObjSetProved( p->pAig, iNode );
+ p->nAllProved++;
+ }
+ }
+ else if ( pObj->fMark0 )
+ { // disproved
+ assert( pObj->fMark1 == 0 );
+ if ( pReprOld->fMark0 == 0 && pObjOld->fMark0 == 0 )
+// if ( pObjOld->fMark0 == 0 )
+ {
+ if ( iRepr == Gia_ObjRepr(p->pAig, iNode) )
+ Abc_Print( 1, "Cec_ManFraClassesUpdate(): Error! Node is not refined!\n" );
+ p->nAllDisproved++;
+ }
+ }
+ else
+ { // failed
+ assert( pObj->fMark0 == 0 );
+ assert( pObj->fMark1 == 0 );
+ assert( !Gia_ObjFailed(p->pAig, iNode) );
+ assert( !Gia_ObjProved(p->pAig, iNode) );
+ Gia_ObjSetFailed( p->pAig, iNode );
+ p->nAllFailed++;
+ }
+ }
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/cec/cecSynth.c b/src/proof/cec/cecSynth.c
new file mode 100644
index 00000000..21470dd4
--- /dev/null
+++ b/src/proof/cec/cecSynth.c
@@ -0,0 +1,380 @@
+/**CFile****************************************************************
+
+ FileName [cecSynth.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Combinational equivalence checking.]
+
+ Synopsis [Partitioned sequential synthesis.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: cecSynth.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "cecInt.h"
+#include "src/aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Populate sequential synthesis parameters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cec_SeqSynthesisSetDefaultParams( Cec_ParSeq_t * p )
+{
+ memset( p, 0, sizeof(Cec_ParSeq_t) );
+ p->fUseLcorr = 0; // enables latch correspondence
+ p->fUseScorr = 0; // enables signal correspondence
+ p->nBTLimit = 1000; // (scorr/lcorr) conflict limit at a node
+ p->nFrames = 1; // (scorr only) the number of timeframes
+ p->nLevelMax = -1; // (scorr only) the max number of levels
+ p->fConsts = 1; // (scl only) merging constants
+ p->fEquivs = 1; // (scl only) merging equivalences
+ p->fUseMiniSat = 0; // enables MiniSat in lcorr/scorr
+ p->nMinDomSize = 100; // the size of minimum clock domain
+ p->fVeryVerbose = 0; // verbose stats
+ p->fVerbose = 0; // verbose stats
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_SeqReadMinDomSize( Cec_ParSeq_t * p )
+{
+ return p->nMinDomSize;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_SeqReadVerbose( Cec_ParSeq_t * p )
+{
+ return p->fVerbose;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes partitioning of registers.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManRegCreatePart( Gia_Man_t * p, Vec_Int_t * vPart, int * pnCountPis, int * pnCountRegs, int ** ppMapBack )
+{
+ Gia_Man_t * pNew;
+ Gia_Obj_t * pObj;
+ Vec_Int_t * vNodes, * vRoots;
+ int i, iOut, nCountPis, nCountRegs;
+ int * pMapBack;
+ // collect/mark nodes/PIs in the DFS order from the roots
+ Gia_ManIncrementTravId( p );
+ vRoots = Vec_IntAlloc( Vec_IntSize(vPart) );
+ Vec_IntForEachEntry( vPart, iOut, i )
+ Vec_IntPush( vRoots, Gia_ObjId(p, Gia_ManCo(p, Gia_ManPoNum(p)+iOut)) );
+ vNodes = Gia_ManCollectNodesCis( p, Vec_IntArray(vRoots), Vec_IntSize(vRoots) );
+ Vec_IntFree( vRoots );
+ // unmark register outputs
+ Vec_IntForEachEntry( vPart, iOut, i )
+ Gia_ObjSetTravIdPrevious( p, Gia_ManCi(p, Gia_ManPiNum(p)+iOut) );
+ // count pure PIs
+ nCountPis = nCountRegs = 0;
+ Gia_ManForEachPi( p, pObj, i )
+ nCountPis += Gia_ObjIsTravIdCurrent(p, pObj);
+ // count outputs of other registers
+ Gia_ManForEachRo( p, pObj, i )
+ nCountRegs += Gia_ObjIsTravIdCurrent(p, pObj); // should be !Gia_... ???
+ if ( pnCountPis )
+ *pnCountPis = nCountPis;
+ if ( pnCountRegs )
+ *pnCountRegs = nCountRegs;
+ // clean old manager
+ Gia_ManFillValue(p);
+ Gia_ManConst0(p)->Value = 0;
+ // create the new manager
+ pNew = Gia_ManStart( Vec_IntSize(vNodes) );
+ // create the PIs
+ Gia_ManForEachCi( p, pObj, i )
+ if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+ pObj->Value = Gia_ManAppendCi(pNew);
+ // add variables for the register outputs
+ // create fake POs to hold the register outputs
+ Vec_IntForEachEntry( vPart, iOut, i )
+ {
+ pObj = Gia_ManCi(p, Gia_ManPiNum(p)+iOut);
+ pObj->Value = Gia_ManAppendCi(pNew);
+ Gia_ManAppendCo( pNew, pObj->Value );
+ Gia_ObjSetTravIdCurrent( p, pObj ); // added
+ }
+ // create the nodes
+ Gia_ManForEachObjVec( vNodes, p, pObj, i )
+ if ( Gia_ObjIsAnd(pObj) )
+ pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
+ // add real POs for the registers
+ Vec_IntForEachEntry( vPart, iOut, i )
+ {
+ pObj = Gia_ManCo( p, Gia_ManPoNum(p)+iOut );
+ Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
+ }
+ Gia_ManSetRegNum( pNew, Vec_IntSize(vPart) );
+ // create map
+ if ( ppMapBack )
+ {
+ pMapBack = ABC_FALLOC( int, Gia_ManObjNum(pNew) );
+ // map constant nodes
+ pMapBack[0] = 0;
+ // logic cones of register outputs
+ Gia_ManForEachObjVec( vNodes, p, pObj, i )
+ {
+// pObjNew = Aig_Regular(pObj->pData);
+// pMapBack[pObjNew->Id] = pObj->Id;
+ assert( Abc_Lit2Var(Gia_ObjValue(pObj)) >= 0 );
+ assert( Abc_Lit2Var(Gia_ObjValue(pObj)) < Gia_ManObjNum(pNew) );
+ pMapBack[ Abc_Lit2Var(Gia_ObjValue(pObj)) ] = Gia_ObjId(p, pObj);
+ }
+ // map register outputs
+ Vec_IntForEachEntry( vPart, iOut, i )
+ {
+ pObj = Gia_ManCi(p, Gia_ManPiNum(p)+iOut);
+// pObjNew = pObj->pData;
+// pMapBack[pObjNew->Id] = pObj->Id;
+ assert( Abc_Lit2Var(Gia_ObjValue(pObj)) >= 0 );
+ assert( Abc_Lit2Var(Gia_ObjValue(pObj)) < Gia_ManObjNum(pNew) );
+ pMapBack[ Abc_Lit2Var(Gia_ObjValue(pObj)) ] = Gia_ObjId(p, pObj);
+ }
+ *ppMapBack = pMapBack;
+ }
+ Vec_IntFree( vNodes );
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfers the classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Gia_TransferMappedClasses( Gia_Man_t * pPart, int * pMapBack, int * pReprs )
+{
+ Gia_Obj_t * pObj;
+ int i, Id1, Id2, nClasses;
+ if ( pPart->pReprs == NULL )
+ return 0;
+ nClasses = 0;
+ Gia_ManForEachObj( pPart, pObj, i )
+ {
+ if ( Gia_ObjRepr(pPart, i) == GIA_VOID )
+ continue;
+ assert( i < Gia_ManObjNum(pPart) );
+ assert( Gia_ObjRepr(pPart, i) < Gia_ManObjNum(pPart) );
+ Id1 = pMapBack[ i ];
+ Id2 = pMapBack[ Gia_ObjRepr(pPart, i) ];
+ if ( Id1 == Id2 )
+ continue;
+ if ( Id1 < Id2 )
+ pReprs[Id2] = Id1;
+ else
+ pReprs[Id1] = Id2;
+ nClasses++;
+ }
+ return nClasses;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Gia_ManFindRepr_rec( int * pReprs, int Id )
+{
+ if ( pReprs[Id] == 0 )
+ return 0;
+ if ( pReprs[Id] == ~0 )
+ return Id;
+ return Gia_ManFindRepr_rec( pReprs, pReprs[Id] );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Normalizes equivalences.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Gia_ManNormalizeEquivalences( Gia_Man_t * p, int * pReprs )
+{
+ int i, iRepr;
+ assert( p->pReprs == NULL );
+ assert( p->pNexts == NULL );
+ p->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) );
+ for ( i = 0; i < Gia_ManObjNum(p); i++ )
+ Gia_ObjSetRepr( p, i, GIA_VOID );
+ for ( i = 0; i < Gia_ManObjNum(p); i++ )
+ {
+ if ( pReprs[i] == ~0 )
+ continue;
+ iRepr = Gia_ManFindRepr_rec( pReprs, i );
+ Gia_ObjSetRepr( p, i, iRepr );
+ }
+ p->pNexts = Gia_ManDeriveNexts( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Partitioned sequential synthesis.]
+
+ Description [Returns AIG annotated with equivalence classes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cec_SequentialSynthesisPart( Gia_Man_t * p, Cec_ParSeq_t * pPars )
+{
+ int fPrintParts = 0;
+ char Buffer[100];
+ Gia_Man_t * pTemp;
+ Vec_Ptr_t * vParts = (Vec_Ptr_t *)p->vClockDoms;
+ Vec_Int_t * vPart;
+ int * pMapBack, * pReprs;
+ int i, nCountPis, nCountRegs;
+ int nClasses, clk = clock();
+
+ // save parameters
+ if ( fPrintParts )
+ {
+ // print partitions
+ Abc_Print( 1, "The following clock domains are used:\n" );
+ Vec_PtrForEachEntry( Vec_Int_t *, vParts, vPart, i )
+ {
+ pTemp = Gia_ManRegCreatePart( p, vPart, &nCountPis, &nCountRegs, NULL );
+ sprintf( Buffer, "part%03d.aig", i );
+ Gia_WriteAiger( pTemp, Buffer, 0, 0 );
+ Abc_Print( 1, "part%03d.aig : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d.\n",
+ i, Vec_IntSize(vPart), Gia_ManCiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Gia_ManAndNum(pTemp) );
+ Gia_ManStop( pTemp );
+ }
+ }
+
+ // perform sequential synthesis for clock domains
+ pReprs = ABC_FALLOC( int, Gia_ManObjNum(p) );
+ Vec_PtrForEachEntry( Vec_Int_t *, vParts, vPart, i )
+ {
+ pTemp = Gia_ManRegCreatePart( p, vPart, &nCountPis, &nCountRegs, &pMapBack );
+ if ( nCountPis > 0 )
+ {
+ if ( pPars->fUseScorr )
+ {
+ Cec_ParCor_t CorPars, * pCorPars = &CorPars;
+ Cec_ManCorSetDefaultParams( pCorPars );
+ pCorPars->nBTLimit = pPars->nBTLimit;
+ pCorPars->nLevelMax = pPars->nLevelMax;
+ pCorPars->fVerbose = pPars->fVeryVerbose;
+ pCorPars->fUseCSat = 1;
+ Cec_ManLSCorrespondenceClasses( pTemp, pCorPars );
+ }
+ else if ( pPars->fUseLcorr )
+ {
+ Cec_ParCor_t CorPars, * pCorPars = &CorPars;
+ Cec_ManCorSetDefaultParams( pCorPars );
+ pCorPars->fLatchCorr = 1;
+ pCorPars->nBTLimit = pPars->nBTLimit;
+ pCorPars->fVerbose = pPars->fVeryVerbose;
+ pCorPars->fUseCSat = 1;
+ Cec_ManLSCorrespondenceClasses( pTemp, pCorPars );
+ }
+ else
+ {
+// pNew = Gia_ManSeqStructSweep( pTemp, pPars->fConsts, pPars->fEquivs, pPars->fVerbose );
+// Gia_ManStop( pNew );
+ Gia_ManSeqCleanupClasses( pTemp, pPars->fConsts, pPars->fEquivs, pPars->fVerbose );
+ }
+//Abc_Print( 1, "Part equivalences = %d.\n", Gia_ManEquivCountLitsAll(pTemp) );
+ nClasses = Gia_TransferMappedClasses( pTemp, pMapBack, pReprs );
+ if ( pPars->fVerbose )
+ {
+ Abc_Print( 1, "%3d : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d. Cl = %5d.\n",
+ i, Vec_IntSize(vPart), Gia_ManCiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Gia_ManAndNum(pTemp), nClasses );
+ }
+ }
+ Gia_ManStop( pTemp );
+ ABC_FREE( pMapBack );
+ }
+
+ // generate resulting equivalences
+ Gia_ManNormalizeEquivalences( p, pReprs );
+//Abc_Print( 1, "Total equivalences = %d.\n", Gia_ManEquivCountLitsAll(p) );
+ ABC_FREE( pReprs );
+ if ( pPars->fVerbose )
+ {
+ Abc_PrintTime( 1, "Total time", clock() - clk );
+ }
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/cec/module.make b/src/proof/cec/module.make
new file mode 100644
index 00000000..bac6e9bc
--- /dev/null
+++ b/src/proof/cec/module.make
@@ -0,0 +1,13 @@
+SRC += src/proof/cec/cecCec.c \
+ src/proof/cec/cecChoice.c \
+ src/proof/cec/cecClass.c \
+ src/proof/cec/cecCore.c \
+ src/proof/cec/cecCorr.c \
+ src/proof/cec/cecIso.c \
+ src/proof/cec/cecMan.c \
+ src/proof/cec/cecPat.c \
+ src/proof/cec/cecSeq.c \
+ src/proof/cec/cecSim.c \
+ src/proof/cec/cecSolve.c \
+ src/proof/cec/cecSynth.c \
+ src/proof/cec/cecSweep.c
diff --git a/src/proof/dch/dch.h b/src/proof/dch/dch.h
new file mode 100644
index 00000000..731eb776
--- /dev/null
+++ b/src/proof/dch/dch.h
@@ -0,0 +1,90 @@
+/**CFile****************************************************************
+
+ FileName [dch.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Choice computation for tech-mapping.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 29, 2008.]
+
+ Revision [$Id: dch.h,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__dch__dch_h
+#define ABC__aig__dch__dch_h
+
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+// choicing parameters
+typedef struct Dch_Pars_t_ Dch_Pars_t;
+struct Dch_Pars_t_
+{
+ int nWords; // the number of simulation words
+ int nBTLimit; // conflict limit at a node
+ int nSatVarMax; // the max number of SAT variables
+ int fSynthesis; // set to 1 to perform synthesis
+ int fPolarFlip; // uses polarity adjustment
+ int fSimulateTfo; // uses simulation of TFO classes
+ int fPower; // uses power-aware rewriting
+ int fUseGia; // uses GIA package
+ int fUseCSat; // uses circuit-based solver
+ int fLightSynth; // uses lighter version of synthesis
+ int fVerbose; // verbose stats
+ int timeSynth; // synthesis runtime
+ int nNodesAhead; // the lookahead in terms of nodes
+ int nCallsRecycle; // calls to perform before recycling SAT solver
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== dchAig.c ==========================================================*/
+extern Aig_Man_t * Dch_DeriveTotalAig( Vec_Ptr_t * vAigs );
+/*=== dchCore.c ==========================================================*/
+extern void Dch_ManSetDefaultParams( Dch_Pars_t * p );
+extern int Dch_ManReadVerbose( Dch_Pars_t * p );
+extern Aig_Man_t * Dch_ComputeChoices( Aig_Man_t * pAig, Dch_Pars_t * pPars );
+extern void Dch_ComputeEquivalences( Aig_Man_t * pAig, Dch_Pars_t * pPars );
+/*=== dchScript.c ==========================================================*/
+extern Aig_Man_t * Dar_ManChoiceNew( Aig_Man_t * pAig, Dch_Pars_t * pPars );
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/proof/dch/dchAig.c b/src/proof/dch/dchAig.c
new file mode 100644
index 00000000..91a00c63
--- /dev/null
+++ b/src/proof/dch/dchAig.c
@@ -0,0 +1,119 @@
+/**CFile****************************************************************
+
+ FileName [dchAig.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Choice computation for tech-mapping.]
+
+ Synopsis [AIG manipulation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 29, 2008.]
+
+ Revision [$Id: dchAig.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dchInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Derives the cumulative AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_DeriveTotalAig_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+ if ( pObj->pData )
+ return;
+ Dch_DeriveTotalAig_rec( p, Aig_ObjFanin0(pObj) );
+ Dch_DeriveTotalAig_rec( p, Aig_ObjFanin1(pObj) );
+ pObj->pData = Aig_And( p, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the cumulative AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Dch_DeriveTotalAig( Vec_Ptr_t * vAigs )
+{
+ Aig_Man_t * pAig, * pAig2, * pAigTotal;
+ Aig_Obj_t * pObj, * pObjPi, * pObjPo;
+ int i, k, nNodes;
+ assert( Vec_PtrSize(vAigs) > 0 );
+ // make sure they have the same number of PIs/POs
+ nNodes = 0;
+ pAig = (Aig_Man_t *)Vec_PtrEntry( vAigs, 0 );
+ Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig2, i )
+ {
+ assert( Aig_ManPiNum(pAig) == Aig_ManPiNum(pAig2) );
+ assert( Aig_ManPoNum(pAig) == Aig_ManPoNum(pAig2) );
+ nNodes += Aig_ManNodeNum(pAig2);
+ Aig_ManCleanData( pAig2 );
+ }
+ // map constant nodes
+ pAigTotal = Aig_ManStart( nNodes );
+ Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig2, k )
+ Aig_ManConst1(pAig2)->pData = Aig_ManConst1(pAigTotal);
+ // map primary inputs
+ Aig_ManForEachPi( pAig, pObj, i )
+ {
+ pObjPi = Aig_ObjCreatePi( pAigTotal );
+ Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig2, k )
+ Aig_ManPi( pAig2, i )->pData = pObjPi;
+ }
+ // construct the AIG in the order of POs
+ Aig_ManForEachPo( pAig, pObj, i )
+ {
+ Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig2, k )
+ {
+ pObjPo = Aig_ManPo( pAig2, i );
+ Dch_DeriveTotalAig_rec( pAigTotal, Aig_ObjFanin0(pObjPo) );
+ }
+ Aig_ObjCreatePo( pAigTotal, Aig_ObjChild0Copy(pObj) );
+ }
+/*
+ // mark the cone of the first AIG
+ Aig_ManIncrementTravId( pAigTotal );
+ Aig_ManForEachObj( pAig, pObj, i )
+ if ( pObj->pData )
+ Aig_ObjSetTravIdCurrent( pAigTotal, pObj->pData );
+*/
+ // cleanup should not be done
+ return pAigTotal;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/dch/dchChoice.c b/src/proof/dch/dchChoice.c
new file mode 100644
index 00000000..1772f8aa
--- /dev/null
+++ b/src/proof/dch/dchChoice.c
@@ -0,0 +1,508 @@
+/**CFile****************************************************************
+
+ FileName [dchChoice.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Choice computation for tech-mapping.]
+
+ Synopsis [Contrustion of choices.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 29, 2008.]
+
+ Revision [$Id: dchChoice.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dchInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of representatives.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Dch_DeriveChoiceCountReprs( Aig_Man_t * pAig )
+{
+ Aig_Obj_t * pObj, * pRepr;
+ int i, nReprs = 0;
+ Aig_ManForEachObj( pAig, pObj, i )
+ {
+ pRepr = Aig_ObjRepr( pAig, pObj );
+ if ( pRepr == NULL )
+ continue;
+ assert( pRepr->Id < pObj->Id );
+ nReprs++;
+ }
+ return nReprs;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of equivalences.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Dch_DeriveChoiceCountEquivs( Aig_Man_t * pAig )
+{
+ Aig_Obj_t * pObj, * pTemp, * pPrev;
+ int i, nEquivs = 0, Counter = 0;
+ Aig_ManForEachObj( pAig, pObj, i )
+ {
+ if ( !Aig_ObjIsChoice(pAig, pObj) )
+ continue;
+ for ( pPrev = pObj, pTemp = Aig_ObjEquiv(pAig, pObj); pTemp;
+ pPrev = pTemp, pTemp = Aig_ObjEquiv(pAig, pTemp) )
+ {
+ if ( pTemp->nRefs > 0 )
+ {
+ // remove referenced node from equivalence class
+ assert( pAig->pEquivs[pPrev->Id] == pTemp );
+ pAig->pEquivs[pPrev->Id] = pAig->pEquivs[pTemp->Id];
+ pAig->pEquivs[pTemp->Id] = NULL;
+ // how about the need to continue iterating over the list?
+ // pPrev = pTemp ???
+ Counter++;
+ }
+ nEquivs++;
+ }
+ }
+// printf( "Removed %d classes.\n", Counter );
+
+ if ( Counter )
+ Dch_DeriveChoiceCountEquivs( pAig );
+// if ( Counter )
+// printf( "Removed %d equiv nodes because of non-zero ref counter.\n", Counter );
+ return nEquivs;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the choice node of pRepr is in the TFI of pObj.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Dch_ObjCheckTfi_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+ // check the trivial cases
+ if ( pObj == NULL )
+ return 0;
+ if ( Aig_ObjIsPi(pObj) )
+ return 0;
+ if ( pObj->fMarkA )
+ return 1;
+ // skip the visited node
+ if ( Aig_ObjIsTravIdCurrent( p, pObj ) )
+ return 0;
+ Aig_ObjSetTravIdCurrent( p, pObj );
+ // check the children
+ if ( Dch_ObjCheckTfi_rec( p, Aig_ObjFanin0(pObj) ) )
+ return 1;
+ if ( Dch_ObjCheckTfi_rec( p, Aig_ObjFanin1(pObj) ) )
+ return 1;
+ // check equivalent nodes
+ return Dch_ObjCheckTfi_rec( p, Aig_ObjEquiv(p, pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the choice node of pRepr is in the TFI of pObj.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Dch_ObjCheckTfi( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr )
+{
+ Aig_Obj_t * pTemp;
+ int RetValue;
+ assert( !Aig_IsComplement(pObj) );
+ assert( !Aig_IsComplement(pRepr) );
+ // mark nodes of the choice node
+ for ( pTemp = pRepr; pTemp; pTemp = Aig_ObjEquiv(p, pTemp) )
+ pTemp->fMarkA = 1;
+ // traverse the new node
+ Aig_ManIncrementTravId( p );
+ RetValue = Dch_ObjCheckTfi_rec( p, pObj );
+ // unmark nodes of the choice node
+ for ( pTemp = pRepr; pTemp; pTemp = Aig_ObjEquiv(p, pTemp) )
+ pTemp->fMarkA = 0;
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns representatives of fanin in approapriate polarity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Aig_Obj_t * Aig_ObjGetRepr( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+ Aig_Obj_t * pRepr;
+ if ( (pRepr = Aig_ObjRepr(p, Aig_Regular(pObj))) )
+ return Aig_NotCond( pRepr, Aig_Regular(pObj)->fPhase ^ pRepr->fPhase ^ Aig_IsComplement(pObj) );
+ return pObj;
+}
+
+static inline Aig_Obj_t * Aig_ObjChild0CopyRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_ObjGetRepr( p, Aig_ObjChild0Copy(pObj) ); }
+static inline Aig_Obj_t * Aig_ObjChild1CopyRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_ObjGetRepr( p, Aig_ObjChild1Copy(pObj) ); }
+
+/**Function*************************************************************
+
+ Synopsis [Derives the AIG with choices from representatives.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_DeriveChoiceAigNode( Aig_Man_t * pAigNew, Aig_Man_t * pAigOld, Aig_Obj_t * pObj )
+{
+ Aig_Obj_t * pRepr, * pObjNew, * pReprNew;
+ // get the new node
+ pObj->pData = Aig_And( pAigNew,
+ Aig_ObjChild0CopyRepr(pAigNew, pObj),
+ Aig_ObjChild1CopyRepr(pAigNew, pObj) );
+ pRepr = Aig_ObjRepr( pAigOld, pObj );
+ if ( pRepr == NULL )
+ return;
+ // get the corresponding new nodes
+ pObjNew = Aig_Regular((Aig_Obj_t *)pObj->pData);
+ pReprNew = Aig_Regular((Aig_Obj_t *)pRepr->pData);
+ if ( pObjNew == pReprNew )
+ return;
+ // skip the earlier nodes
+ if ( pReprNew->Id > pObjNew->Id )
+ return;
+ assert( pReprNew->Id < pObjNew->Id );
+ // set the representatives
+ Aig_ObjSetRepr( pAigNew, pObjNew, pReprNew );
+ // skip used nodes
+ if ( pObjNew->nRefs > 0 )
+ return;
+ assert( pObjNew->nRefs == 0 );
+ // update new nodes of the object
+ if ( !Aig_ObjIsNode(pRepr) )
+ return;
+ // skip choices with combinational loops
+ if ( Dch_ObjCheckTfi( pAigNew, pObjNew, pReprNew ) )
+ return;
+ // add choice
+ pAigNew->pEquivs[pObjNew->Id] = pAigNew->pEquivs[pReprNew->Id];
+ pAigNew->pEquivs[pReprNew->Id] = pObjNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the AIG with choices from representatives.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Dch_DeriveChoiceAig_old( Aig_Man_t * pAig )
+{
+ Aig_Man_t * pChoices, * pTemp;
+ Aig_Obj_t * pObj;
+ int i;
+ // start recording equivalences
+ pChoices = Aig_ManStart( Aig_ManObjNumMax(pAig) );
+ pChoices->pEquivs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) );
+ pChoices->pReprs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) );
+ // map constants and PIs
+ Aig_ManCleanData( pAig );
+ Aig_ManConst1(pAig)->pData = Aig_ManConst1(pChoices);
+ Aig_ManForEachPi( pAig, pObj, i )
+ pObj->pData = Aig_ObjCreatePi( pChoices );
+ // construct choices for the internal nodes
+ assert( pAig->pReprs != NULL );
+ Aig_ManForEachNode( pAig, pObj, i )
+ Dch_DeriveChoiceAigNode( pChoices, pAig, pObj );
+ Aig_ManForEachPo( pAig, pObj, i )
+ Aig_ObjCreatePo( pChoices, Aig_ObjChild0CopyRepr(pChoices, pObj) );
+ Dch_DeriveChoiceCountEquivs( pChoices );
+ // there is no need for cleanup
+ ABC_FREE( pChoices->pReprs );
+ pChoices = Aig_ManDupDfs( pTemp = pChoices );
+ Aig_ManStop( pTemp );
+ return pChoices;
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Checks for combinational loops in the AIG.]
+
+ Description [Returns 1 if combinational loop is detected.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Aig_ManCheckAcyclic_rec( Aig_Man_t * p, Aig_Obj_t * pNode, int fVerbose )
+{
+ Aig_Obj_t * pFanin;
+ int fAcyclic;
+ if ( Aig_ObjIsPi(pNode) || Aig_ObjIsConst1(pNode) )
+ return 1;
+ assert( Aig_ObjIsNode(pNode) );
+ // make sure the node is not visited
+ assert( !Aig_ObjIsTravIdPrevious(p, pNode) );
+ // check if the node is part of the combinational loop
+ if ( Aig_ObjIsTravIdCurrent(p, pNode) )
+ {
+ if ( fVerbose )
+ Abc_Print( 1, "Network \"%s\" contains combinational loop!\n", p->pSpec? p->pSpec : NULL );
+ if ( fVerbose )
+ Abc_Print( 1, "Node \"%d\" is encountered twice on the following path to the COs:\n", Aig_ObjId(pNode) );
+ return 0;
+ }
+ // mark this node as a node on the current path
+ Aig_ObjSetTravIdCurrent( p, pNode );
+
+ // visit the transitive fanin
+ pFanin = Aig_ObjFanin0(pNode);
+ // check if the fanin is visited
+ if ( !Aig_ObjIsTravIdPrevious(p, pFanin) )
+ {
+ // traverse the fanin's cone searching for the loop
+ if ( !(fAcyclic = Aig_ManCheckAcyclic_rec(p, pFanin, fVerbose)) )
+ {
+ // return as soon as the loop is detected
+ if ( fVerbose )
+ Abc_Print( 1, " %d ->", Aig_ObjId(pFanin) );
+ return 0;
+ }
+ }
+
+ // visit the transitive fanin
+ pFanin = Aig_ObjFanin1(pNode);
+ // check if the fanin is visited
+ if ( !Aig_ObjIsTravIdPrevious(p, pFanin) )
+ {
+ // traverse the fanin's cone searching for the loop
+ if ( !(fAcyclic = Aig_ManCheckAcyclic_rec(p, pFanin, fVerbose)) )
+ {
+ // return as soon as the loop is detected
+ if ( fVerbose )
+ Abc_Print( 1, " %d ->", Aig_ObjId(pFanin) );
+ return 0;
+ }
+ }
+
+ // visit choices
+ if ( Aig_ObjRepr(p, pNode) == NULL && Aig_ObjEquiv(p, pNode) != NULL )
+ {
+ for ( pFanin = Aig_ObjEquiv(p, pNode); pFanin; pFanin = Aig_ObjEquiv(p, pFanin) )
+ {
+ // check if the fanin is visited
+ if ( Aig_ObjIsTravIdPrevious(p, pFanin) )
+ continue;
+ // traverse the fanin's cone searching for the loop
+ if ( (fAcyclic = Aig_ManCheckAcyclic_rec(p, pFanin, fVerbose)) )
+ continue;
+ // return as soon as the loop is detected
+ if ( fVerbose )
+ Abc_Print( 1, " %d", Aig_ObjId(pFanin) );
+ if ( fVerbose )
+ Abc_Print( 1, " (choice of %d) -> ", Aig_ObjId(pNode) );
+ return 0;
+ }
+ }
+ // mark this node as a visited node
+ Aig_ObjSetTravIdPrevious( p, pNode );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks for combinational loops in the AIG.]
+
+ Description [Returns 1 if there is no combinational loops.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Aig_ManCheckAcyclic( Aig_Man_t * p, int fVerbose )
+{
+ Aig_Obj_t * pNode;
+ int fAcyclic;
+ int i;
+ // set the traversal ID for this DFS ordering
+ Aig_ManIncrementTravId( p );
+ Aig_ManIncrementTravId( p );
+ // pNode->TravId == pNet->nTravIds means "pNode is on the path"
+ // pNode->TravId == pNet->nTravIds - 1 means "pNode is visited but is not on the path"
+ // pNode->TravId < pNet->nTravIds - 1 means "pNode is not visited"
+ // traverse the network to detect cycles
+ fAcyclic = 1;
+ Aig_ManForEachPo( p, pNode, i )
+ {
+ pNode = Aig_ObjFanin0(pNode);
+ if ( Aig_ObjIsTravIdPrevious(p, pNode) )
+ continue;
+ // traverse the output logic cone
+ if ( (fAcyclic = Aig_ManCheckAcyclic_rec(p, pNode, fVerbose)) )
+ continue;
+ // stop as soon as the first loop is detected
+ if ( fVerbose )
+ Abc_Print( 1, " CO %d\n", i );
+ break;
+ }
+ return fAcyclic;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes combinational loop.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Aig_ManFixLoopProblem( Aig_Man_t * p, int fVerbose )
+{
+ Aig_Obj_t * pObj;
+ int i, Counter = 0, Counter2 = 0;
+ Aig_ManForEachObj( p, pObj, i )
+ {
+ if ( !Aig_ObjIsTravIdCurrent(p, pObj) )
+ continue;
+ Counter2++;
+ if ( Aig_ObjRepr(p, pObj) == NULL && Aig_ObjEquiv(p, pObj) != NULL )
+ {
+ Aig_ObjSetEquiv(p, pObj, NULL);
+ Counter++;
+ }
+ }
+ if ( fVerbose )
+ Abc_Print( 1, "Fixed %d choice nodes on the path with %d objects.\n", Counter, Counter2 );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Derives the AIG with choices from representatives.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Dch_DeriveChoiceAigInt( Aig_Man_t * pAig )
+{
+ Aig_Man_t * pChoices;
+ Aig_Obj_t * pObj;
+ int i;
+ // start recording equivalences
+ pChoices = Aig_ManStart( Aig_ManObjNumMax(pAig) );
+ pChoices->pEquivs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) );
+ pChoices->pReprs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) );
+ // map constants and PIs
+ Aig_ManCleanData( pAig );
+ Aig_ManConst1(pAig)->pData = Aig_ManConst1(pChoices);
+ Aig_ManForEachPi( pAig, pObj, i )
+ pObj->pData = Aig_ObjCreatePi( pChoices );
+ // construct choices for the internal nodes
+ assert( pAig->pReprs != NULL );
+ Aig_ManForEachNode( pAig, pObj, i )
+ Dch_DeriveChoiceAigNode( pChoices, pAig, pObj );
+ Aig_ManForEachPo( pAig, pObj, i )
+ Aig_ObjCreatePo( pChoices, Aig_ObjChild0CopyRepr(pChoices, pObj) );
+ Dch_DeriveChoiceCountEquivs( pChoices );
+ Aig_ManSetRegNum( pChoices, Aig_ManRegNum(pAig) );
+ return pChoices;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the AIG with choices from representatives.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Dch_DeriveChoiceAig( Aig_Man_t * pAig )
+{
+ extern int Aig_ManCheckAcyclic( Aig_Man_t * pAig, int fVerbose );
+ Aig_Man_t * pChoices, * pTemp;
+ int fVerbose = 0;
+ pChoices = Dch_DeriveChoiceAigInt( pAig );
+// pChoices = Dch_DeriveChoiceAigInt( pTemp = pChoices );
+// Aig_ManStop( pTemp );
+ // there is no need for cleanup
+ ABC_FREE( pChoices->pReprs );
+ while ( !Aig_ManCheckAcyclic( pChoices, fVerbose ) )
+ {
+ if ( fVerbose )
+ Abc_Print( 1, "There is a loop!\n" );
+ Aig_ManFixLoopProblem( pChoices, fVerbose );
+ }
+ pChoices = Aig_ManDupDfs( pTemp = pChoices );
+ Aig_ManStop( pTemp );
+ return pChoices;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/dch/dchClass.c b/src/proof/dch/dchClass.c
new file mode 100644
index 00000000..24476309
--- /dev/null
+++ b/src/proof/dch/dchClass.c
@@ -0,0 +1,611 @@
+/**CFile****************************************************************
+
+ FileName [dchClass.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Choice computation for tech-mapping.]
+
+ Synopsis [Representation of candidate equivalence classes.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 29, 2008.]
+
+ Revision [$Id: dchClass.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dchInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+ The candidate equivalence classes are stored as a vector of pointers
+ to the array of pointers to the nodes in each class.
+ The first node of the class is its representative node.
+ The representative has the smallest topological order among the class nodes.
+ The nodes inside each class are ordered according to their topological order.
+ The classes are ordered according to the topo order of their representatives.
+*/
+
+// internal representation of candidate equivalence classes
+struct Dch_Cla_t_
+{
+ // class information
+ Aig_Man_t * pAig; // original AIG manager
+ Aig_Obj_t *** pId2Class; // non-const classes by ID of repr node
+ int * pClassSizes; // sizes of each equivalence class
+ // statistics
+ int nClasses; // the total number of non-const classes
+ int nCands1; // the total number of const candidates
+ int nLits; // the number of literals in all classes
+ // memory
+ Aig_Obj_t ** pMemClasses; // memory allocated for equivalence classes
+ Aig_Obj_t ** pMemClassesFree; // memory allocated for equivalence classes to be used
+ // temporary data
+ Vec_Ptr_t * vClassOld; // old equivalence class after splitting
+ Vec_Ptr_t * vClassNew; // new equivalence class(es) after splitting
+ // procedures used for class refinement
+ void * pManData;
+ unsigned (*pFuncNodeHash) (void *,Aig_Obj_t *); // returns hash key of the node
+ int (*pFuncNodeIsConst) (void *,Aig_Obj_t *); // returns 1 if the node is a constant
+ int (*pFuncNodesAreEqual) (void *,Aig_Obj_t *, Aig_Obj_t *); // returns 1 if nodes are equal up to a complement
+};
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static inline Aig_Obj_t * Dch_ObjNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj ) { return ppNexts[pObj->Id]; }
+static inline void Dch_ObjSetNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { ppNexts[pObj->Id] = pNext; }
+
+// iterator through the equivalence classes
+#define Dch_ManForEachClass( p, ppClass, i ) \
+ for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ ) \
+ if ( ((ppClass) = p->pId2Class[i]) == NULL ) {} else
+// iterator through the nodes in one class
+#define Dch_ClassForEachNode( p, pRepr, pNode, i ) \
+ for ( i = 0; i < p->pClassSizes[pRepr->Id]; i++ ) \
+ if ( ((pNode) = p->pId2Class[pRepr->Id][i]) == NULL ) {} else
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Creates one equivalence class.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Dch_ObjAddClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, Aig_Obj_t ** pClass, int nSize )
+{
+ assert( p->pId2Class[pRepr->Id] == NULL );
+ p->pId2Class[pRepr->Id] = pClass;
+ assert( p->pClassSizes[pRepr->Id] == 0 );
+ assert( nSize > 1 );
+ p->pClassSizes[pRepr->Id] = nSize;
+ p->nClasses++;
+ p->nLits += nSize - 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes one equivalence class.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Aig_Obj_t ** Dch_ObjRemoveClass( Dch_Cla_t * p, Aig_Obj_t * pRepr )
+{
+ Aig_Obj_t ** pClass = p->pId2Class[pRepr->Id];
+ int nSize;
+ assert( pClass != NULL );
+ p->pId2Class[pRepr->Id] = NULL;
+ nSize = p->pClassSizes[pRepr->Id];
+ assert( nSize > 1 );
+ p->nClasses--;
+ p->nLits -= nSize - 1;
+ p->pClassSizes[pRepr->Id] = 0;
+ return pClass;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts representation of equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dch_Cla_t * Dch_ClassesStart( Aig_Man_t * pAig )
+{
+ Dch_Cla_t * p;
+ p = ABC_ALLOC( Dch_Cla_t, 1 );
+ memset( p, 0, sizeof(Dch_Cla_t) );
+ p->pAig = pAig;
+ p->pId2Class = ABC_CALLOC( Aig_Obj_t **, Aig_ManObjNumMax(pAig) );
+ p->pClassSizes = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) );
+ p->vClassOld = Vec_PtrAlloc( 100 );
+ p->vClassNew = Vec_PtrAlloc( 100 );
+ assert( pAig->pReprs == NULL );
+ Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts representation of equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_ClassesSetData( Dch_Cla_t * p, void * pManData,
+ unsigned (*pFuncNodeHash)(void *,Aig_Obj_t *), // returns hash key of the node
+ int (*pFuncNodeIsConst)(void *,Aig_Obj_t *), // returns 1 if the node is a constant
+ int (*pFuncNodesAreEqual)(void *,Aig_Obj_t *, Aig_Obj_t *) ) // returns 1 if nodes are equal up to a complement
+{
+ p->pManData = pManData;
+ p->pFuncNodeHash = pFuncNodeHash;
+ p->pFuncNodeIsConst = pFuncNodeIsConst;
+ p->pFuncNodesAreEqual = pFuncNodesAreEqual;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stop representation of equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_ClassesStop( Dch_Cla_t * p )
+{
+ if ( p->vClassNew ) Vec_PtrFree( p->vClassNew );
+ if ( p->vClassOld ) Vec_PtrFree( p->vClassOld );
+ ABC_FREE( p->pId2Class );
+ ABC_FREE( p->pClassSizes );
+ ABC_FREE( p->pMemClasses );
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stop representation of equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Dch_ClassesLitNum( Dch_Cla_t * p )
+{
+ return p->nLits;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stop representation of equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Obj_t ** Dch_ClassesReadClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, int * pnSize )
+{
+ assert( p->pId2Class[pRepr->Id] != NULL );
+ assert( p->pClassSizes[pRepr->Id] > 1 );
+ *pnSize = p->pClassSizes[pRepr->Id];
+ return p->pId2Class[pRepr->Id];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks candidate equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_ClassesCheck( Dch_Cla_t * p )
+{
+ Aig_Obj_t * pObj, * pPrev, ** ppClass;
+ int i, k, nLits, nClasses, nCands1;
+ nClasses = nLits = 0;
+ Dch_ManForEachClass( p, ppClass, k )
+ {
+ pPrev = NULL;
+ Dch_ClassForEachNode( p, ppClass[0], pObj, i )
+ {
+ if ( i == 0 )
+ assert( Aig_ObjRepr(p->pAig, pObj) == NULL );
+ else
+ {
+ assert( Aig_ObjRepr(p->pAig, pObj) == ppClass[0] );
+ assert( pPrev->Id < pObj->Id );
+ nLits++;
+ }
+ pPrev = pObj;
+ }
+ nClasses++;
+ }
+ nCands1 = 0;
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ nCands1 += Dch_ObjIsConst1Cand( p->pAig, pObj );
+ assert( p->nLits == nLits );
+ assert( p->nCands1 == nCands1 );
+ assert( p->nClasses == nClasses );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints simulation classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_ClassesPrintOne( Dch_Cla_t * p, Aig_Obj_t * pRepr )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Abc_Print( 1, "{ " );
+ Dch_ClassForEachNode( p, pRepr, pObj, i )
+ Abc_Print( 1, "%d(%d,%d) ", pObj->Id, pObj->Level, Aig_SupportSize(p->pAig,pObj) );
+ Abc_Print( 1, "}\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints simulation classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_ClassesPrint( Dch_Cla_t * p, int fVeryVerbose )
+{
+ Aig_Obj_t ** ppClass;
+ Aig_Obj_t * pObj;
+ int i;
+ Abc_Print( 1, "Equivalence classes: Const1 = %5d. Class = %5d. Lit = %5d.\n",
+ p->nCands1, p->nClasses, p->nLits );
+ if ( !fVeryVerbose )
+ return;
+ Abc_Print( 1, "Constants { " );
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ if ( Dch_ObjIsConst1Cand( p->pAig, pObj ) )
+ Abc_Print( 1, "%d(%d,%d) ", pObj->Id, pObj->Level, Aig_SupportSize(p->pAig,pObj) );
+ Abc_Print( 1, "}\n" );
+ Dch_ManForEachClass( p, ppClass, i )
+ {
+ Abc_Print( 1, "%3d (%3d) : ", i, p->pClassSizes[i] );
+ Dch_ClassesPrintOne( p, ppClass[0] );
+ }
+ Abc_Print( 1, "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates initial simulation classes.]
+
+ Description [Assumes that simulation info is assigned.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_ClassesPrepare( Dch_Cla_t * p, int fLatchCorr, int nMaxLevs )
+{
+ Aig_Obj_t ** ppTable, ** ppNexts, ** ppClassNew;
+ Aig_Obj_t * pObj, * pTemp, * pRepr;
+ int i, k, nTableSize, nNodes, iEntry, nEntries, nEntries2;
+
+ // allocate the hash table hashing simulation info into nodes
+ nTableSize = Abc_PrimeCudd( Aig_ManObjNumMax(p->pAig)/4 );
+ ppTable = ABC_CALLOC( Aig_Obj_t *, nTableSize );
+ ppNexts = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) );
+
+ // add all the nodes to the hash table
+ nEntries = 0;
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ {
+ if ( fLatchCorr )
+ {
+ if ( !Aig_ObjIsPi(pObj) )
+ continue;
+ }
+ else
+ {
+ if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) )
+ continue;
+ // skip the node with more that the given number of levels
+ if ( nMaxLevs && (int)pObj->Level >= nMaxLevs )
+ continue;
+ }
+ // check if the node belongs to the class of constant 1
+ if ( p->pFuncNodeIsConst( p->pManData, pObj ) )
+ {
+ Dch_ObjSetConst1Cand( p->pAig, pObj );
+ p->nCands1++;
+ continue;
+ }
+ // hash the node by its simulation info
+ iEntry = p->pFuncNodeHash( p->pManData, pObj ) % nTableSize;
+ // add the node to the class
+ if ( ppTable[iEntry] == NULL )
+ ppTable[iEntry] = pObj;
+ else
+ {
+ // set the representative of this node
+ pRepr = ppTable[iEntry];
+ Aig_ObjSetRepr( p->pAig, pObj, pRepr );
+ // add node to the table
+ if ( Dch_ObjNext( ppNexts, pRepr ) == NULL )
+ { // this will be the second entry
+ p->pClassSizes[pRepr->Id]++;
+ nEntries++;
+ }
+ // add the entry to the list
+ Dch_ObjSetNext( ppNexts, pObj, Dch_ObjNext( ppNexts, pRepr ) );
+ Dch_ObjSetNext( ppNexts, pRepr, pObj );
+ p->pClassSizes[pRepr->Id]++;
+ nEntries++;
+ }
+ }
+
+ // allocate room for classes
+ p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, nEntries + p->nCands1 );
+ p->pMemClassesFree = p->pMemClasses + nEntries;
+
+ // copy the entries into storage in the topological order
+ nEntries2 = 0;
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ {
+ if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) )
+ continue;
+ nNodes = p->pClassSizes[pObj->Id];
+ // skip the nodes that are not representatives of non-trivial classes
+ if ( nNodes == 0 )
+ continue;
+ assert( nNodes > 1 );
+ // add the nodes to the class in the topological order
+ ppClassNew = p->pMemClasses + nEntries2;
+ ppClassNew[0] = pObj;
+ for ( pTemp = Dch_ObjNext(ppNexts, pObj), k = 1; pTemp;
+ pTemp = Dch_ObjNext(ppNexts, pTemp), k++ )
+ {
+ ppClassNew[nNodes-k] = pTemp;
+ }
+ // add the class of nodes
+ p->pClassSizes[pObj->Id] = 0;
+ Dch_ObjAddClass( p, pObj, ppClassNew, nNodes );
+ // increment the number of entries
+ nEntries2 += nNodes;
+ }
+ assert( nEntries == nEntries2 );
+ ABC_FREE( ppTable );
+ ABC_FREE( ppNexts );
+ // now it is time to refine the classes
+ Dch_ClassesRefine( p );
+ Dch_ClassesCheck( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Iteratively refines the classes after simulation.]
+
+ Description [Returns the number of refinements performed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Dch_ClassesRefineOneClass( Dch_Cla_t * p, Aig_Obj_t * pReprOld, int fRecursive )
+{
+ Aig_Obj_t ** pClassOld, ** pClassNew;
+ Aig_Obj_t * pObj, * pReprNew;
+ int i;
+
+ // split the class
+ Vec_PtrClear( p->vClassOld );
+ Vec_PtrClear( p->vClassNew );
+ Dch_ClassForEachNode( p, pReprOld, pObj, i )
+ if ( p->pFuncNodesAreEqual(p->pManData, pReprOld, pObj) )
+ Vec_PtrPush( p->vClassOld, pObj );
+ else
+ Vec_PtrPush( p->vClassNew, pObj );
+ // check if splitting happened
+ if ( Vec_PtrSize(p->vClassNew) == 0 )
+ return 0;
+
+ // get the new representative
+ pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 );
+ assert( Vec_PtrSize(p->vClassOld) > 0 );
+ assert( Vec_PtrSize(p->vClassNew) > 0 );
+
+ // create old class
+ pClassOld = Dch_ObjRemoveClass( p, pReprOld );
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassOld, pObj, i )
+ {
+ pClassOld[i] = pObj;
+ Aig_ObjSetRepr( p->pAig, pObj, i? pReprOld : NULL );
+ }
+ // create new class
+ pClassNew = pClassOld + i;
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
+ {
+ pClassNew[i] = pObj;
+ Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL );
+ }
+
+ // put classes back
+ if ( Vec_PtrSize(p->vClassOld) > 1 )
+ Dch_ObjAddClass( p, pReprOld, pClassOld, Vec_PtrSize(p->vClassOld) );
+ if ( Vec_PtrSize(p->vClassNew) > 1 )
+ Dch_ObjAddClass( p, pReprNew, pClassNew, Vec_PtrSize(p->vClassNew) );
+
+ // check if the class should be recursively refined
+ if ( fRecursive && Vec_PtrSize(p->vClassNew) > 1 )
+ return 1 + Dch_ClassesRefineOneClass( p, pReprNew, 1 );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Refines the classes after simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Dch_ClassesRefine( Dch_Cla_t * p )
+{
+ Aig_Obj_t ** ppClass;
+ int i, nRefis = 0;
+ Dch_ManForEachClass( p, ppClass, i )
+ nRefis += Dch_ClassesRefineOneClass( p, ppClass[0], 0 );
+ return nRefis;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns equivalence class of the given node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_ClassesCollectOneClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, Vec_Ptr_t * vRoots )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Vec_PtrClear( vRoots );
+ Dch_ClassForEachNode( p, pRepr, pObj, i )
+ Vec_PtrPush( vRoots, pObj );
+ assert( Vec_PtrSize(vRoots) > 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns equivalence class of the given node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_ClassesCollectConst1Group( Dch_Cla_t * p, Aig_Obj_t * pObj, int nNodes, Vec_Ptr_t * vRoots )
+{
+ int i, Limit;
+ Vec_PtrClear( vRoots );
+ Limit = Abc_MinInt( pObj->Id + nNodes, Aig_ManObjNumMax(p->pAig) );
+ for ( i = pObj->Id; i < Limit; i++ )
+ {
+ pObj = Aig_ManObj( p->pAig, i );
+ if ( pObj && Dch_ObjIsConst1Cand( p->pAig, pObj ) )
+ Vec_PtrPush( vRoots, pObj );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Refine the group of constant 1 nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Dch_ClassesRefineConst1Group( Dch_Cla_t * p, Vec_Ptr_t * vRoots, int fRecursive )
+{
+ Aig_Obj_t * pObj, * pReprNew, ** ppClassNew;
+ int i;
+ if ( Vec_PtrSize(vRoots) == 0 )
+ return 0;
+ // collect the nodes to be refined
+ Vec_PtrClear( p->vClassNew );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vRoots, pObj, i )
+ if ( !p->pFuncNodeIsConst( p->pManData, pObj ) )
+ Vec_PtrPush( p->vClassNew, pObj );
+ // check if there is a new class
+ if ( Vec_PtrSize(p->vClassNew) == 0 )
+ return 0;
+ p->nCands1 -= Vec_PtrSize(p->vClassNew);
+ pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 );
+ Aig_ObjSetRepr( p->pAig, pReprNew, NULL );
+ if ( Vec_PtrSize(p->vClassNew) == 1 )
+ return 1;
+ // create a new class composed of these nodes
+ ppClassNew = p->pMemClassesFree;
+ p->pMemClassesFree += Vec_PtrSize(p->vClassNew);
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
+ {
+ ppClassNew[i] = pObj;
+ Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL );
+ }
+ Dch_ObjAddClass( p, pReprNew, ppClassNew, Vec_PtrSize(p->vClassNew) );
+ // refine them recursively
+ if ( fRecursive )
+ return 1 + Dch_ClassesRefineOneClass( p, pReprNew, 1 );
+ return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/dch/dchCnf.c b/src/proof/dch/dchCnf.c
new file mode 100644
index 00000000..4175a123
--- /dev/null
+++ b/src/proof/dch/dchCnf.c
@@ -0,0 +1,334 @@
+/**CFile****************************************************************
+
+ FileName [dchCnf.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Choice computation for tech-mapping.]
+
+ Synopsis [Computation of CNF.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 29, 2008.]
+
+ Revision [$Id: dchCnf.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dchInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Addes clauses to the solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_AddClausesMux( Dch_Man_t * p, Aig_Obj_t * pNode )
+{
+ Aig_Obj_t * pNodeI, * pNodeT, * pNodeE;
+ int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE;
+
+ assert( !Aig_IsComplement( pNode ) );
+ assert( Aig_ObjIsMuxType( pNode ) );
+ // get nodes (I = if, T = then, E = else)
+ pNodeI = Aig_ObjRecognizeMux( pNode, &pNodeT, &pNodeE );
+ // get the variable numbers
+ VarF = Dch_ObjSatNum(p,pNode);
+ VarI = Dch_ObjSatNum(p,pNodeI);
+ VarT = Dch_ObjSatNum(p,Aig_Regular(pNodeT));
+ VarE = Dch_ObjSatNum(p,Aig_Regular(pNodeE));
+ // get the complementation flags
+ fCompT = Aig_IsComplement(pNodeT);
+ fCompE = Aig_IsComplement(pNodeE);
+
+ // f = ITE(i, t, e)
+
+ // i' + t' + f
+ // i' + t + f'
+ // i + e' + f
+ // i + e + f'
+
+ // create four clauses
+ pLits[0] = toLitCond(VarI, 1);
+ pLits[1] = toLitCond(VarT, 1^fCompT);
+ pLits[2] = toLitCond(VarF, 0);
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( Aig_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+ pLits[0] = toLitCond(VarI, 1);
+ pLits[1] = toLitCond(VarT, 0^fCompT);
+ pLits[2] = toLitCond(VarF, 1);
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( Aig_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+ pLits[0] = toLitCond(VarI, 0);
+ pLits[1] = toLitCond(VarE, 1^fCompE);
+ pLits[2] = toLitCond(VarF, 0);
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+ pLits[0] = toLitCond(VarI, 0);
+ pLits[1] = toLitCond(VarE, 0^fCompE);
+ pLits[2] = toLitCond(VarF, 1);
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+
+ // two additional clauses
+ // t' & e' -> f'
+ // t & e -> f
+
+ // t + e + f'
+ // t' + e' + f
+
+ if ( VarT == VarE )
+ {
+// assert( fCompT == !fCompE );
+ return;
+ }
+
+ pLits[0] = toLitCond(VarT, 0^fCompT);
+ pLits[1] = toLitCond(VarE, 0^fCompE);
+ pLits[2] = toLitCond(VarF, 1);
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( Aig_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+ pLits[0] = toLitCond(VarT, 1^fCompT);
+ pLits[1] = toLitCond(VarE, 1^fCompE);
+ pLits[2] = toLitCond(VarF, 0);
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( Aig_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Addes clauses to the solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_AddClausesSuper( Dch_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vSuper )
+{
+ Aig_Obj_t * pFanin;
+ int * pLits, nLits, RetValue, i;
+ assert( !Aig_IsComplement(pNode) );
+ assert( Aig_ObjIsNode( pNode ) );
+ // create storage for literals
+ nLits = Vec_PtrSize(vSuper) + 1;
+ pLits = ABC_ALLOC( int, nLits );
+ // suppose AND-gate is A & B = C
+ // add !A => !C or A + !C
+ Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i )
+ {
+ pLits[0] = toLitCond(Dch_ObjSatNum(p,Aig_Regular(pFanin)), Aig_IsComplement(pFanin));
+ pLits[1] = toLitCond(Dch_ObjSatNum(p,pNode), 1);
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( Aig_Regular(pFanin)->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( pNode->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+ assert( RetValue );
+ }
+ // add A & B => C or !A + !B + C
+ Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i )
+ {
+ pLits[i] = toLitCond(Dch_ObjSatNum(p,Aig_Regular(pFanin)), !Aig_IsComplement(pFanin));
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( Aig_Regular(pFanin)->fPhase ) pLits[i] = lit_neg( pLits[i] );
+ }
+ }
+ pLits[nLits-1] = toLitCond(Dch_ObjSatNum(p,pNode), 0);
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( pNode->fPhase ) pLits[nLits-1] = lit_neg( pLits[nLits-1] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits );
+ assert( RetValue );
+ ABC_FREE( pLits );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_CollectSuper_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes )
+{
+ // if the new node is complemented or a PI, another gate begins
+ if ( Aig_IsComplement(pObj) || Aig_ObjIsPi(pObj) ||
+ (!fFirst && Aig_ObjRefs(pObj) > 1) ||
+ (fUseMuxes && Aig_ObjIsMuxType(pObj)) )
+ {
+ Vec_PtrPushUnique( vSuper, pObj );
+ return;
+ }
+ // go through the branches
+ Dch_CollectSuper_rec( Aig_ObjChild0(pObj), vSuper, 0, fUseMuxes );
+ Dch_CollectSuper_rec( Aig_ObjChild1(pObj), vSuper, 0, fUseMuxes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_CollectSuper( Aig_Obj_t * pObj, int fUseMuxes, Vec_Ptr_t * vSuper )
+{
+ assert( !Aig_IsComplement(pObj) );
+ assert( !Aig_ObjIsPi(pObj) );
+ Vec_PtrClear( vSuper );
+ Dch_CollectSuper_rec( pObj, vSuper, 1, fUseMuxes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the solver clause database.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_ObjAddToFrontier( Dch_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vFrontier )
+{
+ assert( !Aig_IsComplement(pObj) );
+ if ( Dch_ObjSatNum(p,pObj) )
+ return;
+ assert( Dch_ObjSatNum(p,pObj) == 0 );
+ if ( Aig_ObjIsConst1(pObj) )
+ return;
+ Vec_PtrPush( p->vUsedNodes, pObj );
+ Dch_ObjSetSatNum( p, pObj, p->nSatVars++ );
+ if ( Aig_ObjIsNode(pObj) )
+ Vec_PtrPush( vFrontier, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the solver clause database.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_CnfNodeAddToSolver( Dch_Man_t * p, Aig_Obj_t * pObj )
+{
+ Vec_Ptr_t * vFrontier;
+ Aig_Obj_t * pNode, * pFanin;
+ int i, k, fUseMuxes = 1;
+ // quit if CNF is ready
+ if ( Dch_ObjSatNum(p,pObj) )
+ return;
+ // start the frontier
+ vFrontier = Vec_PtrAlloc( 100 );
+ Dch_ObjAddToFrontier( p, pObj, vFrontier );
+ // explore nodes in the frontier
+ Vec_PtrForEachEntry( Aig_Obj_t *, vFrontier, pNode, i )
+ {
+ // create the supergate
+ assert( Dch_ObjSatNum(p,pNode) );
+ if ( fUseMuxes && Aig_ObjIsMuxType(pNode) )
+ {
+ Vec_PtrClear( p->vFanins );
+ Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin0( Aig_ObjFanin0(pNode) ) );
+ Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin0( Aig_ObjFanin1(pNode) ) );
+ Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin1( Aig_ObjFanin0(pNode) ) );
+ Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin1( Aig_ObjFanin1(pNode) ) );
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanins, pFanin, k )
+ Dch_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier );
+ Dch_AddClausesMux( p, pNode );
+ }
+ else
+ {
+ Dch_CollectSuper( pNode, fUseMuxes, p->vFanins );
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanins, pFanin, k )
+ Dch_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier );
+ Dch_AddClausesSuper( p, pNode, p->vFanins );
+ }
+ assert( Vec_PtrSize(p->vFanins) > 1 );
+ }
+ Vec_PtrFree( vFrontier );
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/dch/dchCore.c b/src/proof/dch/dchCore.c
new file mode 100644
index 00000000..bc78682b
--- /dev/null
+++ b/src/proof/dch/dchCore.c
@@ -0,0 +1,158 @@
+/**CFile****************************************************************
+
+ FileName [dchCore.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Choice computation for tech-mapping.]
+
+ Synopsis [The core procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 29, 2008.]
+
+ Revision [$Id: dchCore.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dchInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [This procedure sets default parameters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_ManSetDefaultParams( Dch_Pars_t * p )
+{
+ memset( p, 0, sizeof(Dch_Pars_t) );
+ p->nWords = 8; // the number of simulation words
+ p->nBTLimit = 1000; // conflict limit at a node
+ p->nSatVarMax = 5000; // the max number of SAT variables
+ p->fSynthesis = 1; // derives three snapshots
+ p->fPolarFlip = 1; // uses polarity adjustment
+ p->fSimulateTfo = 1; // simulate TFO
+ p->fPower = 0; // power-aware rewriting
+ p->fLightSynth = 0; // uses lighter version of synthesis
+ p->fVerbose = 0; // verbose stats
+ p->nNodesAhead = 1000; // the lookahead in terms of nodes
+ p->nCallsRecycle = 100; // calls to perform before recycling SAT solver
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns verbose parameter.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Dch_ManReadVerbose( Dch_Pars_t * p )
+{
+ return p->fVerbose;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs computation of AIGs with choices.]
+
+ Description [Takes several AIGs and performs choicing.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Dch_ComputeChoices( Aig_Man_t * pAig, Dch_Pars_t * pPars )
+{
+ Dch_Man_t * p;
+ Aig_Man_t * pResult;
+ int clk, clkTotal = clock();
+ // reset random numbers
+ Aig_ManRandom(1);
+ // start the choicing manager
+ p = Dch_ManCreate( pAig, pPars );
+ // compute candidate equivalence classes
+clk = clock();
+ p->ppClasses = Dch_CreateCandEquivClasses( pAig, pPars->nWords, pPars->fVerbose );
+p->timeSimInit = clock() - clk;
+// Dch_ClassesPrint( p->ppClasses, 0 );
+ p->nLits = Dch_ClassesLitNum( p->ppClasses );
+ // perform SAT sweeping
+ Dch_ManSweep( p );
+ // free memory ahead of time
+p->timeTotal = clock() - clkTotal;
+ Dch_ManStop( p );
+ // create choices
+ ABC_FREE( pAig->pTable );
+ pResult = Dch_DeriveChoiceAig( pAig );
+ // count the number of representatives
+ if ( pPars->fVerbose )
+ Abc_Print( 1, "STATS: Reprs = %6d. Equivs = %6d. Choices = %6d.\n",
+ Dch_DeriveChoiceCountReprs( pAig ),
+ Dch_DeriveChoiceCountEquivs( pResult ),
+ Aig_ManChoiceNum( pResult ) );
+ return pResult;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs computation of AIGs with choices.]
+
+ Description [Takes several AIGs and performs choicing.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_ComputeEquivalences( Aig_Man_t * pAig, Dch_Pars_t * pPars )
+{
+ Dch_Man_t * p;
+ int clk, clkTotal = clock();
+ // reset random numbers
+ Aig_ManRandom(1);
+ // start the choicing manager
+ p = Dch_ManCreate( pAig, pPars );
+ // compute candidate equivalence classes
+clk = clock();
+ p->ppClasses = Dch_CreateCandEquivClasses( pAig, pPars->nWords, pPars->fVerbose );
+p->timeSimInit = clock() - clk;
+// Dch_ClassesPrint( p->ppClasses, 0 );
+ p->nLits = Dch_ClassesLitNum( p->ppClasses );
+ // perform SAT sweeping
+ Dch_ManSweep( p );
+ // free memory ahead of time
+p->timeTotal = clock() - clkTotal;
+ Dch_ManStop( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/dch/dchInt.h b/src/proof/dch/dchInt.h
new file mode 100644
index 00000000..c9f2f4f6
--- /dev/null
+++ b/src/proof/dch/dchInt.h
@@ -0,0 +1,170 @@
+/**CFile****************************************************************
+
+ FileName [dchInt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Choice computation for tech-mapping.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 29, 2008.]
+
+ Revision [$Id: dchInt.h,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__dch__dchInt_h
+#define ABC__aig__dch__dchInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include "src/aig/aig/aig.h"
+#include "src/sat/bsat/satSolver.h"
+#include "dch.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+// equivalence classes
+typedef struct Dch_Cla_t_ Dch_Cla_t;
+
+// choicing manager
+typedef struct Dch_Man_t_ Dch_Man_t;
+struct Dch_Man_t_
+{
+ // parameters
+ Dch_Pars_t * pPars; // choicing parameters
+ // AIGs used in the package
+// Vec_Ptr_t * vAigs; // user-given AIGs
+ Aig_Man_t * pAigTotal; // intermediate AIG
+ Aig_Man_t * pAigFraig; // final AIG
+ // equivalence classes
+ Dch_Cla_t * ppClasses; // equivalence classes of nodes
+ Aig_Obj_t ** pReprsProved; // equivalences proved
+ // SAT solving
+ sat_solver * pSat; // recyclable SAT solver
+ int nSatVars; // the counter of SAT variables
+ int * pSatVars; // mapping of each node into its SAT var
+ Vec_Ptr_t * vUsedNodes; // nodes whose SAT vars are assigned
+ int nRecycles; // the number of times SAT solver was recycled
+ int nCallsSince; // the number of calls since the last recycle
+ Vec_Ptr_t * vFanins; // fanins of the CNF node
+ Vec_Ptr_t * vSimRoots; // the roots of cand const 1 nodes to simulate
+ Vec_Ptr_t * vSimClasses; // the roots of cand equiv classes to simulate
+ // solver cone size
+ int nConeThis;
+ int nConeMax;
+ // SAT calls statistics
+ int nSatCalls; // the number of SAT calls
+ int nSatProof; // the number of proofs
+ int nSatFailsReal; // the number of timeouts
+ int nSatCallsUnsat; // the number of unsat SAT calls
+ int nSatCallsSat; // the number of sat SAT calls
+ // choice node statistics
+ int nLits; // the number of lits in the cand equiv classes
+ int nReprs; // the number of proved equivalent pairs
+ int nEquivs; // the number of final equivalences
+ int nChoices; // the number of final choice nodes
+ // runtime stats
+ int timeSimInit; // simulation and class computation
+ int timeSimSat; // simulation of the counter-examples
+ int timeSat; // solving SAT
+ int timeSatSat; // sat
+ int timeSatUnsat; // unsat
+ int timeSatUndec; // undecided
+ int timeChoice; // choice computation
+ int timeOther; // other runtime
+ int timeTotal; // total runtime
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int Dch_ObjSatNum( Dch_Man_t * p, Aig_Obj_t * pObj ) { return p->pSatVars[pObj->Id]; }
+static inline void Dch_ObjSetSatNum( Dch_Man_t * p, Aig_Obj_t * pObj, int Num ) { p->pSatVars[pObj->Id] = Num; }
+
+static inline Aig_Obj_t * Dch_ObjFraig( Aig_Obj_t * pObj ) { return (Aig_Obj_t *)pObj->pData; }
+static inline void Dch_ObjSetFraig( Aig_Obj_t * pObj, Aig_Obj_t * pNode ) { pObj->pData = pNode; }
+
+static inline int Dch_ObjIsConst1Cand( Aig_Man_t * pAig, Aig_Obj_t * pObj )
+{
+ return Aig_ObjRepr(pAig, pObj) == Aig_ManConst1(pAig);
+}
+static inline void Dch_ObjSetConst1Cand( Aig_Man_t * pAig, Aig_Obj_t * pObj )
+{
+ assert( !Dch_ObjIsConst1Cand( pAig, pObj ) );
+ Aig_ObjSetRepr( pAig, pObj, Aig_ManConst1(pAig) );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== dchAig.c ===================================================*/
+/*=== dchChoice.c ===================================================*/
+extern int Dch_DeriveChoiceCountReprs( Aig_Man_t * pAig );
+extern int Dch_DeriveChoiceCountEquivs( Aig_Man_t * pAig );
+extern Aig_Man_t * Dch_DeriveChoiceAig( Aig_Man_t * pAig );
+/*=== dchClass.c =================================================*/
+extern Dch_Cla_t * Dch_ClassesStart( Aig_Man_t * pAig );
+extern void Dch_ClassesSetData( Dch_Cla_t * p, void * pManData,
+ unsigned (*pFuncNodeHash)(void *,Aig_Obj_t *),
+ int (*pFuncNodeIsConst)(void *,Aig_Obj_t *),
+ int (*pFuncNodesAreEqual)(void *,Aig_Obj_t *, Aig_Obj_t *) );
+extern void Dch_ClassesStop( Dch_Cla_t * p );
+extern int Dch_ClassesLitNum( Dch_Cla_t * p );
+extern Aig_Obj_t ** Dch_ClassesReadClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, int * pnSize );
+extern void Dch_ClassesPrint( Dch_Cla_t * p, int fVeryVerbose );
+extern void Dch_ClassesPrepare( Dch_Cla_t * p, int fLatchCorr, int nMaxLevs );
+extern int Dch_ClassesRefine( Dch_Cla_t * p );
+extern int Dch_ClassesRefineOneClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, int fRecursive );
+extern void Dch_ClassesCollectOneClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, Vec_Ptr_t * vRoots );
+extern void Dch_ClassesCollectConst1Group( Dch_Cla_t * p, Aig_Obj_t * pObj, int nNodes, Vec_Ptr_t * vRoots );
+extern int Dch_ClassesRefineConst1Group( Dch_Cla_t * p, Vec_Ptr_t * vRoots, int fRecursive );
+/*=== dchCnf.c ===================================================*/
+extern void Dch_CnfNodeAddToSolver( Dch_Man_t * p, Aig_Obj_t * pObj );
+/*=== dchMan.c ===================================================*/
+extern Dch_Man_t * Dch_ManCreate( Aig_Man_t * pAig, Dch_Pars_t * pPars );
+extern void Dch_ManStop( Dch_Man_t * p );
+extern void Dch_ManSatSolverRecycle( Dch_Man_t * p );
+/*=== dchSat.c ===================================================*/
+extern int Dch_NodesAreEquiv( Dch_Man_t * p, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2 );
+/*=== dchSim.c ===================================================*/
+extern Dch_Cla_t * Dch_CreateCandEquivClasses( Aig_Man_t * pAig, int nWords, int fVerbose );
+/*=== dchSimSat.c ===================================================*/
+extern void Dch_ManResimulateCex( Dch_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr );
+extern void Dch_ManResimulateCex2( Dch_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr );
+/*=== dchSweep.c ===================================================*/
+extern void Dch_ManSweep( Dch_Man_t * p );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/proof/dch/dchMan.c b/src/proof/dch/dchMan.c
new file mode 100644
index 00000000..dc856309
--- /dev/null
+++ b/src/proof/dch/dchMan.c
@@ -0,0 +1,191 @@
+/**CFile****************************************************************
+
+ FileName [dchMan.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Choice computation for tech-mapping.]
+
+ Synopsis [Calls to the SAT solver.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 29, 2008.]
+
+ Revision [$Id: dchMan.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dchInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Creates the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dch_Man_t * Dch_ManCreate( Aig_Man_t * pAig, Dch_Pars_t * pPars )
+{
+ Dch_Man_t * p;
+ // create interpolation manager
+ p = ABC_ALLOC( Dch_Man_t, 1 );
+ memset( p, 0, sizeof(Dch_Man_t) );
+ p->pPars = pPars;
+ p->pAigTotal = pAig; //Dch_DeriveTotalAig( vAigs );
+ Aig_ManFanoutStart( p->pAigTotal );
+ // SAT solving
+ p->nSatVars = 1;
+ p->pSatVars = ABC_CALLOC( int, Aig_ManObjNumMax(p->pAigTotal) );
+ p->vUsedNodes = Vec_PtrAlloc( 1000 );
+ p->vFanins = Vec_PtrAlloc( 100 );
+ p->vSimRoots = Vec_PtrAlloc( 1000 );
+ p->vSimClasses = Vec_PtrAlloc( 1000 );
+ // equivalences proved
+ p->pReprsProved = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAigTotal) );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints stats of the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_ManPrintStats( Dch_Man_t * p )
+{
+ int nNodeNum = Aig_ManNodeNum(p->pAigTotal) / 3;
+ Abc_Print( 1, "Parameters: Sim words = %d. Conf limit = %d. SAT var max = %d.\n",
+ p->pPars->nWords, p->pPars->nBTLimit, p->pPars->nSatVarMax );
+ Abc_Print( 1, "AIG nodes : Total = %6d. Dangling = %6d. Main = %6d. (%6.2f %%)\n",
+ Aig_ManNodeNum(p->pAigTotal),
+ Aig_ManNodeNum(p->pAigTotal)-nNodeNum,
+ nNodeNum,
+ 100.0 * nNodeNum/Aig_ManNodeNum(p->pAigTotal) );
+ Abc_Print( 1, "SAT solver: Vars = %d. Max cone = %d. Recycles = %d.\n",
+ p->nSatVars, p->nConeMax, p->nRecycles );
+ Abc_Print( 1, "SAT calls : All = %6d. Unsat = %6d. Sat = %6d. Fail = %6d.\n",
+ p->nSatCalls, p->nSatCalls-p->nSatCallsSat-p->nSatFailsReal,
+ p->nSatCallsSat, p->nSatFailsReal );
+ Abc_Print( 1, "Choices : Lits = %6d. Reprs = %5d. Equivs = %5d. Choices = %5d.\n",
+ p->nLits, p->nReprs, p->nEquivs, p->nChoices );
+ Abc_Print( 1, "Choicing runtime statistics:\n" );
+ p->timeOther = p->timeTotal-p->timeSimInit-p->timeSimSat-p->timeSat-p->timeChoice;
+ Abc_PrintTimeP( 1, "Sim init ", p->timeSimInit, p->timeTotal );
+ Abc_PrintTimeP( 1, "Sim SAT ", p->timeSimSat, p->timeTotal );
+ Abc_PrintTimeP( 1, "SAT solving", p->timeSat, p->timeTotal );
+ Abc_PrintTimeP( 1, " sat ", p->timeSatSat, p->timeTotal );
+ Abc_PrintTimeP( 1, " unsat ", p->timeSatUnsat, p->timeTotal );
+ Abc_PrintTimeP( 1, " undecided", p->timeSatUndec, p->timeTotal );
+ Abc_PrintTimeP( 1, "Choice ", p->timeChoice, p->timeTotal );
+ Abc_PrintTimeP( 1, "Other ", p->timeOther, p->timeTotal );
+ Abc_PrintTimeP( 1, "TOTAL ", p->timeTotal, p->timeTotal );
+ if ( p->pPars->timeSynth )
+ {
+ Abc_PrintTime( 1, "Synthesis ", p->pPars->timeSynth );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_ManStop( Dch_Man_t * p )
+{
+ Aig_ManFanoutStop( p->pAigTotal );
+ if ( p->pPars->fVerbose )
+ Dch_ManPrintStats( p );
+ if ( p->pAigFraig )
+ Aig_ManStop( p->pAigFraig );
+ if ( p->ppClasses )
+ Dch_ClassesStop( p->ppClasses );
+ if ( p->pSat )
+ sat_solver_delete( p->pSat );
+ Vec_PtrFree( p->vUsedNodes );
+ Vec_PtrFree( p->vFanins );
+ Vec_PtrFree( p->vSimRoots );
+ Vec_PtrFree( p->vSimClasses );
+ ABC_FREE( p->pReprsProved );
+ ABC_FREE( p->pSatVars );
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recycles the SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_ManSatSolverRecycle( Dch_Man_t * p )
+{
+ int Lit;
+ if ( p->pSat )
+ {
+ Aig_Obj_t * pObj;
+ int i;
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vUsedNodes, pObj, i )
+ Dch_ObjSetSatNum( p, pObj, 0 );
+ Vec_PtrClear( p->vUsedNodes );
+// memset( p->pSatVars, 0, sizeof(int) * Aig_ManObjNumMax(p->pAigTotal) );
+ sat_solver_delete( p->pSat );
+ }
+ p->pSat = sat_solver_new();
+ sat_solver_setnvars( p->pSat, 1000 );
+ // var 0 is not used
+ // var 1 is reserved for const1 node - add the clause
+ p->nSatVars = 1;
+// p->nSatVars = 0;
+ Lit = toLit( p->nSatVars );
+ if ( p->pPars->fPolarFlip )
+ Lit = lit_neg( Lit );
+ sat_solver_addclause( p->pSat, &Lit, &Lit + 1 );
+ Dch_ObjSetSatNum( p, Aig_ManConst1(p->pAigFraig), p->nSatVars++ );
+
+ p->nRecycles++;
+ p->nCallsSince = 0;
+}
+
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/dch/dchSat.c b/src/proof/dch/dchSat.c
new file mode 100644
index 00000000..f5e346ef
--- /dev/null
+++ b/src/proof/dch/dchSat.c
@@ -0,0 +1,166 @@
+/**CFile****************************************************************
+
+ FileName [dchSat.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Choice computation for tech-mapping.]
+
+ Synopsis [Calls to the SAT solver.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 29, 2008.]
+
+ Revision [$Id: dchSat.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dchInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Runs equivalence test for the two nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Dch_NodesAreEquiv( Dch_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew )
+{
+ int nBTLimit = p->pPars->nBTLimit;
+ int pLits[2], RetValue, RetValue1, status, clk;
+ p->nSatCalls++;
+
+ // sanity checks
+ assert( !Aig_IsComplement(pNew) );
+ assert( !Aig_IsComplement(pOld) );
+ assert( pNew != pOld );
+
+ p->nCallsSince++; // experiment with this!!!
+
+ // check if SAT solver needs recycling
+ if ( p->pSat == NULL ||
+ (p->pPars->nSatVarMax &&
+ p->nSatVars > p->pPars->nSatVarMax &&
+ p->nCallsSince > p->pPars->nCallsRecycle) )
+ Dch_ManSatSolverRecycle( p );
+
+ // if the nodes do not have SAT variables, allocate them
+ Dch_CnfNodeAddToSolver( p, pOld );
+ Dch_CnfNodeAddToSolver( p, pNew );
+
+ // propage unit clauses
+ if ( p->pSat->qtail != p->pSat->qhead )
+ {
+ status = sat_solver_simplify(p->pSat);
+ assert( status != 0 );
+ assert( p->pSat->qtail == p->pSat->qhead );
+ }
+
+ // solve under assumptions
+ // A = 1; B = 0 OR A = 1; B = 1
+ pLits[0] = toLitCond( Dch_ObjSatNum(p,pOld), 0 );
+ pLits[1] = toLitCond( Dch_ObjSatNum(p,pNew), pOld->fPhase == pNew->fPhase );
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( pOld->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( pNew->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ }
+//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 );
+clk = clock();
+ RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2,
+ (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+p->timeSat += clock() - clk;
+ if ( RetValue1 == l_False )
+ {
+p->timeSatUnsat += clock() - clk;
+ pLits[0] = lit_neg( pLits[0] );
+ pLits[1] = lit_neg( pLits[1] );
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+ assert( RetValue );
+ p->nSatCallsUnsat++;
+ }
+ else if ( RetValue1 == l_True )
+ {
+p->timeSatSat += clock() - clk;
+ p->nSatCallsSat++;
+ return 0;
+ }
+ else // if ( RetValue1 == l_Undef )
+ {
+p->timeSatUndec += clock() - clk;
+ p->nSatFailsReal++;
+ return -1;
+ }
+
+ // if the old node was constant 0, we already know the answer
+ if ( pOld == Aig_ManConst1(p->pAigFraig) )
+ {
+ p->nSatProof++;
+ return 1;
+ }
+
+ // solve under assumptions
+ // A = 0; B = 1 OR A = 0; B = 0
+ pLits[0] = toLitCond( Dch_ObjSatNum(p,pOld), 1 );
+ pLits[1] = toLitCond( Dch_ObjSatNum(p,pNew), pOld->fPhase ^ pNew->fPhase );
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( pOld->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( pNew->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ }
+clk = clock();
+ RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2,
+ (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+p->timeSat += clock() - clk;
+ if ( RetValue1 == l_False )
+ {
+p->timeSatUnsat += clock() - clk;
+ pLits[0] = lit_neg( pLits[0] );
+ pLits[1] = lit_neg( pLits[1] );
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+ assert( RetValue );
+ p->nSatCallsUnsat++;
+ }
+ else if ( RetValue1 == l_True )
+ {
+p->timeSatSat += clock() - clk;
+ p->nSatCallsSat++;
+ return 0;
+ }
+ else // if ( RetValue1 == l_Undef )
+ {
+p->timeSatUndec += clock() - clk;
+ p->nSatFailsReal++;
+ return -1;
+ }
+ // return SAT proof
+ p->nSatProof++;
+ return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/dch/dchSim.c b/src/proof/dch/dchSim.c
new file mode 100644
index 00000000..b2d24761
--- /dev/null
+++ b/src/proof/dch/dchSim.c
@@ -0,0 +1,297 @@
+/**CFile****************************************************************
+
+ FileName [dchSim.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Choice computation for tech-mapping.]
+
+ Synopsis [Performs random simulation at the beginning.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 29, 2008.]
+
+ Revision [$Id: dchSim.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dchInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static inline unsigned * Dch_ObjSim( Vec_Ptr_t * vSims, Aig_Obj_t * pObj )
+{
+ return (unsigned *)Vec_PtrEntry( vSims, pObj->Id );
+}
+static inline unsigned Dch_ObjRandomSim()
+{
+ return Aig_ManRandom(0);
+}
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the node appears to be constant 1 candidate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Dch_NodeIsConstCex( void * p, Aig_Obj_t * pObj )
+{
+ return pObj->fPhase == pObj->fMarkB;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the nodes appear equal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Dch_NodesAreEqualCex( void * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
+{
+ return (pObj0->fPhase == pObj1->fPhase) == (pObj0->fMarkB == pObj1->fMarkB);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes hash value of the node using its simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Dch_NodeHash( void * p, Aig_Obj_t * pObj )
+{
+ Vec_Ptr_t * vSims = (Vec_Ptr_t *)p;
+ static int s_FPrimes[128] = {
+ 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459,
+ 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997,
+ 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543,
+ 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089,
+ 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671,
+ 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243,
+ 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871,
+ 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471,
+ 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073,
+ 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689,
+ 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309,
+ 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933,
+ 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
+ };
+ unsigned * pSim;
+ unsigned uHash;
+ int k, nWords;
+ nWords = (unsigned *)Vec_PtrEntry(vSims, 1) - (unsigned *)Vec_PtrEntry(vSims, 0);
+ uHash = 0;
+ pSim = Dch_ObjSim( vSims, pObj );
+ if ( pObj->fPhase )
+ {
+ for ( k = 0; k < nWords; k++ )
+ uHash ^= ~pSim[k] * s_FPrimes[k & 0x7F];
+ }
+ else
+ {
+ for ( k = 0; k < nWords; k++ )
+ uHash ^= pSim[k] * s_FPrimes[k & 0x7F];
+ }
+ return uHash;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if simulation info is composed of all zeros.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Dch_NodeIsConst( void * p, Aig_Obj_t * pObj )
+{
+ Vec_Ptr_t * vSims = (Vec_Ptr_t *)p;
+ unsigned * pSim;
+ int k, nWords;
+ nWords = (unsigned *)Vec_PtrEntry(vSims, 1) - (unsigned *)Vec_PtrEntry(vSims, 0);
+ pSim = Dch_ObjSim( vSims, pObj );
+ if ( pObj->fPhase )
+ {
+ for ( k = 0; k < nWords; k++ )
+ if ( ~pSim[k] )
+ return 0;
+ }
+ else
+ {
+ for ( k = 0; k < nWords; k++ )
+ if ( pSim[k] )
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if simulation infos are equal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Dch_NodesAreEqual( void * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
+{
+ Vec_Ptr_t * vSims = (Vec_Ptr_t *)p;
+ unsigned * pSim0, * pSim1;
+ int k, nWords;
+ nWords = (unsigned *)Vec_PtrEntry(vSims, 1) - (unsigned *)Vec_PtrEntry(vSims, 0);
+ pSim0 = Dch_ObjSim( vSims, pObj0 );
+ pSim1 = Dch_ObjSim( vSims, pObj1 );
+ if ( pObj0->fPhase != pObj1->fPhase )
+ {
+ for ( k = 0; k < nWords; k++ )
+ if ( pSim0[k] != ~pSim1[k] )
+ return 0;
+ }
+ else
+ {
+ for ( k = 0; k < nWords; k++ )
+ if ( pSim0[k] != pSim1[k] )
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Perform random simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_PerformRandomSimulation( Aig_Man_t * pAig, Vec_Ptr_t * vSims )
+{
+ unsigned * pSim, * pSim0, * pSim1;
+ Aig_Obj_t * pObj;
+ int i, k, nWords;
+ nWords = (unsigned *)Vec_PtrEntry(vSims, 1) - (unsigned *)Vec_PtrEntry(vSims, 0);
+
+ // assign const 1 sim info
+ pObj = Aig_ManConst1(pAig);
+ pSim = Dch_ObjSim( vSims, pObj );
+ memset( pSim, 0xff, sizeof(unsigned) * nWords );
+
+ // assign primary input random sim info
+ Aig_ManForEachPi( pAig, pObj, i )
+ {
+ pSim = Dch_ObjSim( vSims, pObj );
+ for ( k = 0; k < nWords; k++ )
+ pSim[k] = Dch_ObjRandomSim();
+ pSim[0] <<= 1;
+ }
+
+ // simulate AIG in the topological order
+ Aig_ManForEachNode( pAig, pObj, i )
+ {
+ pSim0 = Dch_ObjSim( vSims, Aig_ObjFanin0(pObj) );
+ pSim1 = Dch_ObjSim( vSims, Aig_ObjFanin1(pObj) );
+ pSim = Dch_ObjSim( vSims, pObj );
+
+ if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) // both are compls
+ {
+ for ( k = 0; k < nWords; k++ )
+ pSim[k] = ~pSim0[k] & ~pSim1[k];
+ }
+ else if ( Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) ) // first one is compl
+ {
+ for ( k = 0; k < nWords; k++ )
+ pSim[k] = ~pSim0[k] & pSim1[k];
+ }
+ else if ( !Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) // second one is compl
+ {
+ for ( k = 0; k < nWords; k++ )
+ pSim[k] = pSim0[k] & ~pSim1[k];
+ }
+ else // if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) // none is compl
+ {
+ for ( k = 0; k < nWords; k++ )
+ pSim[k] = pSim0[k] & pSim1[k];
+ }
+ }
+ // get simulation information for primary outputs
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives candidate equivalence classes of AIG nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Dch_Cla_t * Dch_CreateCandEquivClasses( Aig_Man_t * pAig, int nWords, int fVerbose )
+{
+ Dch_Cla_t * pClasses;
+ Vec_Ptr_t * vSims;
+ int i;
+ // allocate simulation information
+ vSims = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(pAig), nWords );
+ // run random simulation from the primary inputs
+ Dch_PerformRandomSimulation( pAig, vSims );
+ // start storage for equivalence classes
+ pClasses = Dch_ClassesStart( pAig );
+ Dch_ClassesSetData( pClasses, vSims, Dch_NodeHash, Dch_NodeIsConst, Dch_NodesAreEqual );
+ // hash nodes by sim info
+ Dch_ClassesPrepare( pClasses, 0, 0 );
+ // iterate random simulation
+ for ( i = 0; i < 7; i++ )
+ {
+ Dch_PerformRandomSimulation( pAig, vSims );
+ Dch_ClassesRefine( pClasses );
+ }
+ // clean up and return
+ Vec_PtrFree( vSims );
+ // prepare class refinement procedures
+ Dch_ClassesSetData( pClasses, NULL, NULL, Dch_NodeIsConstCex, Dch_NodesAreEqualCex );
+ return pClasses;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/dch/dchSimSat.c b/src/proof/dch/dchSimSat.c
new file mode 100644
index 00000000..808e754a
--- /dev/null
+++ b/src/proof/dch/dchSimSat.c
@@ -0,0 +1,258 @@
+/**CFile****************************************************************
+
+ FileName [dchSimSat.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Choice computation for tech-mapping.]
+
+ Synopsis [Performs resimulation using counter-examples.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 29, 2008.]
+
+ Revision [$Id: dchSimSat.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dchInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Collects internal nodes in the reverse DFS order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_ManCollectTfoCands_rec( Dch_Man_t * p, Aig_Obj_t * pObj )
+{
+ Aig_Obj_t * pFanout, * pRepr;
+ int iFanout = -1, i;
+ assert( !Aig_IsComplement(pObj) );
+ if ( Aig_ObjIsTravIdCurrent(p->pAigTotal, pObj) )
+ return;
+ Aig_ObjSetTravIdCurrent(p->pAigTotal, pObj);
+ // traverse the fanouts
+ Aig_ObjForEachFanout( p->pAigTotal, pObj, pFanout, iFanout, i )
+ Dch_ManCollectTfoCands_rec( p, pFanout );
+ // check if the given node has a representative
+ pRepr = Aig_ObjRepr( p->pAigTotal, pObj );
+ if ( pRepr == NULL )
+ return;
+ // pRepr is the constant 1 node
+ if ( pRepr == Aig_ManConst1(p->pAigTotal) )
+ {
+ Vec_PtrPush( p->vSimRoots, pObj );
+ return;
+ }
+ // pRepr is the representative of an equivalence class
+ if ( pRepr->fMarkA )
+ return;
+ pRepr->fMarkA = 1;
+ Vec_PtrPush( p->vSimClasses, pRepr );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collect equivalence classes and const1 cands in the TFO.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_ManCollectTfoCands( Dch_Man_t * p, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2 )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Vec_PtrClear( p->vSimRoots );
+ Vec_PtrClear( p->vSimClasses );
+ Aig_ManIncrementTravId( p->pAigTotal );
+ Aig_ObjSetTravIdCurrent( p->pAigTotal, Aig_ManConst1(p->pAigTotal) );
+ Dch_ManCollectTfoCands_rec( p, pObj1 );
+ Dch_ManCollectTfoCands_rec( p, pObj2 );
+ Vec_PtrSort( p->vSimRoots, (int (*)(void))Aig_ObjCompareIdIncrease );
+ Vec_PtrSort( p->vSimClasses, (int (*)(void))Aig_ObjCompareIdIncrease );
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vSimClasses, pObj, i )
+ pObj->fMarkA = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resimulates the cone of influence of the solved nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_ManResimulateSolved_rec( Dch_Man_t * p, Aig_Obj_t * pObj )
+{
+ if ( Aig_ObjIsTravIdCurrent(p->pAigTotal, pObj) )
+ return;
+ Aig_ObjSetTravIdCurrent(p->pAigTotal, pObj);
+ if ( Aig_ObjIsPi(pObj) )
+ {
+ Aig_Obj_t * pObjFraig;
+ int nVarNum;
+ pObjFraig = Dch_ObjFraig( pObj );
+ assert( !Aig_IsComplement(pObjFraig) );
+ nVarNum = Dch_ObjSatNum( p, pObjFraig );
+ // get the value from the SAT solver
+ // (account for the fact that some vars may be minimized away)
+ pObj->fMarkB = !nVarNum? 0 : sat_solver_var_value( p->pSat, nVarNum );
+// pObj->fMarkB = !nVarNum? Aig_ManRandom(0) & 1 : sat_solver_var_value( p->pSat, nVarNum );
+ return;
+ }
+ Dch_ManResimulateSolved_rec( p, Aig_ObjFanin0(pObj) );
+ Dch_ManResimulateSolved_rec( p, Aig_ObjFanin1(pObj) );
+ pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) )
+ & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) );
+ // count the cone size
+ if ( Dch_ObjSatNum( p, Aig_Regular(Dch_ObjFraig(pObj)) ) > 0 )
+ p->nConeThis++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resimulates the cone of influence of the other nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_ManResimulateOther_rec( Dch_Man_t * p, Aig_Obj_t * pObj )
+{
+ if ( Aig_ObjIsTravIdCurrent(p->pAigTotal, pObj) )
+ return;
+ Aig_ObjSetTravIdCurrent(p->pAigTotal, pObj);
+ if ( Aig_ObjIsPi(pObj) )
+ {
+ // set random value
+ pObj->fMarkB = Aig_ManRandom(0) & 1;
+ return;
+ }
+ Dch_ManResimulateOther_rec( p, Aig_ObjFanin0(pObj) );
+ Dch_ManResimulateOther_rec( p, Aig_ObjFanin1(pObj) );
+ pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) )
+ & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Handle the counter-example.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_ManResimulateCex( Dch_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr )
+{
+ Aig_Obj_t * pRoot, ** ppClass;
+ int i, k, nSize, RetValue1, RetValue2, clk = clock();
+ // get the equivalence classes
+ Dch_ManCollectTfoCands( p, pObj, pRepr );
+ // resimulate the cone of influence of the solved nodes
+ p->nConeThis = 0;
+ Aig_ManIncrementTravId( p->pAigTotal );
+ Aig_ObjSetTravIdCurrent( p->pAigTotal, Aig_ManConst1(p->pAigTotal) );
+ Dch_ManResimulateSolved_rec( p, pObj );
+ Dch_ManResimulateSolved_rec( p, pRepr );
+ p->nConeMax = Abc_MaxInt( p->nConeMax, p->nConeThis );
+ // resimulate the cone of influence of the other nodes
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vSimRoots, pRoot, i )
+ Dch_ManResimulateOther_rec( p, pRoot );
+ // refine these nodes
+ RetValue1 = Dch_ClassesRefineConst1Group( p->ppClasses, p->vSimRoots, 0 );
+ // resimulate the cone of influence of the cand classes
+ RetValue2 = 0;
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vSimClasses, pRoot, i )
+ {
+ ppClass = Dch_ClassesReadClass( p->ppClasses, pRoot, &nSize );
+ for ( k = 0; k < nSize; k++ )
+ Dch_ManResimulateOther_rec( p, ppClass[k] );
+ // refine this class
+ RetValue2 += Dch_ClassesRefineOneClass( p->ppClasses, pRoot, 0 );
+ }
+ // make sure refinement happened
+ if ( Aig_ObjIsConst1(pRepr) )
+ assert( RetValue1 );
+ else
+ assert( RetValue2 );
+p->timeSimSat += clock() - clk;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Handle the counter-example.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_ManResimulateCex2( Dch_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr )
+{
+ Aig_Obj_t * pRoot;
+ int i, RetValue, clk = clock();
+ // get the equivalence class
+ if ( Dch_ObjIsConst1Cand(p->pAigTotal, pObj) )
+ Dch_ClassesCollectConst1Group( p->ppClasses, pObj, 500, p->vSimRoots );
+ else
+ Dch_ClassesCollectOneClass( p->ppClasses, pRepr, p->vSimRoots );
+ // resimulate the cone of influence of the solved nodes
+ p->nConeThis = 0;
+ Aig_ManIncrementTravId( p->pAigTotal );
+ Aig_ObjSetTravIdCurrent( p->pAigTotal, Aig_ManConst1(p->pAigTotal) );
+ Dch_ManResimulateSolved_rec( p, pObj );
+ Dch_ManResimulateSolved_rec( p, pRepr );
+ p->nConeMax = Abc_MaxInt( p->nConeMax, p->nConeThis );
+ // resimulate the cone of influence of the other nodes
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vSimRoots, pRoot, i )
+ Dch_ManResimulateOther_rec( p, pRoot );
+ // refine this class
+ if ( Dch_ObjIsConst1Cand(p->pAigTotal, pObj) )
+ RetValue = Dch_ClassesRefineConst1Group( p->ppClasses, p->vSimRoots, 0 );
+ else
+ RetValue = Dch_ClassesRefineOneClass( p->ppClasses, pRepr, 0 );
+ assert( RetValue );
+p->timeSimSat += clock() - clk;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/dch/dchSweep.c b/src/proof/dch/dchSweep.c
new file mode 100644
index 00000000..a1c4f79b
--- /dev/null
+++ b/src/proof/dch/dchSweep.c
@@ -0,0 +1,146 @@
+/**CFile****************************************************************
+
+ FileName [dchSweep.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Choice computation for tech-mapping.]
+
+ Synopsis [One round of SAT sweeping.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 29, 2008.]
+
+ Revision [$Id: dchSweep.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "dchInt.h"
+#include "src/misc/bar/bar.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static inline Aig_Obj_t * Dch_ObjChild0Fra( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Dch_ObjFraig(Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj)) : NULL; }
+static inline Aig_Obj_t * Dch_ObjChild1Fra( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Dch_ObjFraig(Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj)) : NULL; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging for one node.]
+
+ Description [Returns the fraiged node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_ManSweepNode( Dch_Man_t * p, Aig_Obj_t * pObj )
+{
+ Aig_Obj_t * pObjRepr, * pObjFraig, * pObjFraig2, * pObjReprFraig;
+ int RetValue;
+ // get representative of this class
+ pObjRepr = Aig_ObjRepr( p->pAigTotal, pObj );
+ if ( pObjRepr == NULL )
+ return;
+ // get the fraiged node
+ pObjFraig = Dch_ObjFraig( pObj );
+ if ( pObjFraig == NULL )
+ return;
+ // get the fraiged representative
+ pObjReprFraig = Dch_ObjFraig( pObjRepr );
+ if ( pObjReprFraig == NULL )
+ return;
+ // if the fraiged nodes are the same, return
+ if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) )
+ {
+ // remember the proved equivalence
+ p->pReprsProved[ pObj->Id ] = pObjRepr;
+ return;
+ }
+ assert( Aig_Regular(pObjFraig) != Aig_ManConst1(p->pAigFraig) );
+ RetValue = Dch_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) );
+ if ( RetValue == -1 ) // timed out
+ {
+ Dch_ObjSetFraig( pObj, NULL );
+ return;
+ }
+ if ( RetValue == 1 ) // proved equivalent
+ {
+ pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase );
+ Dch_ObjSetFraig( pObj, pObjFraig2 );
+ // remember the proved equivalence
+ p->pReprsProved[ pObj->Id ] = pObjRepr;
+ return;
+ }
+ // disproved the equivalence
+ if ( p->pPars->fSimulateTfo )
+ Dch_ManResimulateCex( p, pObj, pObjRepr );
+ else
+ Dch_ManResimulateCex2( p, pObj, pObjRepr );
+ assert( Aig_ObjRepr( p->pAigTotal, pObj ) != pObjRepr );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging for the internal nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Dch_ManSweep( Dch_Man_t * p )
+{
+ Bar_Progress_t * pProgress = NULL;
+ Aig_Obj_t * pObj, * pObjNew;
+ int i;
+ // map constants and PIs
+ p->pAigFraig = Aig_ManStart( Aig_ManObjNumMax(p->pAigTotal) );
+ Aig_ManCleanData( p->pAigTotal );
+ Aig_ManConst1(p->pAigTotal)->pData = Aig_ManConst1(p->pAigFraig);
+ Aig_ManForEachPi( p->pAigTotal, pObj, i )
+ pObj->pData = Aig_ObjCreatePi( p->pAigFraig );
+ // sweep internal nodes
+ pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAigTotal) );
+ Aig_ManForEachNode( p->pAigTotal, pObj, i )
+ {
+ Bar_ProgressUpdate( pProgress, i, NULL );
+ if ( Dch_ObjFraig(Aig_ObjFanin0(pObj)) == NULL ||
+ Dch_ObjFraig(Aig_ObjFanin1(pObj)) == NULL )
+ continue;
+ pObjNew = Aig_And( p->pAigFraig, Dch_ObjChild0Fra(pObj), Dch_ObjChild1Fra(pObj) );
+ if ( pObjNew == NULL )
+ continue;
+ Dch_ObjSetFraig( pObj, pObjNew );
+ Dch_ManSweepNode( p, pObj );
+ }
+ Bar_ProgressStop( pProgress );
+ // update the representatives of the nodes (makes classes invalid)
+ ABC_FREE( p->pAigTotal->pReprs );
+ p->pAigTotal->pReprs = p->pReprsProved;
+ p->pReprsProved = NULL;
+ // clean the mark
+ Aig_ManCleanMarkB( p->pAigTotal );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/dch/module.make b/src/proof/dch/module.make
new file mode 100644
index 00000000..11163cef
--- /dev/null
+++ b/src/proof/dch/module.make
@@ -0,0 +1,10 @@
+SRC += src/proof/dch/dchAig.c \
+ src/proof/dch/dchChoice.c \
+ src/proof/dch/dchClass.c \
+ src/proof/dch/dchCnf.c \
+ src/proof/dch/dchCore.c \
+ src/proof/dch/dchMan.c \
+ src/proof/dch/dchSat.c \
+ src/proof/dch/dchSim.c \
+ src/proof/dch/dchSimSat.c \
+ src/proof/dch/dchSweep.c
diff --git a/src/proof/fra/fra.h b/src/proof/fra/fra.h
new file mode 100644
index 00000000..3e50ff57
--- /dev/null
+++ b/src/proof/fra/fra.h
@@ -0,0 +1,389 @@
+/**CFile****************************************************************
+
+ FileName [fra.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [[New FRAIG package.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 30, 2007.]
+
+ Revision [$Id: fra.h,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__fra__fra_h
+#define ABC__aig__fra__fra_h
+
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <time.h>
+
+#include "src/misc/vec/vec.h"
+#include "src/aig/aig/aig.h"
+#include "src/opt/dar/dar.h"
+#include "src/sat/bsat/satSolver.h"
+#include "src/aig/ioa/ioa.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Fra_Par_t_ Fra_Par_t;
+typedef struct Fra_Ssw_t_ Fra_Ssw_t;
+typedef struct Fra_Sec_t_ Fra_Sec_t;
+typedef struct Fra_Man_t_ Fra_Man_t;
+typedef struct Fra_Cla_t_ Fra_Cla_t;
+typedef struct Fra_Sml_t_ Fra_Sml_t;
+typedef struct Fra_Bmc_t_ Fra_Bmc_t;
+
+// FRAIG parameters
+struct Fra_Par_t_
+{
+ int nSimWords; // the number of words in the simulation info
+ double dSimSatur; // the ratio of refined classes when saturation is reached
+ int fPatScores; // enables simulation pattern scoring
+ int MaxScore; // max score after which resimulation is used
+ double dActConeRatio; // the ratio of cone to be bumped
+ double dActConeBumpMax; // the largest bump in activity
+ int fChoicing; // enables choicing
+ int fSpeculate; // use speculative reduction
+ int fProve; // prove the miter outputs
+ int fVerbose; // verbose output
+ int fDoSparse; // skip sparse functions
+ int fConeBias; // bias variables in the cone (good for unsat runs)
+ int nBTLimitNode; // conflict limit at a node
+ int nBTLimitMiter; // conflict limit at an output
+ int nLevelMax; // the max level to consider seriously
+ int nFramesP; // the number of timeframes to in the prefix
+ int nFramesK; // the number of timeframes to unroll
+ int nMaxImps; // the maximum number of implications to consider
+ int nMaxLevs; // the maximum number of levels to consider
+ int fRewrite; // use rewriting for constraint reduction
+ int fLatchCorr; // computes latch correspondence only
+ int fUseImps; // use implications
+ int fUse1Hot; // use one-hotness conditions
+ int fWriteImps; // record implications
+ int fDontShowBar; // does not show progressbar during fraiging
+};
+
+// seq SAT sweeping parameters
+struct Fra_Ssw_t_
+{
+ int nPartSize; // size of the partition
+ int nOverSize; // size of the overlap between partitions
+ int nFramesP; // number of frames in the prefix
+ int nFramesK; // number of frames for induction (1=simple)
+ int nMaxImps; // max implications to consider
+ int nMaxLevs; // max levels to consider
+ int nMinDomSize; // min clock domain considered for optimization
+ int fUseImps; // use implications
+ int fRewrite; // enable rewriting of the specualatively reduced model
+ int fFraiging; // enable comb SAT sweeping as preprocessing
+ int fLatchCorr; // perform register correspondence
+ int fWriteImps; // write implications into a file
+ int fUse1Hot; // use one-hotness constraints
+ int fVerbose; // enable verbose output
+ int fSilent; // disable any output
+ int nIters; // the number of iterations performed
+ float TimeLimit; // the runtime budget for this call
+};
+
+// SEC parametesr
+struct Fra_Sec_t_
+{
+ int fTryComb; // try CEC call as a preprocessing step
+ int fTryBmc; // try BMC call as a preprocessing step
+ int nFramesMax; // the max number of frames used for induction
+ int nBTLimit; // the conflict limit at a node
+ int nBTLimitGlobal; // the global conflict limit
+ int nBTLimitInter; // the conflict limit for interpolation
+ int nBddVarsMax; // the state space limit for BDD reachability
+ int nBddMax; // the max number of BDD nodes
+ int nBddIterMax; // the limit on the number of BDD iterations
+ int nPdrTimeout; // the timeout for PDR in the end
+ int fPhaseAbstract; // enables phase abstraction
+ int fRetimeFirst; // enables most-forward retiming at the beginning
+ int fRetimeRegs; // enables min-register retiming at the beginning
+ int fFraiging; // enables fraiging at the beginning
+ int fInduction; // enable the use of induction
+ int fInterpolation; // enables interpolation
+ int fInterSeparate; // enables interpolation for each outputs separately
+ int fReachability; // enables BDD based reachability
+ int fReorderImage; // enables BDD reordering during image computation
+ int fStopOnFirstFail; // enables stopping after first output of a miter has failed to prove
+ int fUseNewProver; // the new prover
+ int fUsePdr; // the PDR
+ int fSilent; // disables all output
+ int fVerbose; // enables verbose reporting of statistics
+ int fVeryVerbose; // enables very verbose reporting
+ int TimeLimit; // enables the timeout
+ int fReadUnsolved; // inserts the unsolved model back
+ int nSMnumber; // the number of model written
+ // internal parameters
+ int fRecursive; // set to 1 when SEC is called recursively
+ int fReportSolution; // enables report solution in a special form
+};
+
+// FRAIG equivalence classes
+struct Fra_Cla_t_
+{
+ Aig_Man_t * pAig; // the original AIG manager
+ Aig_Obj_t ** pMemRepr; // pointers to representatives of each node
+ Vec_Ptr_t * vClasses; // equivalence classes
+ Vec_Ptr_t * vClasses1; // equivalence class of Const1 node
+ Vec_Ptr_t * vClassesTemp; // temporary storage for new classes
+ Aig_Obj_t ** pMemClasses; // memory allocated for equivalence classes
+ Aig_Obj_t ** pMemClassesFree; // memory allocated for equivalence classes to be used
+ Vec_Ptr_t * vClassOld; // old equivalence class after splitting
+ Vec_Ptr_t * vClassNew; // new equivalence class(es) after splitting
+ int nPairs; // the number of pairs of nodes
+ int fRefinement; // set to 1 when refinement has happened
+ Vec_Int_t * vImps; // implications
+ // procedures used for class refinement
+ int (*pFuncNodeHash) (Aig_Obj_t *, int); // returns has key of the node
+ int (*pFuncNodeIsConst) (Aig_Obj_t *); // returns 1 if the node is a constant
+ int (*pFuncNodesAreEqual)(Aig_Obj_t *, Aig_Obj_t *); // returns 1 if nodes are equal up to a complement
+};
+
+// simulation manager
+struct Fra_Sml_t_
+{
+ Aig_Man_t * pAig; // the original AIG manager
+ int nPref; // the number of times frames in the prefix
+ int nFrames; // the number of times frames
+ int nWordsFrame; // the number of words in each time frame
+ int nWordsTotal; // the total number of words at a node
+ int nWordsPref; // the number of word in the prefix
+ int fNonConstOut; // have seen a non-const-0 output during simulation
+ int nSimRounds; // statistics
+ int timeSim; // statistics
+ unsigned pData[0]; // simulation data for the nodes
+};
+
+// FRAIG manager
+struct Fra_Man_t_
+{
+ // high-level data
+ Fra_Par_t * pPars; // parameters governing fraiging
+ // AIG managers
+ Aig_Man_t * pManAig; // the starting AIG manager
+ Aig_Man_t * pManFraig; // the final AIG manager
+ // mapping AIG into FRAIG
+ int nFramesAll; // the number of timeframes used
+ Aig_Obj_t ** pMemFraig; // memory allocated for points to the fraig nodes
+ int nSizeAlloc; // allocated size of the arrays for timeframe nodes
+ // equivalence classes
+ Fra_Cla_t * pCla; // representation of (candidate) equivalent nodes
+ // simulation info
+ Fra_Sml_t * pSml; // simulation manager
+ // bounded model checking manager
+ Fra_Bmc_t * pBmc;
+ // counter example storage
+ int nPatWords; // the number of words in the counter example
+ unsigned * pPatWords; // the counter example
+ Vec_Int_t * vCex;
+ // one-hotness conditions
+ Vec_Int_t * vOneHots;
+ // satisfiability solving
+ sat_solver * pSat; // SAT solver
+ int nSatVars; // the number of variables currently used
+ Vec_Ptr_t * vPiVars; // the PIs of the cone used
+ ABC_INT64_T nBTLimitGlobal; // resource limit
+ ABC_INT64_T nInsLimitGlobal; // resource limit
+ Vec_Ptr_t ** pMemFanins; // the arrays of fanins for some FRAIG nodes
+ int * pMemSatNums; // the array of SAT numbers for some FRAIG nodes
+ int nMemAlloc; // allocated size of the arrays for FRAIG varnums and fanins
+ Vec_Ptr_t * vTimeouts; // the nodes, for which equivalence checking timed out
+ // statistics
+ int nSimRounds;
+ int nNodesMiter;
+ int nLitsBeg;
+ int nLitsEnd;
+ int nNodesBeg;
+ int nNodesEnd;
+ int nRegsBeg;
+ int nRegsEnd;
+ int nSatCalls;
+ int nSatCallsSat;
+ int nSatCallsUnsat;
+ int nSatProof;
+ int nSatFails;
+ int nSatFailsReal;
+ int nSpeculs;
+ int nChoices;
+ int nChoicesFake;
+ int nSatCallsRecent;
+ int nSatCallsSkipped;
+ // runtime
+ int timeSim;
+ int timeTrav;
+ int timeRwr;
+ int timeSat;
+ int timeSatUnsat;
+ int timeSatSat;
+ int timeSatFail;
+ int timeRef;
+ int timeTotal;
+ int time1;
+ int time2;
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static inline unsigned * Fra_ObjSim( Fra_Sml_t * p, int Id ) { return p->pData + p->nWordsTotal * Id; }
+static inline unsigned Fra_ObjRandomSim() { return Aig_ManRandom(0); }
+
+static inline Aig_Obj_t * Fra_ObjFraig( Aig_Obj_t * pObj, int i ) { return ((Fra_Man_t *)pObj->pData)->pMemFraig[((Fra_Man_t *)pObj->pData)->nFramesAll*pObj->Id + i]; }
+static inline void Fra_ObjSetFraig( Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { ((Fra_Man_t *)pObj->pData)->pMemFraig[((Fra_Man_t *)pObj->pData)->nFramesAll*pObj->Id + i] = pNode; }
+
+static inline Vec_Ptr_t * Fra_ObjFaninVec( Aig_Obj_t * pObj ) { return ((Fra_Man_t *)pObj->pData)->pMemFanins[pObj->Id]; }
+static inline void Fra_ObjSetFaninVec( Aig_Obj_t * pObj, Vec_Ptr_t * vFanins ) { ((Fra_Man_t *)pObj->pData)->pMemFanins[pObj->Id] = vFanins; }
+
+static inline int Fra_ObjSatNum( Aig_Obj_t * pObj ) { return ((Fra_Man_t *)pObj->pData)->pMemSatNums[pObj->Id]; }
+static inline void Fra_ObjSetSatNum( Aig_Obj_t * pObj, int Num ) { ((Fra_Man_t *)pObj->pData)->pMemSatNums[pObj->Id] = Num; }
+
+static inline Aig_Obj_t * Fra_ClassObjRepr( Aig_Obj_t * pObj ) { return ((Fra_Man_t *)pObj->pData)->pCla->pMemRepr[pObj->Id]; }
+static inline void Fra_ClassObjSetRepr( Aig_Obj_t * pObj, Aig_Obj_t * pNode ) { ((Fra_Man_t *)pObj->pData)->pCla->pMemRepr[pObj->Id] = pNode; }
+
+static inline Aig_Obj_t * Fra_ObjChild0Fra( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Fra_ObjFraig(Aig_ObjFanin0(pObj),i), Aig_ObjFaninC0(pObj)) : NULL; }
+static inline Aig_Obj_t * Fra_ObjChild1Fra( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Fra_ObjFraig(Aig_ObjFanin1(pObj),i), Aig_ObjFaninC1(pObj)) : NULL; }
+
+static inline int Fra_ImpLeft( int Imp ) { return Imp & 0xFFFF; }
+static inline int Fra_ImpRight( int Imp ) { return Imp >> 16; }
+static inline int Fra_ImpCreate( int Left, int Right ) { return (Right << 16) | Left; }
+
+////////////////////////////////////////////////////////////////////////
+/// ITERATORS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== fraCec.c ========================================================*/
+extern int Fra_FraigSat( Aig_Man_t * pMan, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int fFlipBits, int fAndOuts, int fNewSolver, int fVerbose );
+extern int Fra_FraigCec( Aig_Man_t ** ppAig, int nConfLimit, int fVerbose );
+extern int Fra_FraigCecPartitioned( Aig_Man_t * pMan1, Aig_Man_t * pMan2, int nConfLimit, int nPartSize, int fSmart, int fVerbose );
+/*=== fraClass.c ========================================================*/
+extern int Fra_BmcNodeIsConst( Aig_Obj_t * pObj );
+extern int Fra_BmcNodesAreEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 );
+extern void Fra_BmcStop( Fra_Bmc_t * p );
+extern void Fra_BmcPerform( Fra_Man_t * p, int nPref, int nDepth );
+extern void Fra_BmcPerformSimple( Aig_Man_t * pAig, int nFrames, int nBTLimit, int fRewrite, int fVerbose );
+/*=== fraClass.c ========================================================*/
+extern Fra_Cla_t * Fra_ClassesStart( Aig_Man_t * pAig );
+extern void Fra_ClassesStop( Fra_Cla_t * p );
+extern void Fra_ClassesCopyReprs( Fra_Cla_t * p, Vec_Ptr_t * vFailed );
+extern void Fra_ClassesPrint( Fra_Cla_t * p, int fVeryVerbose );
+extern void Fra_ClassesPrepare( Fra_Cla_t * p, int fLatchCorr, int nMaxLevs );
+extern int Fra_ClassesRefine( Fra_Cla_t * p );
+extern int Fra_ClassesRefine1( Fra_Cla_t * p, int fRefineNewClass, int * pSkipped );
+extern int Fra_ClassesCountLits( Fra_Cla_t * p );
+extern int Fra_ClassesCountPairs( Fra_Cla_t * p );
+extern void Fra_ClassesTest( Fra_Cla_t * p, int Id1, int Id2 );
+extern void Fra_ClassesLatchCorr( Fra_Man_t * p );
+extern void Fra_ClassesPostprocess( Fra_Cla_t * p );
+extern void Fra_ClassesSelectRepr( Fra_Cla_t * p );
+extern Aig_Man_t * Fra_ClassesDeriveAig( Fra_Cla_t * p, int nFramesK );
+/*=== fraCnf.c ========================================================*/
+extern void Fra_CnfNodeAddToSolver( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew );
+/*=== fraCore.c ========================================================*/
+extern void Fra_FraigSweep( Fra_Man_t * pManAig );
+extern int Fra_FraigMiterStatus( Aig_Man_t * p );
+extern int Fra_FraigMiterAssertedOutput( Aig_Man_t * p );
+extern Aig_Man_t * Fra_FraigPerform( Aig_Man_t * pManAig, Fra_Par_t * pPars );
+extern Aig_Man_t * Fra_FraigChoice( Aig_Man_t * pManAig, int nConfMax, int nLevelMax );
+extern Aig_Man_t * Fra_FraigEquivence( Aig_Man_t * pManAig, int nConfMax, int fProve );
+/*=== fraHot.c ========================================================*/
+extern Vec_Int_t * Fra_OneHotCompute( Fra_Man_t * p, Fra_Sml_t * pSim );
+extern void Fra_OneHotAssume( Fra_Man_t * p, Vec_Int_t * vOneHots );
+extern void Fra_OneHotCheck( Fra_Man_t * p, Vec_Int_t * vOneHots );
+extern int Fra_OneHotRefineUsingCex( Fra_Man_t * p, Vec_Int_t * vOneHots );
+extern int Fra_OneHotCount( Fra_Man_t * p, Vec_Int_t * vOneHots );
+extern void Fra_OneHotEstimateCoverage( Fra_Man_t * p, Vec_Int_t * vOneHots );
+extern Aig_Man_t * Fra_OneHotCreateExdc( Fra_Man_t * p, Vec_Int_t * vOneHots );
+extern void Fra_OneHotAddKnownConstraint( Fra_Man_t * p, Vec_Ptr_t * vOnehots );
+/*=== fraImp.c ========================================================*/
+extern Vec_Int_t * Fra_ImpDerive( Fra_Man_t * p, int nImpMaxLimit, int nImpUseLimit, int fLatchCorr );
+extern void Fra_ImpAddToSolver( Fra_Man_t * p, Vec_Int_t * vImps, int * pSatVarNums );
+extern int Fra_ImpCheckForNode( Fra_Man_t * p, Vec_Int_t * vImps, Aig_Obj_t * pNode, int Pos );
+extern int Fra_ImpRefineUsingCex( Fra_Man_t * p, Vec_Int_t * vImps );
+extern void Fra_ImpCompactArray( Vec_Int_t * vImps );
+extern double Fra_ImpComputeStateSpaceRatio( Fra_Man_t * p );
+extern int Fra_ImpVerifyUsingSimulation( Fra_Man_t * p );
+extern void Fra_ImpRecordInManager( Fra_Man_t * p, Aig_Man_t * pNew );
+/*=== fraInd.c ========================================================*/
+extern Aig_Man_t * Fra_FraigInduction( Aig_Man_t * p, Fra_Ssw_t * pPars );
+/*=== fraIndVer.c =====================================================*/
+extern int Fra_InvariantVerify( Aig_Man_t * p, int nFrames, Vec_Int_t * vClauses, Vec_Int_t * vLits );
+/*=== fraLcr.c ========================================================*/
+extern Aig_Man_t * Fra_FraigLatchCorrespondence( Aig_Man_t * pAig, int nFramesP, int nConfMax, int fProve, int fVerbose, int * pnIter, float TimeLimit );
+/*=== fraMan.c ========================================================*/
+extern void Fra_ParamsDefault( Fra_Par_t * pParams );
+extern void Fra_ParamsDefaultSeq( Fra_Par_t * pParams );
+extern Fra_Man_t * Fra_ManStart( Aig_Man_t * pManAig, Fra_Par_t * pParams );
+extern void Fra_ManClean( Fra_Man_t * p, int nNodesMax );
+extern Aig_Man_t * Fra_ManPrepareComb( Fra_Man_t * p );
+extern void Fra_ManFinalizeComb( Fra_Man_t * p );
+extern void Fra_ManStop( Fra_Man_t * p );
+extern void Fra_ManPrint( Fra_Man_t * p );
+/*=== fraSat.c ========================================================*/
+extern int Fra_NodesAreEquiv( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew );
+extern int Fra_NodesAreImp( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew, int fComplL, int fComplR );
+extern int Fra_NodesAreClause( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew, int fComplL, int fComplR );
+extern int Fra_NodeIsConst( Fra_Man_t * p, Aig_Obj_t * pNew );
+/*=== fraSec.c ========================================================*/
+extern void Fra_SecSetDefaultParams( Fra_Sec_t * p );
+extern int Fra_FraigSec( Aig_Man_t * p, Fra_Sec_t * pParSec, Aig_Man_t ** ppResult );
+/*=== fraSim.c ========================================================*/
+extern int Fra_SmlNodeHash( Aig_Obj_t * pObj, int nTableSize );
+extern int Fra_SmlNodeIsConst( Aig_Obj_t * pObj );
+extern int Fra_SmlNodesAreEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 );
+extern int Fra_SmlNodeNotEquWeight( Fra_Sml_t * p, int Left, int Right );
+extern int Fra_SmlNodeCountOnes( Fra_Sml_t * p, Aig_Obj_t * pObj );
+extern int Fra_SmlCheckOutput( Fra_Man_t * p );
+extern void Fra_SmlSavePattern( Fra_Man_t * p );
+extern void Fra_SmlSimulate( Fra_Man_t * p, int fInit );
+extern void Fra_SmlResimulate( Fra_Man_t * p );
+extern Fra_Sml_t * Fra_SmlStart( Aig_Man_t * pAig, int nPref, int nFrames, int nWordsFrame );
+extern void Fra_SmlStop( Fra_Sml_t * p );
+extern Fra_Sml_t * Fra_SmlSimulateSeq( Aig_Man_t * pAig, int nPref, int nFrames, int nWords, int fCheckMiter );
+extern Fra_Sml_t * Fra_SmlSimulateComb( Aig_Man_t * pAig, int nWords );
+extern Abc_Cex_t * Fra_SmlGetCounterExample( Fra_Sml_t * p );
+extern Abc_Cex_t * Fra_SmlCopyCounterExample( Aig_Man_t * pAig, Aig_Man_t * pFrames, int * pModel );
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/proof/fra/fraBmc.c b/src/proof/fra/fraBmc.c
new file mode 100644
index 00000000..7b4db3de
--- /dev/null
+++ b/src/proof/fra/fraBmc.c
@@ -0,0 +1,451 @@
+/**CFile****************************************************************
+
+ FileName [fraBmc.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [New FRAIG package.]
+
+ Synopsis [Bounded model checking.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 30, 2007.]
+
+ Revision [$Id: fraBmc.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// simulation manager
+struct Fra_Bmc_t_
+{
+ // parameters
+ int nPref; // the size of the prefix
+ int nDepth; // the depth of the frames
+ int nFramesAll; // the total number of timeframes
+ // implications to be filtered
+ Vec_Int_t * vImps;
+ // AIG managers
+ Aig_Man_t * pAig; // the original AIG manager
+ Aig_Man_t * pAigFrames; // initialized timeframes
+ Aig_Man_t * pAigFraig; // the fraiged initialized timeframes
+ // mapping of nodes
+ Aig_Obj_t ** pObjToFrames; // mapping of the original node into frames
+ Aig_Obj_t ** pObjToFraig; // mapping of the frames node into fraig
+};
+
+static inline Aig_Obj_t * Bmc_ObjFrames( Aig_Obj_t * pObj, int i ) { return ((Fra_Man_t *)pObj->pData)->pBmc->pObjToFrames[((Fra_Man_t *)pObj->pData)->pBmc->nFramesAll*pObj->Id + i]; }
+static inline void Bmc_ObjSetFrames( Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { ((Fra_Man_t *)pObj->pData)->pBmc->pObjToFrames[((Fra_Man_t *)pObj->pData)->pBmc->nFramesAll*pObj->Id + i] = pNode; }
+
+static inline Aig_Obj_t * Bmc_ObjFraig( Aig_Obj_t * pObj ) { return ((Fra_Man_t *)pObj->pData)->pBmc->pObjToFraig[pObj->Id]; }
+static inline void Bmc_ObjSetFraig( Aig_Obj_t * pObj, Aig_Obj_t * pNode ) { ((Fra_Man_t *)pObj->pData)->pBmc->pObjToFraig[pObj->Id] = pNode; }
+
+static inline Aig_Obj_t * Bmc_ObjChild0Frames( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Bmc_ObjFrames(Aig_ObjFanin0(pObj),i), Aig_ObjFaninC0(pObj)) : NULL; }
+static inline Aig_Obj_t * Bmc_ObjChild1Frames( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Bmc_ObjFrames(Aig_ObjFanin1(pObj),i), Aig_ObjFaninC1(pObj)) : NULL; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the nodes are equivalent.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_BmcNodesAreEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
+{
+ Fra_Man_t * p = (Fra_Man_t *)pObj0->pData;
+ Aig_Obj_t * pObjFrames0, * pObjFrames1;
+ Aig_Obj_t * pObjFraig0, * pObjFraig1;
+ int i;
+ for ( i = p->pBmc->nPref; i < p->pBmc->nFramesAll; i++ )
+ {
+ pObjFrames0 = Aig_Regular( Bmc_ObjFrames(pObj0, i) );
+ pObjFrames1 = Aig_Regular( Bmc_ObjFrames(pObj1, i) );
+ if ( pObjFrames0 == pObjFrames1 )
+ continue;
+ pObjFraig0 = Aig_Regular( Bmc_ObjFraig(pObjFrames0) );
+ pObjFraig1 = Aig_Regular( Bmc_ObjFraig(pObjFrames1) );
+ if ( pObjFraig0 != pObjFraig1 )
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the node is costant.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_BmcNodeIsConst( Aig_Obj_t * pObj )
+{
+ Fra_Man_t * p = (Fra_Man_t *)pObj->pData;
+ return Fra_BmcNodesAreEqual( pObj, Aig_ManConst1(p->pManAig) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Refines implications using BMC.]
+
+ Description [The input is the combinational FRAIG manager,
+ which is used to FRAIG the timeframes. ]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_BmcFilterImplications( Fra_Man_t * p, Fra_Bmc_t * pBmc )
+{
+ Aig_Obj_t * pLeft, * pRight;
+ Aig_Obj_t * pLeftT, * pRightT;
+ Aig_Obj_t * pLeftF, * pRightF;
+ int i, f, Imp, Left, Right;
+ int fComplL, fComplR;
+ assert( p->nFramesAll == 1 );
+ assert( p->pManAig == pBmc->pAigFrames );
+ Vec_IntForEachEntry( pBmc->vImps, Imp, i )
+ {
+ if ( Imp == 0 )
+ continue;
+ Left = Fra_ImpLeft(Imp);
+ Right = Fra_ImpRight(Imp);
+ // get the corresponding nodes
+ pLeft = Aig_ManObj( pBmc->pAig, Left );
+ pRight = Aig_ManObj( pBmc->pAig, Right );
+ // iterate through the timeframes
+ for ( f = pBmc->nPref; f < pBmc->nFramesAll; f++ )
+ {
+ // get timeframe nodes
+ pLeftT = Bmc_ObjFrames( pLeft, f );
+ pRightT = Bmc_ObjFrames( pRight, f );
+ // get the corresponding FRAIG nodes
+ pLeftF = Fra_ObjFraig( Aig_Regular(pLeftT), 0 );
+ pRightF = Fra_ObjFraig( Aig_Regular(pRightT), 0 );
+ // get the complemented attributes
+ fComplL = pLeft->fPhase ^ Aig_IsComplement(pLeftF) ^ Aig_IsComplement(pLeftT);
+ fComplR = pRight->fPhase ^ Aig_IsComplement(pRightF) ^ Aig_IsComplement(pRightT);
+ // check equality
+ if ( Aig_Regular(pLeftF) == Aig_Regular(pRightF) )
+ {
+ if ( fComplL == fComplR ) // x => x - always true
+ continue;
+ assert( fComplL != fComplR );
+ // consider 4 possibilities:
+ // NOT(1) => 1 or 0 => 1 - always true
+ // 1 => NOT(1) or 1 => 0 - never true
+ // NOT(x) => x or x - not always true
+ // x => NOT(x) or NOT(x) - not always true
+ if ( Aig_ObjIsConst1(Aig_Regular(pLeftF)) && fComplL ) // proved implication
+ continue;
+ // disproved implication
+ Vec_IntWriteEntry( pBmc->vImps, i, 0 );
+ break;
+ }
+ // check the implication
+ if ( Fra_NodesAreImp( p, Aig_Regular(pLeftF), Aig_Regular(pRightF), fComplL, fComplR ) != 1 )
+ {
+ Vec_IntWriteEntry( pBmc->vImps, i, 0 );
+ break;
+ }
+ }
+ }
+ Fra_ImpCompactArray( pBmc->vImps );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Starts the BMC manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fra_Bmc_t * Fra_BmcStart( Aig_Man_t * pAig, int nPref, int nDepth )
+{
+ Fra_Bmc_t * p;
+ p = ABC_ALLOC( Fra_Bmc_t, 1 );
+ memset( p, 0, sizeof(Fra_Bmc_t) );
+ p->pAig = pAig;
+ p->nPref = nPref;
+ p->nDepth = nDepth;
+ p->nFramesAll = nPref + nDepth;
+ p->pObjToFrames = ABC_ALLOC( Aig_Obj_t *, p->nFramesAll * Aig_ManObjNumMax(pAig) );
+ memset( p->pObjToFrames, 0, sizeof(Aig_Obj_t *) * p->nFramesAll * Aig_ManObjNumMax(pAig) );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the BMC manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_BmcStop( Fra_Bmc_t * p )
+{
+ Aig_ManStop( p->pAigFrames );
+ if ( p->pAigFraig )
+ Aig_ManStop( p->pAigFraig );
+ ABC_FREE( p->pObjToFrames );
+ ABC_FREE( p->pObjToFraig );
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Constructs initialized timeframes of the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Fra_BmcFrames( Fra_Bmc_t * p, int fKeepPos )
+{
+ Aig_Man_t * pAigFrames;
+ Aig_Obj_t * pObj, * pObjNew;
+ Aig_Obj_t ** pLatches;
+ int i, k, f;
+
+ // start the fraig package
+ pAigFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->nFramesAll );
+ pAigFrames->pName = Abc_UtilStrsav( p->pAig->pName );
+ pAigFrames->pSpec = Abc_UtilStrsav( p->pAig->pSpec );
+ // create PI nodes for the frames
+ for ( f = 0; f < p->nFramesAll; f++ )
+ Bmc_ObjSetFrames( Aig_ManConst1(p->pAig), f, Aig_ManConst1(pAigFrames) );
+ for ( f = 0; f < p->nFramesAll; f++ )
+ Aig_ManForEachPiSeq( p->pAig, pObj, i )
+ Bmc_ObjSetFrames( pObj, f, Aig_ObjCreatePi(pAigFrames) );
+ // set initial state for the latches
+ Aig_ManForEachLoSeq( p->pAig, pObj, i )
+ Bmc_ObjSetFrames( pObj, 0, Aig_ManConst0(pAigFrames) );
+
+ // add timeframes
+ pLatches = ABC_ALLOC( Aig_Obj_t *, Aig_ManRegNum(p->pAig) );
+ for ( f = 0; f < p->nFramesAll; f++ )
+ {
+ // add internal nodes of this frame
+ Aig_ManForEachNode( p->pAig, pObj, i )
+ {
+ pObjNew = Aig_And( pAigFrames, Bmc_ObjChild0Frames(pObj,f), Bmc_ObjChild1Frames(pObj,f) );
+ Bmc_ObjSetFrames( pObj, f, pObjNew );
+ }
+ if ( f == p->nFramesAll - 1 )
+ break;
+ // save the latch input values
+ k = 0;
+ Aig_ManForEachLiSeq( p->pAig, pObj, i )
+ pLatches[k++] = Bmc_ObjChild0Frames(pObj,f);
+ assert( k == Aig_ManRegNum(p->pAig) );
+ // insert them to the latch output values
+ k = 0;
+ Aig_ManForEachLoSeq( p->pAig, pObj, i )
+ Bmc_ObjSetFrames( pObj, f+1, pLatches[k++] );
+ assert( k == Aig_ManRegNum(p->pAig) );
+ }
+ ABC_FREE( pLatches );
+ if ( fKeepPos )
+ {
+ for ( f = 0; f < p->nFramesAll; f++ )
+ Aig_ManForEachPoSeq( p->pAig, pObj, i )
+ Aig_ObjCreatePo( pAigFrames, Bmc_ObjChild0Frames(pObj,f) );
+ Aig_ManCleanup( pAigFrames );
+ }
+ else
+ {
+ // add POs to all the dangling nodes
+ Aig_ManForEachObj( pAigFrames, pObjNew, i )
+ if ( Aig_ObjIsNode(pObjNew) && pObjNew->nRefs == 0 )
+ Aig_ObjCreatePo( pAigFrames, pObjNew );
+ }
+ // return the new manager
+ return pAigFrames;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs BMC for the given AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_BmcPerform( Fra_Man_t * p, int nPref, int nDepth )
+{
+ Aig_Obj_t * pObj;
+ int i, nImpsOld = 0, clk = clock();
+ assert( p->pBmc == NULL );
+ // derive and fraig the frames
+ p->pBmc = Fra_BmcStart( p->pManAig, nPref, nDepth );
+ p->pBmc->pAigFrames = Fra_BmcFrames( p->pBmc, 0 );
+ // if implications are present, configure the AIG manager to check them
+ if ( p->pCla->vImps )
+ {
+ p->pBmc->pAigFrames->pImpFunc = (void (*) (void*, void*))Fra_BmcFilterImplications;
+ p->pBmc->pAigFrames->pImpData = p->pBmc;
+ p->pBmc->vImps = p->pCla->vImps;
+ nImpsOld = Vec_IntSize(p->pCla->vImps);
+ }
+ p->pBmc->pAigFraig = Fra_FraigEquivence( p->pBmc->pAigFrames, 1000000, 0 );
+ p->pBmc->pObjToFraig = p->pBmc->pAigFrames->pObjCopies;
+ p->pBmc->pAigFrames->pObjCopies = NULL;
+ // annotate frames nodes with pointers to the manager
+ Aig_ManForEachObj( p->pBmc->pAigFrames, pObj, i )
+ pObj->pData = p;
+ // report the results
+ if ( p->pPars->fVerbose )
+ {
+ printf( "Original AIG = %d. Init %d frames = %d. Fraig = %d. ",
+ Aig_ManNodeNum(p->pBmc->pAig), p->pBmc->nFramesAll,
+ Aig_ManNodeNum(p->pBmc->pAigFrames), Aig_ManNodeNum(p->pBmc->pAigFraig) );
+ ABC_PRT( "Time", clock() - clk );
+ printf( "Before BMC: " );
+// Fra_ClassesPrint( p->pCla, 0 );
+ printf( "Const = %5d. Class = %5d. Lit = %5d. ",
+ Vec_PtrSize(p->pCla->vClasses1), Vec_PtrSize(p->pCla->vClasses), Fra_ClassesCountLits(p->pCla) );
+ if ( p->pCla->vImps )
+ printf( "Imp = %5d. ", nImpsOld );
+ printf( "\n" );
+ }
+ // refine the classes
+ p->pCla->pFuncNodeIsConst = Fra_BmcNodeIsConst;
+ p->pCla->pFuncNodesAreEqual = Fra_BmcNodesAreEqual;
+ Fra_ClassesRefine( p->pCla );
+ Fra_ClassesRefine1( p->pCla, 1, NULL );
+ p->pCla->pFuncNodeIsConst = Fra_SmlNodeIsConst;
+ p->pCla->pFuncNodesAreEqual = Fra_SmlNodesAreEqual;
+ // report the results
+ if ( p->pPars->fVerbose )
+ {
+ printf( "After BMC: " );
+// Fra_ClassesPrint( p->pCla, 0 );
+ printf( "Const = %5d. Class = %5d. Lit = %5d. ",
+ Vec_PtrSize(p->pCla->vClasses1), Vec_PtrSize(p->pCla->vClasses), Fra_ClassesCountLits(p->pCla) );
+ if ( p->pCla->vImps )
+ printf( "Imp = %5d. ", Vec_IntSize(p->pCla->vImps) );
+ printf( "\n" );
+ }
+ // free the BMC manager
+ Fra_BmcStop( p->pBmc );
+ p->pBmc = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs BMC for the given AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_BmcPerformSimple( Aig_Man_t * pAig, int nFrames, int nBTLimit, int fRewrite, int fVerbose )
+{
+ extern Fra_Man_t * Fra_LcrAigPrepare( Aig_Man_t * pAig );
+ Fra_Man_t * pTemp;
+ Fra_Bmc_t * pBmc;
+ Aig_Man_t * pAigTemp;
+ int clk, iOutput;
+ // derive and fraig the frames
+ clk = clock();
+ pBmc = Fra_BmcStart( pAig, 0, nFrames );
+ pTemp = Fra_LcrAigPrepare( pAig );
+ pTemp->pBmc = pBmc;
+ pBmc->pAigFrames = Fra_BmcFrames( pBmc, 1 );
+ if ( fVerbose )
+ {
+ printf( "AIG: PI/PO/Reg = %d/%d/%d. Node = %6d. Lev = %5d.\n",
+ Aig_ManPiNum(pAig)-Aig_ManRegNum(pAig), Aig_ManPoNum(pAig)-Aig_ManRegNum(pAig), Aig_ManRegNum(pAig),
+ Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig) );
+ printf( "Time-frames (%d): PI/PO = %d/%d. Node = %6d. Lev = %5d. ",
+ nFrames, Aig_ManPiNum(pBmc->pAigFrames), Aig_ManPoNum(pBmc->pAigFrames),
+ Aig_ManNodeNum(pBmc->pAigFrames), Aig_ManLevelNum(pBmc->pAigFrames) );
+ ABC_PRT( "Time", clock() - clk );
+ }
+ if ( fRewrite )
+ {
+ clk = clock();
+ pBmc->pAigFrames = Dar_ManRwsat( pAigTemp = pBmc->pAigFrames, 1, 0 );
+ Aig_ManStop( pAigTemp );
+ if ( fVerbose )
+ {
+ printf( "Time-frames after rewriting: Node = %6d. Lev = %5d. ",
+ Aig_ManNodeNum(pBmc->pAigFrames), Aig_ManLevelNum(pBmc->pAigFrames) );
+ ABC_PRT( "Time", clock() - clk );
+ }
+ }
+ clk = clock();
+ iOutput = Fra_FraigMiterAssertedOutput( pBmc->pAigFrames );
+ if ( iOutput >= 0 )
+ pAig->pSeqModel = Abc_CexMakeTriv( Aig_ManRegNum(pAig), Aig_ManPiNum(pAig)-Aig_ManRegNum(pAig), Aig_ManPoNum(pAig)-Aig_ManRegNum(pAig), iOutput );
+ else
+ {
+ pBmc->pAigFraig = Fra_FraigEquivence( pBmc->pAigFrames, nBTLimit, 1 );
+ iOutput = Fra_FraigMiterAssertedOutput( pBmc->pAigFraig );
+ if ( pBmc->pAigFraig->pData )
+ {
+ pAig->pSeqModel = Fra_SmlCopyCounterExample( pAig, pBmc->pAigFrames, (int *)pBmc->pAigFraig->pData );
+ ABC_FREE( pBmc->pAigFraig->pData );
+ }
+ else if ( iOutput >= 0 )
+ pAig->pSeqModel = Abc_CexMakeTriv( Aig_ManRegNum(pAig), Aig_ManPiNum(pAig)-Aig_ManRegNum(pAig), Aig_ManPoNum(pAig)-Aig_ManRegNum(pAig), iOutput );
+ }
+ if ( fVerbose )
+ {
+ printf( "Fraiged init frames: Node = %6d. Lev = %5d. ",
+ pBmc->pAigFraig? Aig_ManNodeNum(pBmc->pAigFraig) : -1,
+ pBmc->pAigFraig? Aig_ManLevelNum(pBmc->pAigFraig) : -1 );
+ ABC_PRT( "Time", clock() - clk );
+ }
+ Fra_BmcStop( pBmc );
+ ABC_FREE( pTemp );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fra/fraCec.c b/src/proof/fra/fraCec.c
new file mode 100644
index 00000000..ac11b0bb
--- /dev/null
+++ b/src/proof/fra/fraCec.c
@@ -0,0 +1,516 @@
+/**CFile****************************************************************
+
+ FileName [fraCec.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [New FRAIG package.]
+
+ Synopsis [CEC engined based on fraiging.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 30, 2007.]
+
+ Revision [$Id: fraCec.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+#include "src/sat/cnf/cnf.h"
+#include "src/sat/bsat/satSolver2.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_FraigSat( Aig_Man_t * pMan, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int fFlipBits, int fAndOuts, int fNewSolver, int fVerbose )
+{
+ if ( fNewSolver )
+ {
+ extern void * Cnf_DataWriteIntoSolver2( Cnf_Dat_t * p, int nFrames, int fInit );
+ extern int Cnf_DataWriteOrClause2( void * pSat, Cnf_Dat_t * pCnf );
+
+ sat_solver2 * pSat;
+ Cnf_Dat_t * pCnf;
+ int status, RetValue, clk = clock();
+ Vec_Int_t * vCiIds;
+
+ assert( Aig_ManRegNum(pMan) == 0 );
+ pMan->pData = NULL;
+
+ // derive CNF
+ pCnf = Cnf_Derive( pMan, Aig_ManPoNum(pMan) );
+ // pCnf = Cnf_DeriveSimple( pMan, Aig_ManPoNum(pMan) );
+
+ if ( fFlipBits )
+ Cnf_DataTranformPolarity( pCnf, 0 );
+
+ // convert into SAT solver
+ pSat = (sat_solver2 *)Cnf_DataWriteIntoSolver2( pCnf, 1, 0 );
+ if ( pSat == NULL )
+ {
+ Cnf_DataFree( pCnf );
+ return 1;
+ }
+
+
+ if ( fAndOuts )
+ {
+ // assert each output independently
+ if ( !Cnf_DataWriteAndClauses( pSat, pCnf ) )
+ {
+ sat_solver2_delete( pSat );
+ Cnf_DataFree( pCnf );
+ return 1;
+ }
+ }
+ else
+ {
+ // add the OR clause for the outputs
+ if ( !Cnf_DataWriteOrClause2( pSat, pCnf ) )
+ {
+ sat_solver2_delete( pSat );
+ Cnf_DataFree( pCnf );
+ return 1;
+ }
+ }
+ vCiIds = Cnf_DataCollectPiSatNums( pCnf, pMan );
+ Cnf_DataFree( pCnf );
+
+
+ printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver2_nvars(pSat), sat_solver2_nclauses(pSat) );
+ ABC_PRT( "Time", clock() - clk );
+
+ // simplify the problem
+ clk = clock();
+ status = sat_solver2_simplify(pSat);
+// printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver2_nvars(pSat), sat_solver2_nclauses(pSat) );
+// ABC_PRT( "Time", clock() - clk );
+ if ( status == 0 )
+ {
+ Vec_IntFree( vCiIds );
+ sat_solver2_delete( pSat );
+ // printf( "The problem is UNSATISFIABLE after simplification.\n" );
+ return 1;
+ }
+
+ // solve the miter
+ clk = clock();
+ if ( fVerbose )
+ pSat->verbosity = 1;
+ status = sat_solver2_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+ if ( status == l_Undef )
+ {
+ // printf( "The problem timed out.\n" );
+ RetValue = -1;
+ }
+ else if ( status == l_True )
+ {
+ // printf( "The problem is SATISFIABLE.\n" );
+ RetValue = 0;
+ }
+ else if ( status == l_False )
+ {
+ // printf( "The problem is UNSATISFIABLE.\n" );
+ RetValue = 1;
+ }
+ else
+ assert( 0 );
+
+ // Abc_Print( 1, "The number of conflicts = %6d. ", (int)pSat->stats.conflicts );
+ // Abc_PrintTime( 1, "Solving time", clock() - clk );
+
+ // if the problem is SAT, get the counterexample
+ if ( status == l_True )
+ {
+ pMan->pData = Sat_Solver2GetModel( pSat, vCiIds->pArray, vCiIds->nSize );
+ }
+ // free the sat_solver2
+ if ( fVerbose )
+ Sat_Solver2PrintStats( stdout, pSat );
+ //sat_solver2_store_write( pSat, "trace.cnf" );
+ //sat_solver2_store_free( pSat );
+ sat_solver2_delete( pSat );
+ Vec_IntFree( vCiIds );
+ return RetValue;
+ }
+ else
+ {
+ sat_solver * pSat;
+ Cnf_Dat_t * pCnf;
+ int status, RetValue, clk = clock();
+ Vec_Int_t * vCiIds;
+
+ assert( Aig_ManRegNum(pMan) == 0 );
+ pMan->pData = NULL;
+
+ // derive CNF
+ pCnf = Cnf_Derive( pMan, Aig_ManPoNum(pMan) );
+ // pCnf = Cnf_DeriveSimple( pMan, Aig_ManPoNum(pMan) );
+
+ if ( fFlipBits )
+ Cnf_DataTranformPolarity( pCnf, 0 );
+
+ // convert into SAT solver
+ pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+ if ( pSat == NULL )
+ {
+ Cnf_DataFree( pCnf );
+ return 1;
+ }
+
+
+ if ( fAndOuts )
+ {
+ // assert each output independently
+ if ( !Cnf_DataWriteAndClauses( pSat, pCnf ) )
+ {
+ sat_solver_delete( pSat );
+ Cnf_DataFree( pCnf );
+ return 1;
+ }
+ }
+ else
+ {
+ // add the OR clause for the outputs
+ if ( !Cnf_DataWriteOrClause( pSat, pCnf ) )
+ {
+ sat_solver_delete( pSat );
+ Cnf_DataFree( pCnf );
+ return 1;
+ }
+ }
+ vCiIds = Cnf_DataCollectPiSatNums( pCnf, pMan );
+ Cnf_DataFree( pCnf );
+
+
+ // printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) );
+ // ABC_PRT( "Time", clock() - clk );
+
+ // simplify the problem
+ clk = clock();
+ status = sat_solver_simplify(pSat);
+ // printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) );
+ // ABC_PRT( "Time", clock() - clk );
+ if ( status == 0 )
+ {
+ Vec_IntFree( vCiIds );
+ sat_solver_delete( pSat );
+ // printf( "The problem is UNSATISFIABLE after simplification.\n" );
+ return 1;
+ }
+
+ // solve the miter
+ clk = clock();
+ if ( fVerbose )
+ pSat->verbosity = 1;
+ status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+ if ( status == l_Undef )
+ {
+ // printf( "The problem timed out.\n" );
+ RetValue = -1;
+ }
+ else if ( status == l_True )
+ {
+ // printf( "The problem is SATISFIABLE.\n" );
+ RetValue = 0;
+ }
+ else if ( status == l_False )
+ {
+ // printf( "The problem is UNSATISFIABLE.\n" );
+ RetValue = 1;
+ }
+ else
+ assert( 0 );
+
+ // Abc_Print( 1, "The number of conflicts = %6d. ", (int)pSat->stats.conflicts );
+ // Abc_PrintTime( 1, "Solving time", clock() - clk );
+
+ // if the problem is SAT, get the counterexample
+ if ( status == l_True )
+ {
+ pMan->pData = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize );
+ }
+ // free the sat_solver
+ if ( fVerbose )
+ Sat_SolverPrintStats( stdout, pSat );
+ //sat_solver_store_write( pSat, "trace.cnf" );
+ //sat_solver_store_free( pSat );
+ sat_solver_delete( pSat );
+ Vec_IntFree( vCiIds );
+ return RetValue;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_FraigCec( Aig_Man_t ** ppAig, int nConfLimit, int fVerbose )
+{
+ int nBTLimitStart = 300; // starting SAT run
+ int nBTLimitFirst = 2; // first fraiging iteration
+ int nBTLimitLast = nConfLimit; // the last-gasp SAT run
+
+ Fra_Par_t Params, * pParams = &Params;
+ Aig_Man_t * pAig = *ppAig, * pTemp;
+ int i, RetValue, clk;
+
+ // report the original miter
+ if ( fVerbose )
+ {
+ printf( "Original miter: Nodes = %6d.\n", Aig_ManNodeNum(pAig) );
+ }
+ RetValue = Fra_FraigMiterStatus( pAig );
+// assert( RetValue == -1 );
+ if ( RetValue == 0 )
+ {
+ pAig->pData = ABC_ALLOC( int, Aig_ManPiNum(pAig) );
+ memset( pAig->pData, 0, sizeof(int) * Aig_ManPiNum(pAig) );
+ return RetValue;
+ }
+
+ // if SAT only, solve without iteration
+clk = clock();
+ RetValue = Fra_FraigSat( pAig, (ABC_INT64_T)2*nBTLimitStart, (ABC_INT64_T)0, 1, 0, 0, 0 );
+ if ( fVerbose )
+ {
+ printf( "Initial SAT: Nodes = %6d. ", Aig_ManNodeNum(pAig) );
+ABC_PRT( "Time", clock() - clk );
+ }
+ if ( RetValue >= 0 )
+ return RetValue;
+
+ // duplicate the AIG
+clk = clock();
+ pAig = Dar_ManRwsat( pTemp = pAig, 1, 0 );
+ Aig_ManStop( pTemp );
+ if ( fVerbose )
+ {
+ printf( "Rewriting: Nodes = %6d. ", Aig_ManNodeNum(pAig) );
+ABC_PRT( "Time", clock() - clk );
+ }
+
+ // perform the loop
+ Fra_ParamsDefault( pParams );
+ pParams->nBTLimitNode = nBTLimitFirst;
+ pParams->nBTLimitMiter = nBTLimitStart;
+ pParams->fDontShowBar = 1;
+ pParams->fProve = 1;
+ for ( i = 0; i < 6; i++ )
+ {
+//printf( "Running fraiging with %d BTnode and %d BTmiter.\n", pParams->nBTLimitNode, pParams->nBTLimitMiter );
+ // run fraiging
+clk = clock();
+ pAig = Fra_FraigPerform( pTemp = pAig, pParams );
+ Aig_ManStop( pTemp );
+ if ( fVerbose )
+ {
+ printf( "Fraiging (i=%d): Nodes = %6d. ", i+1, Aig_ManNodeNum(pAig) );
+ABC_PRT( "Time", clock() - clk );
+ }
+
+ // check the miter status
+ RetValue = Fra_FraigMiterStatus( pAig );
+ if ( RetValue >= 0 )
+ break;
+
+ // perform rewriting
+clk = clock();
+ pAig = Dar_ManRewriteDefault( pTemp = pAig );
+ Aig_ManStop( pTemp );
+ if ( fVerbose )
+ {
+ printf( "Rewriting: Nodes = %6d. ", Aig_ManNodeNum(pAig) );
+ABC_PRT( "Time", clock() - clk );
+ }
+
+ // check the miter status
+ RetValue = Fra_FraigMiterStatus( pAig );
+ if ( RetValue >= 0 )
+ break;
+ // try simulation
+
+ // set the parameters for the next run
+ pParams->nBTLimitNode = 8 * pParams->nBTLimitNode;
+ pParams->nBTLimitMiter = 2 * pParams->nBTLimitMiter;
+ }
+
+ // if still unsolved try last gasp
+ if ( RetValue == -1 )
+ {
+clk = clock();
+ RetValue = Fra_FraigSat( pAig, (ABC_INT64_T)nBTLimitLast, (ABC_INT64_T)0, 1, 0, 0, 0 );
+ if ( fVerbose )
+ {
+ printf( "Final SAT: Nodes = %6d. ", Aig_ManNodeNum(pAig) );
+ABC_PRT( "Time", clock() - clk );
+ }
+ }
+
+ *ppAig = pAig;
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_FraigCecPartitioned( Aig_Man_t * pMan1, Aig_Man_t * pMan2, int nConfLimit, int nPartSize, int fSmart, int fVerbose )
+{
+ Aig_Man_t * pAig;
+ Vec_Ptr_t * vParts;
+ int i, RetValue = 1, nOutputs;
+ // create partitions
+ vParts = Aig_ManMiterPartitioned( pMan1, pMan2, nPartSize, fSmart );
+ // solve the partitions
+ nOutputs = -1;
+ Vec_PtrForEachEntry( Aig_Man_t *, vParts, pAig, i )
+ {
+ nOutputs++;
+ if ( fVerbose )
+ {
+ printf( "Verifying part %4d (out of %4d) PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r",
+ i+1, Vec_PtrSize(vParts), Aig_ManPiNum(pAig), Aig_ManPoNum(pAig),
+ Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig) );
+ fflush( stdout );
+ }
+ RetValue = Fra_FraigMiterStatus( pAig );
+ if ( RetValue == 1 )
+ continue;
+ if ( RetValue == 0 )
+ break;
+ RetValue = Fra_FraigCec( &pAig, nConfLimit, 0 );
+ Vec_PtrWriteEntry( vParts, i, pAig );
+ if ( RetValue == 1 )
+ continue;
+ if ( RetValue == 0 )
+ break;
+ break;
+ }
+ // clear the result
+ if ( fVerbose )
+ {
+ printf( " \r" );
+ fflush( stdout );
+ }
+ // report the timeout
+ if ( RetValue == -1 )
+ {
+ printf( "Timed out after verifying %d partitions (out of %d).\n", nOutputs, Vec_PtrSize(vParts) );
+ fflush( stdout );
+ }
+ // free intermediate results
+ Vec_PtrForEachEntry( Aig_Man_t *, vParts, pAig, i )
+ Aig_ManStop( pAig );
+ Vec_PtrFree( vParts );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_FraigCecTop( Aig_Man_t * pMan1, Aig_Man_t * pMan2, int nConfLimit, int nPartSize, int fSmart, int fVerbose )
+{
+ Aig_Man_t * pTemp;
+ //Abc_NtkDarCec( pNtk1, pNtk2, fPartition, fVerbose );
+ int RetValue, clkTotal = clock();
+
+ if ( Aig_ManPiNum(pMan1) != Aig_ManPiNum(pMan1) )
+ {
+ printf( "Abc_CommandAbc8Cec(): Miters have different number of PIs.\n" );
+ return 0;
+ }
+ if ( Aig_ManPoNum(pMan1) != Aig_ManPoNum(pMan1) )
+ {
+ printf( "Abc_CommandAbc8Cec(): Miters have different number of POs.\n" );
+ return 0;
+ }
+ assert( Aig_ManPiNum(pMan1) == Aig_ManPiNum(pMan1) );
+ assert( Aig_ManPoNum(pMan1) == Aig_ManPoNum(pMan1) );
+
+ // make sure that the first miter has more nodes
+ if ( Aig_ManNodeNum(pMan1) < Aig_ManNodeNum(pMan2) )
+ {
+ pTemp = pMan1;
+ pMan1 = pMan2;
+ pMan2 = pTemp;
+ }
+ assert( Aig_ManNodeNum(pMan1) >= Aig_ManNodeNum(pMan2) );
+
+ if ( nPartSize )
+ RetValue = Fra_FraigCecPartitioned( pMan1, pMan2, nConfLimit, nPartSize, fSmart, fVerbose );
+ else // no partitioning
+ RetValue = Fra_FraigCecPartitioned( pMan1, pMan2, nConfLimit, Aig_ManPoNum(pMan1), 0, fVerbose );
+
+ // report the miter
+ if ( RetValue == 1 )
+ {
+ printf( "Networks are equivalent. " );
+ABC_PRT( "Time", clock() - clkTotal );
+ }
+ else if ( RetValue == 0 )
+ {
+ printf( "Networks are NOT EQUIVALENT. " );
+ABC_PRT( "Time", clock() - clkTotal );
+ }
+ else
+ {
+ printf( "Networks are UNDECIDED. " );
+ABC_PRT( "Time", clock() - clkTotal );
+ }
+ fflush( stdout );
+ return RetValue;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fra/fraClass.c b/src/proof/fra/fraClass.c
new file mode 100644
index 00000000..67351f6d
--- /dev/null
+++ b/src/proof/fra/fraClass.c
@@ -0,0 +1,862 @@
+/**CFile****************************************************************
+
+ FileName [fraClass.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: fraClass.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+ The candidate equivalence classes are stored as a vector of pointers
+ to the array of pointers to the nodes in each class.
+ The first node of the class is its representative node.
+ The representative has the smallest topological order among the class nodes.
+ The nodes inside each class are ordered according to their topological order.
+ The classes are ordered according to the topological order of their representatives.
+ The array of pointers to the class nodes is terminated with a NULL pointer.
+ To enable dynamic addition of new classes (during class refinement),
+ each array has at least as many NULLs in the end, as there are nodes in the class.
+*/
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static inline Aig_Obj_t * Fra_ObjNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj ) { return ppNexts[pObj->Id]; }
+static inline void Fra_ObjSetNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { ppNexts[pObj->Id] = pNext; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Starts representation of equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fra_Cla_t * Fra_ClassesStart( Aig_Man_t * pAig )
+{
+ Fra_Cla_t * p;
+ p = ABC_ALLOC( Fra_Cla_t, 1 );
+ memset( p, 0, sizeof(Fra_Cla_t) );
+ p->pAig = pAig;
+ p->pMemRepr = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) );
+ memset( p->pMemRepr, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(pAig) );
+ p->vClasses = Vec_PtrAlloc( 100 );
+ p->vClasses1 = Vec_PtrAlloc( 100 );
+ p->vClassesTemp = Vec_PtrAlloc( 100 );
+ p->vClassOld = Vec_PtrAlloc( 100 );
+ p->vClassNew = Vec_PtrAlloc( 100 );
+ p->pFuncNodeHash = Fra_SmlNodeHash;
+ p->pFuncNodeIsConst = Fra_SmlNodeIsConst;
+ p->pFuncNodesAreEqual = Fra_SmlNodesAreEqual;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stop representation of equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClassesStop( Fra_Cla_t * p )
+{
+ ABC_FREE( p->pMemClasses );
+ ABC_FREE( p->pMemRepr );
+ if ( p->vClassesTemp ) Vec_PtrFree( p->vClassesTemp );
+ if ( p->vClassNew ) Vec_PtrFree( p->vClassNew );
+ if ( p->vClassOld ) Vec_PtrFree( p->vClassOld );
+ if ( p->vClasses1 ) Vec_PtrFree( p->vClasses1 );
+ if ( p->vClasses ) Vec_PtrFree( p->vClasses );
+ if ( p->vImps ) Vec_IntFree( p->vImps );
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts representation of equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClassesCopyReprs( Fra_Cla_t * p, Vec_Ptr_t * vFailed )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Aig_ManReprStart( p->pAig, Aig_ManObjNumMax(p->pAig) );
+ memmove( p->pAig->pReprs, p->pMemRepr, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p->pAig) );
+ if ( Vec_PtrSize(p->vClasses1) == 0 && Vec_PtrSize(p->vClasses) == 0 )
+ {
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ {
+ if ( p->pAig->pReprs[i] != NULL )
+ printf( "Classes are not cleared!\n" );
+ assert( p->pAig->pReprs[i] == NULL );
+ }
+ }
+ if ( vFailed )
+ Vec_PtrForEachEntry( Aig_Obj_t *, vFailed, pObj, i )
+ p->pAig->pReprs[pObj->Id] = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints simulation classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_ClassCount( Aig_Obj_t ** pClass )
+{
+ Aig_Obj_t * pTemp;
+ int i;
+ for ( i = 0; (pTemp = pClass[i]); i++ );
+ return i;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Count the number of literals.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_ClassesCountLits( Fra_Cla_t * p )
+{
+ Aig_Obj_t ** pClass;
+ int i, nNodes, nLits = 0;
+ nLits = Vec_PtrSize( p->vClasses1 );
+ Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, pClass, i )
+ {
+ nNodes = Fra_ClassCount( pClass );
+ assert( nNodes > 1 );
+ nLits += nNodes - 1;
+ }
+ return nLits;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Count the number of pairs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_ClassesCountPairs( Fra_Cla_t * p )
+{
+ Aig_Obj_t ** pClass;
+ int i, nNodes, nPairs = 0;
+ Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, pClass, i )
+ {
+ nNodes = Fra_ClassCount( pClass );
+ assert( nNodes > 1 );
+ nPairs += nNodes * (nNodes - 1) / 2;
+ }
+ return nPairs;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints simulation classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_PrintClass( Fra_Cla_t * p, Aig_Obj_t ** pClass )
+{
+ Aig_Obj_t * pTemp;
+ int i;
+ for ( i = 1; (pTemp = pClass[i]); i++ )
+ assert( Fra_ClassObjRepr(pTemp) == pClass[0] );
+ printf( "{ " );
+ for ( i = 0; (pTemp = pClass[i]); i++ )
+ printf( "%d(%d,%d) ", pTemp->Id, pTemp->Level, Aig_SupportSize(p->pAig,pTemp) );
+ printf( "}\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints simulation classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClassesPrint( Fra_Cla_t * p, int fVeryVerbose )
+{
+ Aig_Obj_t ** pClass;
+ Aig_Obj_t * pObj;
+ int i;
+
+ printf( "Const = %5d. Class = %5d. Lit = %5d. ",
+ Vec_PtrSize(p->vClasses1), Vec_PtrSize(p->vClasses), Fra_ClassesCountLits(p) );
+ if ( p->vImps && Vec_IntSize(p->vImps) > 0 )
+ printf( "Imp = %5d. ", Vec_IntSize(p->vImps) );
+ printf( "\n" );
+
+ if ( fVeryVerbose )
+ {
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vClasses1, pObj, i )
+ assert( Fra_ClassObjRepr(pObj) == Aig_ManConst1(p->pAig) );
+ printf( "Constants { " );
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vClasses1, pObj, i )
+ printf( "%d(%d,%d) ", pObj->Id, pObj->Level, Aig_SupportSize(p->pAig,pObj) );
+ printf( "}\n" );
+ Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, pClass, i )
+ {
+ printf( "%3d (%3d) : ", i, Fra_ClassCount(pClass) );
+ Fra_PrintClass( p, pClass );
+ }
+ printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates initial simulation classes.]
+
+ Description [Assumes that simulation info is assigned.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClassesPrepare( Fra_Cla_t * p, int fLatchCorr, int nMaxLevs )
+{
+ Aig_Obj_t ** ppTable, ** ppNexts;
+ Aig_Obj_t * pObj, * pTemp;
+ int i, k, nTableSize, nEntries, nNodes, iEntry;
+
+ // allocate the hash table hashing simulation info into nodes
+ nTableSize = Abc_PrimeCudd( Aig_ManObjNumMax(p->pAig) );
+ ppTable = ABC_FALLOC( Aig_Obj_t *, nTableSize );
+ ppNexts = ABC_FALLOC( Aig_Obj_t *, nTableSize );
+ memset( ppTable, 0, sizeof(Aig_Obj_t *) * nTableSize );
+
+ // add all the nodes to the hash table
+ Vec_PtrClear( p->vClasses1 );
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ {
+ if ( fLatchCorr )
+ {
+ if ( !Aig_ObjIsPi(pObj) )
+ continue;
+ }
+ else
+ {
+ if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) )
+ continue;
+ // skip the node with more that the given number of levels
+ if ( nMaxLevs && (int)pObj->Level > nMaxLevs )
+ continue;
+ }
+ // hash the node by its simulation info
+ iEntry = p->pFuncNodeHash( pObj, nTableSize );
+ // check if the node belongs to the class of constant 1
+ if ( p->pFuncNodeIsConst( pObj ) )
+ {
+ Vec_PtrPush( p->vClasses1, pObj );
+ Fra_ClassObjSetRepr( pObj, Aig_ManConst1(p->pAig) );
+ continue;
+ }
+ // add the node to the class
+ if ( ppTable[iEntry] == NULL )
+ {
+ ppTable[iEntry] = pObj;
+ Fra_ObjSetNext( ppNexts, pObj, pObj );
+ }
+ else
+ {
+ Fra_ObjSetNext( ppNexts, pObj, Fra_ObjNext(ppNexts,ppTable[iEntry]) );
+ Fra_ObjSetNext( ppNexts, ppTable[iEntry], pObj );
+ }
+ }
+
+ // count the total number of nodes in the non-trivial classes
+ // mark the representative nodes of each equivalence class
+ nEntries = 0;
+ for ( i = 0; i < nTableSize; i++ )
+ if ( ppTable[i] && ppTable[i] != Fra_ObjNext(ppNexts, ppTable[i]) )
+ {
+ for ( pTemp = Fra_ObjNext(ppNexts, ppTable[i]), k = 1;
+ pTemp != ppTable[i];
+ pTemp = Fra_ObjNext(ppNexts, pTemp), k++ );
+ assert( k > 1 );
+ nEntries += k;
+ // mark the node
+ assert( ppTable[i]->fMarkA == 0 );
+ ppTable[i]->fMarkA = 1;
+ }
+
+ // allocate room for classes
+ p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, 2*(nEntries + Vec_PtrSize(p->vClasses1)) );
+ p->pMemClassesFree = p->pMemClasses + 2*nEntries;
+
+ // copy the entries into storage in the topological order
+ Vec_PtrClear( p->vClasses );
+ nEntries = 0;
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ {
+ if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) )
+ continue;
+ // skip the nodes that are not representatives of non-trivial classes
+ if ( pObj->fMarkA == 0 )
+ continue;
+ pObj->fMarkA = 0;
+ // add the class of nodes
+ Vec_PtrPush( p->vClasses, p->pMemClasses + 2*nEntries );
+ // count the number of entries in this class
+ for ( pTemp = Fra_ObjNext(ppNexts, pObj), k = 1;
+ pTemp != pObj;
+ pTemp = Fra_ObjNext(ppNexts, pTemp), k++ );
+ nNodes = k;
+ assert( nNodes > 1 );
+ // add the nodes to the class in the topological order
+ p->pMemClasses[2*nEntries] = pObj;
+ for ( pTemp = Fra_ObjNext(ppNexts, pObj), k = 1;
+ pTemp != pObj;
+ pTemp = Fra_ObjNext(ppNexts, pTemp), k++ )
+ {
+ p->pMemClasses[2*nEntries+nNodes-k] = pTemp;
+ Fra_ClassObjSetRepr( pTemp, pObj );
+ }
+ // add as many empty entries
+ p->pMemClasses[2*nEntries + nNodes] = NULL;
+ // increment the number of entries
+ nEntries += k;
+ }
+ ABC_FREE( ppTable );
+ ABC_FREE( ppNexts );
+ // now it is time to refine the classes
+ Fra_ClassesRefine( p );
+// Fra_ClassesPrint( p, 0 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Refines one class using simulation info.]
+
+ Description [Returns the new class if refinement happened.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Obj_t ** Fra_RefineClassOne( Fra_Cla_t * p, Aig_Obj_t ** ppClass )
+{
+ Aig_Obj_t * pObj, ** ppThis;
+ int i;
+ assert( ppClass[0] != NULL && ppClass[1] != NULL );
+
+ // check if the class is going to be refined
+ for ( ppThis = ppClass + 1; (pObj = *ppThis); ppThis++ )
+ if ( !p->pFuncNodesAreEqual(ppClass[0], pObj) )
+ break;
+ if ( pObj == NULL )
+ return NULL;
+ // split the class
+ Vec_PtrClear( p->vClassOld );
+ Vec_PtrClear( p->vClassNew );
+ Vec_PtrPush( p->vClassOld, ppClass[0] );
+ for ( ppThis = ppClass + 1; (pObj = *ppThis); ppThis++ )
+ if ( p->pFuncNodesAreEqual(ppClass[0], pObj) )
+ Vec_PtrPush( p->vClassOld, pObj );
+ else
+ Vec_PtrPush( p->vClassNew, pObj );
+/*
+ printf( "Refining class (" );
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassOld, pObj, i )
+ printf( "%d,", pObj->Id );
+ printf( ") + (" );
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
+ printf( "%d,", pObj->Id );
+ printf( ")\n" );
+*/
+ // put the nodes back into the class memory
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassOld, pObj, i )
+ {
+ ppClass[i] = pObj;
+ ppClass[Vec_PtrSize(p->vClassOld)+i] = NULL;
+ Fra_ClassObjSetRepr( pObj, i? ppClass[0] : NULL );
+ }
+ ppClass += 2*Vec_PtrSize(p->vClassOld);
+ // put the new nodes into the class memory
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
+ {
+ ppClass[i] = pObj;
+ ppClass[Vec_PtrSize(p->vClassNew)+i] = NULL;
+ Fra_ClassObjSetRepr( pObj, i? ppClass[0] : NULL );
+ }
+ return ppClass;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Iteratively refines the classes after simulation.]
+
+ Description [Returns the number of refinements performed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_RefineClassLastIter( Fra_Cla_t * p, Vec_Ptr_t * vClasses )
+{
+ Aig_Obj_t ** pClass, ** pClass2;
+ int nRefis;
+ pClass = (Aig_Obj_t **)Vec_PtrEntryLast( vClasses );
+ for ( nRefis = 0; (pClass2 = Fra_RefineClassOne( p, pClass )); nRefis++ )
+ {
+ // if the original class is trivial, remove it
+ if ( pClass[1] == NULL )
+ Vec_PtrPop( vClasses );
+ // if the new class is trivial, stop
+ if ( pClass2[1] == NULL )
+ {
+ nRefis++;
+ break;
+ }
+ // othewise, add the class and continue
+ assert( pClass2[0] != NULL );
+ Vec_PtrPush( vClasses, pClass2 );
+ pClass = pClass2;
+ }
+ return nRefis;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Refines the classes after simulation.]
+
+ Description [Assumes that simulation info is assigned. Returns the
+ number of classes refined.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_ClassesRefine( Fra_Cla_t * p )
+{
+ Vec_Ptr_t * vTemp;
+ Aig_Obj_t ** pClass;
+ int i, nRefis;
+ // refine the classes
+ nRefis = 0;
+ Vec_PtrClear( p->vClassesTemp );
+ Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, pClass, i )
+ {
+ // add the class to the new array
+ assert( pClass[0] != NULL );
+ Vec_PtrPush( p->vClassesTemp, pClass );
+ // refine the class iteratively
+ nRefis += Fra_RefineClassLastIter( p, p->vClassesTemp );
+ }
+ // exchange the class representation
+ vTemp = p->vClassesTemp;
+ p->vClassesTemp = p->vClasses;
+ p->vClasses = vTemp;
+ return nRefis;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Refines constant 1 equivalence class.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_ClassesRefine1( Fra_Cla_t * p, int fRefineNewClass, int * pSkipped )
+{
+ Aig_Obj_t * pObj, ** ppClass;
+ int i, k, nRefis = 1;
+ // check if there is anything to refine
+ if ( Vec_PtrSize(p->vClasses1) == 0 )
+ return 0;
+ // make sure constant 1 class contains only non-constant nodes
+ assert( Vec_PtrEntry(p->vClasses1,0) != Aig_ManConst1(p->pAig) );
+ // collect all the nodes to be refined
+ k = 0;
+ Vec_PtrClear( p->vClassNew );
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vClasses1, pObj, i )
+ {
+ if ( p->pFuncNodeIsConst( pObj ) )
+ Vec_PtrWriteEntry( p->vClasses1, k++, pObj );
+ else
+ Vec_PtrPush( p->vClassNew, pObj );
+ }
+ Vec_PtrShrink( p->vClasses1, k );
+ if ( Vec_PtrSize(p->vClassNew) == 0 )
+ return 0;
+/*
+ printf( "Refined const-1 class: {" );
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
+ printf( " %d", pObj->Id );
+ printf( " }\n" );
+*/
+ if ( Vec_PtrSize(p->vClassNew) == 1 )
+ {
+ Fra_ClassObjSetRepr( (Aig_Obj_t *)Vec_PtrEntry(p->vClassNew,0), NULL );
+ return 1;
+ }
+ // create a new class composed of these nodes
+ ppClass = p->pMemClassesFree;
+ p->pMemClassesFree += 2 * Vec_PtrSize(p->vClassNew);
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
+ {
+ ppClass[i] = pObj;
+ ppClass[Vec_PtrSize(p->vClassNew)+i] = NULL;
+ Fra_ClassObjSetRepr( pObj, i? ppClass[0] : NULL );
+ }
+ assert( ppClass[0] != NULL );
+ Vec_PtrPush( p->vClasses, ppClass );
+ // iteratively refine this class
+ if ( fRefineNewClass )
+ nRefis += Fra_RefineClassLastIter( p, p->vClasses );
+ else if ( pSkipped )
+ (*pSkipped)++;
+ return nRefis;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts representation of equivalence classes with one class.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClassesTest( Fra_Cla_t * p, int Id1, int Id2 )
+{
+ Aig_Obj_t ** pClass;
+ p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, 4 );
+ pClass = p->pMemClasses;
+ assert( Id1 < Id2 );
+ pClass[0] = Aig_ManObj( p->pAig, Id1 );
+ pClass[1] = Aig_ManObj( p->pAig, Id2 );
+ pClass[2] = NULL;
+ pClass[3] = NULL;
+ Fra_ClassObjSetRepr( pClass[1], pClass[0] );
+ Vec_PtrPush( p->vClasses, pClass );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates latch correspondence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClassesLatchCorr( Fra_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i, nEntries = 0;
+ Vec_PtrClear( p->pCla->vClasses1 );
+ Aig_ManForEachLoSeq( p->pManAig, pObj, i )
+ {
+ Vec_PtrPush( p->pCla->vClasses1, pObj );
+ Fra_ClassObjSetRepr( pObj, Aig_ManConst1(p->pManAig) );
+ }
+ // allocate room for classes
+ p->pCla->pMemClasses = ABC_ALLOC( Aig_Obj_t *, 2*(nEntries + Vec_PtrSize(p->pCla->vClasses1)) );
+ p->pCla->pMemClassesFree = p->pCla->pMemClasses + 2*nEntries;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Postprocesses the classes by removing half of the less useful.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClassesPostprocess( Fra_Cla_t * p )
+{
+ int Ratio = 2;
+ Fra_Sml_t * pComb;
+ Aig_Obj_t * pObj, * pRepr, ** ppClass;
+ int * pWeights, WeightMax = 0, i, k, c;
+ // perform combinational simulation
+ pComb = Fra_SmlSimulateComb( p->pAig, 32 );
+ // compute the weight of each node in the classes
+ pWeights = ABC_ALLOC( int, Aig_ManObjNumMax(p->pAig) );
+ memset( pWeights, 0, sizeof(int) * Aig_ManObjNumMax(p->pAig) );
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ {
+ pRepr = Fra_ClassObjRepr( pObj );
+ if ( pRepr == NULL )
+ continue;
+ pWeights[i] = Fra_SmlNodeNotEquWeight( pComb, pRepr->Id, pObj->Id );
+ WeightMax = Abc_MaxInt( WeightMax, pWeights[i] );
+ }
+ Fra_SmlStop( pComb );
+ printf( "Before: Const = %6d. Class = %6d. ", Vec_PtrSize(p->vClasses1), Vec_PtrSize(p->vClasses) );
+ // remove nodes from classes whose weight is less than WeightMax/Ratio
+ k = 0;
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vClasses1, pObj, i )
+ {
+ if ( pWeights[pObj->Id] >= WeightMax/Ratio )
+ Vec_PtrWriteEntry( p->vClasses1, k++, pObj );
+ else
+ Fra_ClassObjSetRepr( pObj, NULL );
+ }
+ Vec_PtrShrink( p->vClasses1, k );
+ // in each class, compact the nodes
+ Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, ppClass, i )
+ {
+ k = 1;
+ for ( c = 1; ppClass[c]; c++ )
+ {
+ if ( pWeights[ppClass[c]->Id] >= WeightMax/Ratio )
+ ppClass[k++] = ppClass[c];
+ else
+ Fra_ClassObjSetRepr( ppClass[c], NULL );
+ }
+ ppClass[k] = NULL;
+ }
+ // remove classes with only repr
+ k = 0;
+ Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, ppClass, i )
+ if ( ppClass[1] != NULL )
+ Vec_PtrWriteEntry( p->vClasses, k++, ppClass );
+ Vec_PtrShrink( p->vClasses, k );
+ printf( "After: Const = %6d. Class = %6d. \n", Vec_PtrSize(p->vClasses1), Vec_PtrSize(p->vClasses) );
+ ABC_FREE( pWeights );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Postprocesses the classes by selecting representative lowest in top order.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClassesSelectRepr( Fra_Cla_t * p )
+{
+ Aig_Obj_t ** pClass, * pNodeMin;
+ int i, c, cMinSupp, nSuppSizeMin, nSuppSizeCur;
+ // reassign representatives in each class
+ Vec_PtrForEachEntry( Aig_Obj_t **, p->vClasses, pClass, i )
+ {
+ // collect support sizes and find the min-support node
+ cMinSupp = -1;
+ pNodeMin = NULL;
+ nSuppSizeMin = ABC_INFINITY;
+ for ( c = 0; pClass[c]; c++ )
+ {
+ nSuppSizeCur = Aig_SupportSize( p->pAig, pClass[c] );
+// nSuppSizeCur = 1;
+ if ( nSuppSizeMin > nSuppSizeCur ||
+ (nSuppSizeMin == nSuppSizeCur && pNodeMin->Level > pClass[c]->Level) )
+ {
+ nSuppSizeMin = nSuppSizeCur;
+ pNodeMin = pClass[c];
+ cMinSupp = c;
+ }
+ }
+ // skip the case when the repr did not change
+ if ( cMinSupp == 0 )
+ continue;
+ // make the new node the representative of the class
+ pClass[cMinSupp] = pClass[0];
+ pClass[0] = pNodeMin;
+ // set the representative
+ for ( c = 0; pClass[c]; c++ )
+ Fra_ClassObjSetRepr( pClass[c], c? pClass[0] : NULL );
+ }
+}
+
+
+
+static inline Aig_Obj_t * Fra_ObjEqu( Aig_Obj_t ** ppEquivs, Aig_Obj_t * pObj ) { return ppEquivs[pObj->Id]; }
+static inline void Fra_ObjSetEqu( Aig_Obj_t ** ppEquivs, Aig_Obj_t * pObj, Aig_Obj_t * pNode ) { ppEquivs[pObj->Id] = pNode; }
+
+static inline Aig_Obj_t * Fra_ObjChild0Equ( Aig_Obj_t ** ppEquivs, Aig_Obj_t * pObj ) { return Aig_NotCond(Fra_ObjEqu(ppEquivs,Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj)); }
+static inline Aig_Obj_t * Fra_ObjChild1Equ( Aig_Obj_t ** ppEquivs, Aig_Obj_t * pObj ) { return Aig_NotCond(Fra_ObjEqu(ppEquivs,Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj)); }
+
+/**Function*************************************************************
+
+ Synopsis [Add the node and its constraints to the new AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fra_ClassesDeriveNode( Aig_Man_t * pManFraig, Aig_Obj_t * pObj, Aig_Obj_t ** ppEquivs )
+{
+ Aig_Obj_t * pObjNew, * pObjRepr, * pObjReprNew, * pMiter;//, * pObjNew2;
+ // skip nodes without representative
+ if ( (pObjRepr = Fra_ClassObjRepr(pObj)) == NULL )
+ return;
+ assert( pObjRepr->Id < pObj->Id );
+ // get the new node
+ pObjNew = Fra_ObjEqu( ppEquivs, pObj );
+ // get the new node of the representative
+ pObjReprNew = Fra_ObjEqu( ppEquivs, pObjRepr );
+ // if this is the same node, no need to add constraints
+ if ( Aig_Regular(pObjNew) == Aig_Regular(pObjReprNew) )
+ return;
+ // these are different nodes - perform speculative reduction
+// pObjNew2 = Aig_NotCond( pObjReprNew, pObj->fPhase ^ pObjRepr->fPhase );
+ // set the new node
+// Fra_ObjSetEqu( ppEquivs, pObj, pObjNew2 );
+ // add the constraint
+ pMiter = Aig_Exor( pManFraig, Aig_Regular(pObjNew), Aig_Regular(pObjReprNew) );
+ pMiter = Aig_NotCond( pMiter, Aig_Regular(pMiter)->fPhase ^ Aig_IsComplement(pMiter) );
+ pMiter = Aig_Not( pMiter );
+ Aig_ObjCreatePo( pManFraig, pMiter );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives AIG for the partitioned problem.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Fra_ClassesDeriveAig( Fra_Cla_t * p, int nFramesK )
+{
+ Aig_Man_t * pManFraig;
+ Aig_Obj_t * pObj, * pObjNew;
+ Aig_Obj_t ** pLatches, ** ppEquivs;
+ int i, k, f, nFramesAll = nFramesK + 1;
+ assert( Aig_ManRegNum(p->pAig) > 0 );
+ assert( Aig_ManRegNum(p->pAig) < Aig_ManPiNum(p->pAig) );
+ assert( nFramesK > 0 );
+ // start the fraig package
+ pManFraig = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * nFramesAll );
+ pManFraig->pName = Abc_UtilStrsav( p->pAig->pName );
+ pManFraig->pSpec = Abc_UtilStrsav( p->pAig->pSpec );
+ // allocate place for the node mapping
+ ppEquivs = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) );
+ Fra_ObjSetEqu( ppEquivs, Aig_ManConst1(p->pAig), Aig_ManConst1(pManFraig) );
+ // create latches for the first frame
+ Aig_ManForEachLoSeq( p->pAig, pObj, i )
+ Fra_ObjSetEqu( ppEquivs, pObj, Aig_ObjCreatePi(pManFraig) );
+ // add timeframes
+ pLatches = ABC_ALLOC( Aig_Obj_t *, Aig_ManRegNum(p->pAig) );
+ for ( f = 0; f < nFramesAll; f++ )
+ {
+ // create PIs for this frame
+ Aig_ManForEachPiSeq( p->pAig, pObj, i )
+ Fra_ObjSetEqu( ppEquivs, pObj, Aig_ObjCreatePi(pManFraig) );
+ // set the constraints on the latch outputs
+ Aig_ManForEachLoSeq( p->pAig, pObj, i )
+ Fra_ClassesDeriveNode( pManFraig, pObj, ppEquivs );
+ // add internal nodes of this frame
+ Aig_ManForEachNode( p->pAig, pObj, i )
+ {
+ pObjNew = Aig_And( pManFraig, Fra_ObjChild0Equ(ppEquivs, pObj), Fra_ObjChild1Equ(ppEquivs, pObj) );
+ Fra_ObjSetEqu( ppEquivs, pObj, pObjNew );
+ Fra_ClassesDeriveNode( pManFraig, pObj, ppEquivs );
+ }
+ if ( f == nFramesAll - 1 )
+ break;
+ if ( f == nFramesAll - 2 )
+ pManFraig->nAsserts = Aig_ManPoNum(pManFraig);
+ // save the latch input values
+ k = 0;
+ Aig_ManForEachLiSeq( p->pAig, pObj, i )
+ pLatches[k++] = Fra_ObjChild0Equ( ppEquivs, pObj );
+ // insert them to the latch output values
+ k = 0;
+ Aig_ManForEachLoSeq( p->pAig, pObj, i )
+ Fra_ObjSetEqu( ppEquivs, pObj, pLatches[k++] );
+ }
+ ABC_FREE( pLatches );
+ ABC_FREE( ppEquivs );
+ // mark the asserts
+ assert( Aig_ManPoNum(pManFraig) % nFramesAll == 0 );
+printf( "Assert miters = %6d. Output miters = %6d.\n",
+ pManFraig->nAsserts, Aig_ManPoNum(pManFraig) - pManFraig->nAsserts );
+ // remove dangling nodes
+ Aig_ManCleanup( pManFraig );
+ return pManFraig;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fra/fraClau.c b/src/proof/fra/fraClau.c
new file mode 100644
index 00000000..fb87550d
--- /dev/null
+++ b/src/proof/fra/fraClau.c
@@ -0,0 +1,763 @@
+/**CFile****************************************************************
+
+ FileName [fraClau.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [New FRAIG package.]
+
+ Synopsis [Induction with clause strengthening.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 30, 2007.]
+
+ Revision [$Id: fraClau.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+#include "src/sat/cnf/cnf.h"
+#include "src/sat/bsat/satSolver.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+ This code is inspired by the paper: Aaron Bradley and Zohar Manna,
+ "Checking safety by inductive generalization of counterexamples to
+ induction", FMCAD '07.
+*/
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Cla_Man_t_ Cla_Man_t;
+struct Cla_Man_t_
+{
+ // SAT solvers
+ sat_solver * pSatMain;
+ sat_solver * pSatTest;
+ sat_solver * pSatBmc;
+ // CNF for the test solver
+// Cnf_Dat_t * pCnfTest;
+ // SAT variables
+ Vec_Int_t * vSatVarsMainCs;
+ Vec_Int_t * vSatVarsTestCs;
+ Vec_Int_t * vSatVarsTestNs;
+ Vec_Int_t * vSatVarsBmcNs;
+ // helper variables
+ int nSatVarsTestBeg;
+ int nSatVarsTestCur;
+ // counter-examples
+ Vec_Int_t * vCexMain0;
+ Vec_Int_t * vCexMain;
+ Vec_Int_t * vCexTest;
+ Vec_Int_t * vCexBase;
+ Vec_Int_t * vCexAssm;
+ Vec_Int_t * vCexBmc;
+ // mapping of CS into NS var numbers
+ int * pMapCsMainToCsTest;
+ int * pMapCsTestToCsMain;
+ int * pMapCsTestToNsTest;
+ int * pMapCsTestToNsBmc;
+};
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Saves variables corresponding to latch outputs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Fra_ClauSaveLatchVars( Aig_Man_t * pMan, Cnf_Dat_t * pCnf, int fCsVars )
+{
+ Vec_Int_t * vVars;
+ Aig_Obj_t * pObjLo, * pObjLi;
+ int i;
+ vVars = Vec_IntAlloc( Aig_ManRegNum(pMan) );
+ Aig_ManForEachLiLoSeq( pMan, pObjLi, pObjLo, i )
+ Vec_IntPush( vVars, pCnf->pVarNums[fCsVars? pObjLo->Id : pObjLi->Id] );
+ return vVars;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Saves variables corresponding to latch outputs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Fra_ClauSaveOutputVars( Aig_Man_t * pMan, Cnf_Dat_t * pCnf )
+{
+ Vec_Int_t * vVars;
+ Aig_Obj_t * pObj;
+ int i;
+ vVars = Vec_IntAlloc( Aig_ManPoNum(pMan) );
+ Aig_ManForEachPo( pMan, pObj, i )
+ Vec_IntPush( vVars, pCnf->pVarNums[pObj->Id] );
+ return vVars;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Saves variables corresponding to latch outputs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Fra_ClauSaveInputVars( Aig_Man_t * pMan, Cnf_Dat_t * pCnf, int nStarting )
+{
+ Vec_Int_t * vVars;
+ Aig_Obj_t * pObj;
+ int i;
+ vVars = Vec_IntAlloc( Aig_ManPiNum(pMan) - nStarting );
+ Aig_ManForEachPi( pMan, pObj, i )
+ {
+ if ( i < nStarting )
+ continue;
+ Vec_IntPush( vVars, pCnf->pVarNums[pObj->Id] );
+ }
+ return vVars;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Saves variables corresponding to latch outputs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int * Fra_ClauCreateMapping( Vec_Int_t * vSatVarsFrom, Vec_Int_t * vSatVarsTo, int nVarsMax )
+{
+ int * pMapping, Var, i;
+ assert( Vec_IntSize(vSatVarsFrom) == Vec_IntSize(vSatVarsTo) );
+ pMapping = ABC_ALLOC( int, nVarsMax );
+ for ( i = 0; i < nVarsMax; i++ )
+ pMapping[i] = -1;
+ Vec_IntForEachEntry( vSatVarsFrom, Var, i )
+ pMapping[Var] = Vec_IntEntry(vSatVarsTo,i);
+ return pMapping;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Deletes the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClauStop( Cla_Man_t * p )
+{
+ ABC_FREE( p->pMapCsMainToCsTest );
+ ABC_FREE( p->pMapCsTestToCsMain );
+ ABC_FREE( p->pMapCsTestToNsTest );
+ ABC_FREE( p->pMapCsTestToNsBmc );
+ Vec_IntFree( p->vSatVarsMainCs );
+ Vec_IntFree( p->vSatVarsTestCs );
+ Vec_IntFree( p->vSatVarsTestNs );
+ Vec_IntFree( p->vSatVarsBmcNs );
+ Vec_IntFree( p->vCexMain0 );
+ Vec_IntFree( p->vCexMain );
+ Vec_IntFree( p->vCexTest );
+ Vec_IntFree( p->vCexBase );
+ Vec_IntFree( p->vCexAssm );
+ Vec_IntFree( p->vCexBmc );
+ if ( p->pSatMain ) sat_solver_delete( p->pSatMain );
+ if ( p->pSatTest ) sat_solver_delete( p->pSatTest );
+ if ( p->pSatBmc ) sat_solver_delete( p->pSatBmc );
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Takes the AIG with the single output to be checked.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cla_Man_t * Fra_ClauStart( Aig_Man_t * pMan )
+{
+ Cla_Man_t * p;
+ Cnf_Dat_t * pCnfMain;
+ Cnf_Dat_t * pCnfTest;
+ Cnf_Dat_t * pCnfBmc;
+ Aig_Man_t * pFramesMain;
+ Aig_Man_t * pFramesTest;
+ Aig_Man_t * pFramesBmc;
+ assert( Aig_ManPoNum(pMan) - Aig_ManRegNum(pMan) == 1 );
+
+ // start the manager
+ p = ABC_ALLOC( Cla_Man_t, 1 );
+ memset( p, 0, sizeof(Cla_Man_t) );
+ p->vCexMain0 = Vec_IntAlloc( Aig_ManRegNum(pMan) );
+ p->vCexMain = Vec_IntAlloc( Aig_ManRegNum(pMan) );
+ p->vCexTest = Vec_IntAlloc( Aig_ManRegNum(pMan) );
+ p->vCexBase = Vec_IntAlloc( Aig_ManRegNum(pMan) );
+ p->vCexAssm = Vec_IntAlloc( Aig_ManRegNum(pMan) );
+ p->vCexBmc = Vec_IntAlloc( Aig_ManRegNum(pMan) );
+
+ // derive two timeframes to be checked
+ pFramesMain = Aig_ManFrames( pMan, 2, 0, 1, 0, 0, NULL ); // nFrames, fInit, fOuts, fRegs
+//Aig_ManShow( pFramesMain, 0, NULL );
+ assert( Aig_ManPoNum(pFramesMain) == 2 );
+ Aig_ObjChild0Flip( Aig_ManPo(pFramesMain, 0) ); // complement the first output
+ pCnfMain = Cnf_DeriveSimple( pFramesMain, 0 );
+//Cnf_DataWriteIntoFile( pCnfMain, "temp.cnf", 1 );
+ p->pSatMain = (sat_solver *)Cnf_DataWriteIntoSolver( pCnfMain, 1, 0 );
+/*
+ {
+ int i;
+ Aig_Obj_t * pObj;
+ Aig_ManForEachObj( pFramesMain, pObj, i )
+ printf( "%d -> %d \n", pObj->Id, pCnfMain->pVarNums[pObj->Id] );
+ printf( "\n" );
+ }
+*/
+
+ // derive one timeframe to be checked
+ pFramesTest = Aig_ManFrames( pMan, 1, 0, 0, 1, 0, NULL );
+ assert( Aig_ManPoNum(pFramesTest) == Aig_ManRegNum(pMan) );
+ pCnfTest = Cnf_DeriveSimple( pFramesTest, Aig_ManRegNum(pMan) );
+ p->pSatTest = (sat_solver *)Cnf_DataWriteIntoSolver( pCnfTest, 1, 0 );
+ p->nSatVarsTestBeg = p->nSatVarsTestCur = sat_solver_nvars( p->pSatTest );
+
+ // derive one timeframe to be checked for BMC
+ pFramesBmc = Aig_ManFrames( pMan, 1, 1, 0, 1, 0, NULL );
+//Aig_ManShow( pFramesBmc, 0, NULL );
+ assert( Aig_ManPoNum(pFramesBmc) == Aig_ManRegNum(pMan) );
+ pCnfBmc = Cnf_DeriveSimple( pFramesBmc, Aig_ManRegNum(pMan) );
+ p->pSatBmc = (sat_solver *)Cnf_DataWriteIntoSolver( pCnfBmc, 1, 0 );
+
+ // create variable sets
+ p->vSatVarsMainCs = Fra_ClauSaveInputVars( pFramesMain, pCnfMain, 2 * (Aig_ManPiNum(pMan)-Aig_ManRegNum(pMan)) );
+ p->vSatVarsTestCs = Fra_ClauSaveLatchVars( pFramesTest, pCnfTest, 1 );
+ p->vSatVarsTestNs = Fra_ClauSaveLatchVars( pFramesTest, pCnfTest, 0 );
+ p->vSatVarsBmcNs = Fra_ClauSaveOutputVars( pFramesBmc, pCnfBmc );
+ assert( Vec_IntSize(p->vSatVarsTestCs) == Vec_IntSize(p->vSatVarsMainCs) );
+ assert( Vec_IntSize(p->vSatVarsTestCs) == Vec_IntSize(p->vSatVarsBmcNs) );
+
+ // create mapping of CS into NS vars
+ p->pMapCsMainToCsTest = Fra_ClauCreateMapping( p->vSatVarsMainCs, p->vSatVarsTestCs, Aig_ManObjNumMax(pFramesMain) );
+ p->pMapCsTestToCsMain = Fra_ClauCreateMapping( p->vSatVarsTestCs, p->vSatVarsMainCs, Aig_ManObjNumMax(pFramesTest) );
+ p->pMapCsTestToNsTest = Fra_ClauCreateMapping( p->vSatVarsTestCs, p->vSatVarsTestNs, Aig_ManObjNumMax(pFramesTest) );
+ p->pMapCsTestToNsBmc = Fra_ClauCreateMapping( p->vSatVarsTestCs, p->vSatVarsBmcNs, Aig_ManObjNumMax(pFramesTest) );
+
+ // cleanup
+ Cnf_DataFree( pCnfMain );
+ Cnf_DataFree( pCnfTest );
+ Cnf_DataFree( pCnfBmc );
+ Aig_ManStop( pFramesMain );
+ Aig_ManStop( pFramesTest );
+ Aig_ManStop( pFramesBmc );
+ if ( p->pSatMain == NULL || p->pSatTest == NULL || p->pSatBmc == NULL )
+ {
+ Fra_ClauStop( p );
+ return NULL;
+ }
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Splits off second half and returns it as a new vector.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static Vec_Int_t * Vec_IntSplitHalf( Vec_Int_t * vVec )
+{
+ Vec_Int_t * vPart;
+ int Entry, i;
+ assert( Vec_IntSize(vVec) > 1 );
+ vPart = Vec_IntAlloc( Vec_IntSize(vVec) / 2 + 1 );
+ Vec_IntForEachEntryStart( vVec, Entry, i, Vec_IntSize(vVec) / 2 )
+ Vec_IntPush( vPart, Entry );
+ Vec_IntShrink( vVec, Vec_IntSize(vVec) / 2 );
+ return vPart;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Appends the contents of the second vector.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Vec_IntAppend( Vec_Int_t * vVec1, Vec_Int_t * vVec2 )
+{
+ int Entry, i;
+ Vec_IntForEachEntry( vVec2, Entry, i )
+ Vec_IntPush( vVec1, Entry );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Complements all literals in the clause.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Vec_IntComplement( Vec_Int_t * vVec )
+{
+ int i;
+ for ( i = 0; i < Vec_IntSize(vVec); i++ )
+ vVec->pArray[i] = lit_neg( vVec->pArray[i] );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks if the property holds. Returns counter-example if not.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_ClauCheckProperty( Cla_Man_t * p, Vec_Int_t * vCex )
+{
+ int nBTLimit = 0;
+ int RetValue, iVar, i;
+ sat_solver_act_var_clear( p->pSatMain );
+ RetValue = sat_solver_solve( p->pSatMain, NULL, NULL, (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+ Vec_IntClear( vCex );
+ if ( RetValue == l_False )
+ return 1;
+ assert( RetValue == l_True );
+ Vec_IntForEachEntry( p->vSatVarsMainCs, iVar, i )
+ Vec_IntPush( vCex, sat_solver_var_literal(p->pSatMain, iVar) );
+/*
+ {
+ int i;
+ for (i = 0; i < p->pSatMain->size; i++)
+ printf( "%d=%d ", i, p->pSatMain->model.ptr[i] == l_True );
+ printf( "\n" );
+ }
+*/
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks if the clause holds using BMC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_ClauCheckBmc( Cla_Man_t * p, Vec_Int_t * vClause )
+{
+ int nBTLimit = 0;
+ int RetValue;
+ RetValue = sat_solver_solve( p->pSatBmc, Vec_IntArray(vClause), Vec_IntArray(vClause) + Vec_IntSize(vClause),
+ (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+ if ( RetValue == l_False )
+ return 1;
+ assert( RetValue == l_True );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Lifts the clause to depend on NS variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClauRemapClause( int * pMap, Vec_Int_t * vClause, Vec_Int_t * vRemapped, int fInv )
+{
+ int iLit, i;
+ Vec_IntClear( vRemapped );
+ Vec_IntForEachEntry( vClause, iLit, i )
+ {
+ assert( pMap[lit_var(iLit)] >= 0 );
+ iLit = toLitCond( pMap[lit_var(iLit)], lit_sign(iLit) ^ fInv );
+ Vec_IntPush( vRemapped, iLit );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks if the clause holds. Returns counter example if not.]
+
+ Description [Uses test SAT solver.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_ClauCheckClause( Cla_Man_t * p, Vec_Int_t * vClause, Vec_Int_t * vCex )
+{
+ int nBTLimit = 0;
+ int RetValue, iVar, i;
+ // complement literals
+ Vec_IntPush( vClause, toLit( p->nSatVarsTestCur++ ) ); // helper positive
+ Vec_IntComplement( vClause ); // helper negative (the clause is C v h')
+ // add the clause
+ RetValue = sat_solver_addclause( p->pSatTest, Vec_IntArray(vClause), Vec_IntArray(vClause) + Vec_IntSize(vClause) );
+ assert( RetValue == 1 );
+ // complement all literals
+ Vec_IntPop( vClause ); // helper removed
+ Vec_IntComplement( vClause );
+ // create the assumption in terms of NS variables
+ Fra_ClauRemapClause( p->pMapCsTestToNsTest, vClause, p->vCexAssm, 0 );
+ // add helper literals
+ for ( i = p->nSatVarsTestBeg; i < p->nSatVarsTestCur - 1; i++ )
+ Vec_IntPush( p->vCexAssm, toLitCond(i,1) ); // other helpers negative
+ Vec_IntPush( p->vCexAssm, toLitCond(i,0) ); // positive helper
+ // try to solve
+ RetValue = sat_solver_solve( p->pSatTest, Vec_IntArray(p->vCexAssm), Vec_IntArray(p->vCexAssm) + Vec_IntSize(p->vCexAssm),
+ (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+ if ( vCex )
+ Vec_IntClear( vCex );
+ if ( RetValue == l_False )
+ return 1;
+ assert( RetValue == l_True );
+ if ( vCex )
+ {
+ Vec_IntForEachEntry( p->vSatVarsTestCs, iVar, i )
+ Vec_IntPush( vCex, sat_solver_var_literal(p->pSatTest, iVar) );
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reduces the counter-example by removing complemented literals.]
+
+ Description [Removes literals from vMain that differ from those in the
+ counter-example (vNew). Relies on the fact that the PI variables are
+ assigned in the increasing order.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClauReduceClause( Vec_Int_t * vMain, Vec_Int_t * vNew )
+{
+ int LitM, LitN, VarM, VarN, i, j, k;
+ assert( Vec_IntSize(vMain) <= Vec_IntSize(vNew) );
+ for ( i = j = k = 0; i < Vec_IntSize(vMain) && j < Vec_IntSize(vNew); )
+ {
+ LitM = Vec_IntEntry( vMain, i );
+ LitN = Vec_IntEntry( vNew, j );
+ VarM = lit_var( LitM );
+ VarN = lit_var( LitN );
+ if ( VarM < VarN )
+ {
+ assert( 0 );
+ }
+ else if ( VarM > VarN )
+ {
+ j++;
+ }
+ else // if ( VarM == VarN )
+ {
+ i++;
+ j++;
+ if ( LitM == LitN )
+ Vec_IntWriteEntry( vMain, k++, LitM );
+ }
+ }
+ assert( i == Vec_IntSize(vMain) );
+ Vec_IntShrink( vMain, k );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the minimal invariant that holds.]
+
+ Description [On entrace, vBasis does not hold, vBasis+vExtra holds but
+ is not minimal. On exit, vBasis is unchanged, vBasis+vExtra is minimal.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClauMinimizeClause_rec( Cla_Man_t * p, Vec_Int_t * vBasis, Vec_Int_t * vExtra )
+{
+ Vec_Int_t * vExtra2;
+ int nSizeOld;
+ if ( Vec_IntSize(vExtra) == 1 )
+ return;
+ nSizeOld = Vec_IntSize( vBasis );
+ vExtra2 = Vec_IntSplitHalf( vExtra );
+
+ // try the first half
+ Vec_IntAppend( vBasis, vExtra );
+ if ( Fra_ClauCheckClause( p, vBasis, NULL ) )
+ {
+ Vec_IntShrink( vBasis, nSizeOld );
+ Fra_ClauMinimizeClause_rec( p, vBasis, vExtra );
+ return;
+ }
+ Vec_IntShrink( vBasis, nSizeOld );
+
+ // try the second half
+ Vec_IntAppend( vBasis, vExtra2 );
+ if ( Fra_ClauCheckClause( p, vBasis, NULL ) )
+ {
+ Vec_IntShrink( vBasis, nSizeOld );
+ Fra_ClauMinimizeClause_rec( p, vBasis, vExtra2 );
+ return;
+ }
+// Vec_IntShrink( vBasis, nSizeOld );
+
+ // find the smallest with the second half added
+ Fra_ClauMinimizeClause_rec( p, vBasis, vExtra );
+ Vec_IntShrink( vBasis, nSizeOld );
+ Vec_IntAppend( vBasis, vExtra );
+ // find the smallest with the second half added
+ Fra_ClauMinimizeClause_rec( p, vBasis, vExtra2 );
+ Vec_IntShrink( vBasis, nSizeOld );
+ Vec_IntAppend( vExtra, vExtra2 );
+ Vec_IntFree( vExtra2 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Minimizes the clauses using a simple method.]
+
+ Description [The input and output clause are in vExtra.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClauMinimizeClause( Cla_Man_t * p, Vec_Int_t * vBasis, Vec_Int_t * vExtra )
+{
+ int iLit, iLit2, i, k;
+ Vec_IntForEachEntryReverse( vExtra, iLit, i )
+ {
+ // copy literals without the given one
+ Vec_IntClear( vBasis );
+ Vec_IntForEachEntry( vExtra, iLit2, k )
+ if ( k != i )
+ Vec_IntPush( vBasis, iLit2 );
+ // try whether it is inductive
+ if ( !Fra_ClauCheckClause( p, vBasis, NULL ) )
+ continue;
+ // the clause is inductive
+ // remove the literal
+ for ( k = i; k < Vec_IntSize(vExtra)-1; k++ )
+ Vec_IntWriteEntry( vExtra, k, Vec_IntEntry(vExtra,k+1) );
+ Vec_IntShrink( vExtra, Vec_IntSize(vExtra)-1 );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the clause.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClauPrintClause( Vec_Int_t * vSatCsVars, Vec_Int_t * vCex )
+{
+ int LitM, VarM, VarN, i, j, k;
+ assert( Vec_IntSize(vCex) <= Vec_IntSize(vSatCsVars) );
+ for ( i = j = k = 0; i < Vec_IntSize(vCex) && j < Vec_IntSize(vSatCsVars); )
+ {
+ LitM = Vec_IntEntry( vCex, i );
+ VarM = lit_var( LitM );
+ VarN = Vec_IntEntry( vSatCsVars, j );
+ if ( VarM < VarN )
+ {
+ assert( 0 );
+ }
+ else if ( VarM > VarN )
+ {
+ j++;
+ printf( "-" );
+ }
+ else // if ( VarM == VarN )
+ {
+ i++;
+ j++;
+ printf( "%d", !lit_sign(LitM) );
+ }
+ }
+ assert( i == Vec_IntSize(vCex) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Takes the AIG with the single output to be checked.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_Clau( Aig_Man_t * pMan, int nIters, int fVerbose, int fVeryVerbose )
+{
+ Cla_Man_t * p;
+ int Iter, RetValue, fFailed, i;
+ assert( Aig_ManPoNum(pMan) - Aig_ManRegNum(pMan) == 1 );
+ // create the manager
+ p = Fra_ClauStart( pMan );
+ if ( p == NULL )
+ {
+ printf( "The property is trivially inductive.\n" );
+ return 1;
+ }
+ // generate counter-examples and expand them
+ for ( Iter = 0; !Fra_ClauCheckProperty( p, p->vCexMain0 ) && Iter < nIters; Iter++ )
+ {
+ if ( fVerbose )
+ printf( "%4d : ", Iter );
+ // remap clause into the test manager
+ Fra_ClauRemapClause( p->pMapCsMainToCsTest, p->vCexMain0, p->vCexMain, 0 );
+ if ( fVerbose && fVeryVerbose )
+ Fra_ClauPrintClause( p->vSatVarsTestCs, p->vCexMain );
+ // the main counter-example is in p->vCexMain
+ // intermediate counter-examples are in p->vCexTest
+ // generate the reduced counter-example to the inductive property
+ fFailed = 0;
+ for ( i = 0; !Fra_ClauCheckClause( p, p->vCexMain, p->vCexTest ); i++ )
+ {
+ Fra_ClauReduceClause( p->vCexMain, p->vCexTest );
+ Fra_ClauRemapClause( p->pMapCsTestToNsBmc, p->vCexMain, p->vCexBmc, 0 );
+
+// if ( !Fra_ClauCheckBmc(p, p->vCexBmc) )
+ if ( Vec_IntSize(p->vCexMain) < 1 )
+ {
+ Vec_IntComplement( p->vCexMain0 );
+ RetValue = sat_solver_addclause( p->pSatMain, Vec_IntArray(p->vCexMain0), Vec_IntArray(p->vCexMain0) + Vec_IntSize(p->vCexMain0) );
+ if ( RetValue == 0 )
+ {
+ printf( "\nProperty is proved after %d iterations.\n", Iter+1 );
+ return 0;
+ }
+ fFailed = 1;
+ break;
+ }
+ }
+ if ( fFailed )
+ {
+ if ( fVerbose )
+ printf( " Reducing failed after %d iterations (BMC failed).\n", i );
+ continue;
+ }
+ if ( Vec_IntSize(p->vCexMain) == 0 )
+ {
+ if ( fVerbose )
+ printf( " Reducing failed after %d iterations (nothing left).\n", i );
+ continue;
+ }
+ if ( fVerbose )
+ printf( " " );
+ if ( fVerbose && fVeryVerbose )
+ Fra_ClauPrintClause( p->vSatVarsTestCs, p->vCexMain );
+ if ( fVerbose )
+ printf( " LitsInd = %3d. ", Vec_IntSize(p->vCexMain) );
+ // minimize the inductive property
+ Vec_IntClear( p->vCexBase );
+ if ( Vec_IntSize(p->vCexMain) > 1 )
+// Fra_ClauMinimizeClause_rec( p, p->vCexBase, p->vCexMain );
+ Fra_ClauMinimizeClause( p, p->vCexBase, p->vCexMain );
+ assert( Vec_IntSize(p->vCexMain) > 0 );
+ if ( fVerbose && fVeryVerbose )
+ Fra_ClauPrintClause( p->vSatVarsTestCs, p->vCexMain );
+ if ( fVerbose )
+ printf( " LitsRed = %3d. ", Vec_IntSize(p->vCexMain) );
+ if ( fVerbose )
+ printf( "\n" );
+ // add the clause to the solver
+ Fra_ClauRemapClause( p->pMapCsTestToCsMain, p->vCexMain, p->vCexAssm, 1 );
+ RetValue = sat_solver_addclause( p->pSatMain, Vec_IntArray(p->vCexAssm), Vec_IntArray(p->vCexAssm) + Vec_IntSize(p->vCexAssm) );
+ if ( RetValue == 0 )
+ {
+ Iter++;
+ break;
+ }
+ if ( p->pSatMain->qtail != p->pSatMain->qhead )
+ {
+ RetValue = sat_solver_simplify(p->pSatMain);
+ assert( RetValue != 0 );
+ assert( p->pSatMain->qtail == p->pSatMain->qhead );
+ }
+ }
+
+ // report the results
+ if ( Iter == nIters )
+ {
+ printf( "Property is not proved after %d iterations.\n", nIters );
+ return 0;
+ }
+ printf( "Property is proved after %d iterations.\n", Iter );
+ Fra_ClauStop( p );
+ return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fra/fraClaus.c b/src/proof/fra/fraClaus.c
new file mode 100644
index 00000000..e71219b5
--- /dev/null
+++ b/src/proof/fra/fraClaus.c
@@ -0,0 +1,1875 @@
+/**CFile****************************************************************
+
+ FileName [fraClaus.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [New FRAIG package.]
+
+ Synopsis [Induction with clause strengthening.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 30, 2007.]
+
+ Revision [$Id: fraClau.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+#include "src/sat/cnf/cnf.h"
+#include "src/sat/bsat/satSolver.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Clu_Man_t_ Clu_Man_t;
+struct Clu_Man_t_
+{
+ // parameters
+ int nFrames; // the K of the K-step induction
+ int nPref; // the number of timeframes to skip
+ int nClausesMax; // the max number of 4-clauses to consider
+ int nLutSize; // the max cut size
+ int nLevels; // the number of levels for cut computation
+ int nCutsMax; // the maximum number of cuts to compute at a node
+ int nBatches; // the number of clause batches to use
+ int fStepUp; // increase cut size for each batch
+ int fTarget; // tries to prove the property
+ int fVerbose;
+ int fVeryVerbose;
+ // internal parameters
+ int nSimWords; // the number of simulation words
+ int nSimWordsPref; // the number of simulation words in the prefix
+ int nSimFrames; // the number of frames to simulate
+ int nBTLimit; // the largest number of backtracks (0 = infinite)
+ // the network
+ Aig_Man_t * pAig;
+ // SAT solvers
+ sat_solver * pSatMain;
+ sat_solver * pSatBmc;
+ // CNF for the test solver
+ Cnf_Dat_t * pCnf;
+ int fFail;
+ int fFiltering;
+ int fNothingNew;
+ // clauses
+ Vec_Int_t * vLits;
+ Vec_Int_t * vClauses;
+ Vec_Int_t * vCosts;
+ int nClauses;
+ int nCuts;
+ int nOneHots;
+ int nOneHotsProven;
+ // clauses proven
+ Vec_Int_t * vLitsProven;
+ Vec_Int_t * vClausesProven;
+ // counter-examples
+ Vec_Ptr_t * vCexes;
+ int nCexes;
+ int nCexesAlloc;
+};
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Runs the SAT solver on the problem.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_ClausRunBmc( Clu_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ int Lits[2], nLitsTot, RetValue, i;
+ // set the output literals
+ nLitsTot = 2 * p->pCnf->nVars;
+ pObj = Aig_ManPo(p->pAig, 0);
+ for ( i = 0; i < p->nPref + p->nFrames; i++ )
+ {
+ Lits[0] = i * nLitsTot + toLitCond( p->pCnf->pVarNums[pObj->Id], 0 );
+ RetValue = sat_solver_solve( p->pSatBmc, Lits, Lits + 1, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+ if ( RetValue != l_False )
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Runs the SAT solver on the problem.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_ClausRunSat( Clu_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ int * pLits;
+ int i, RetValue;
+ pLits = ABC_ALLOC( int, p->nFrames + 1 );
+ // set the output literals
+ pObj = Aig_ManPo(p->pAig, 0);
+ for ( i = 0; i <= p->nFrames; i++ )
+ pLits[i] = i * 2 * p->pCnf->nVars + toLitCond( p->pCnf->pVarNums[pObj->Id], i != p->nFrames );
+ // try to solve the problem
+ RetValue = sat_solver_solve( p->pSatMain, pLits, pLits + p->nFrames + 1, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+ ABC_FREE( pLits );
+ if ( RetValue == l_False )
+ return 1;
+ // get the counter-example
+ assert( RetValue == l_True );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Runs the SAT solver on the problem.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_ClausRunSat0( Clu_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ int Lits[2], RetValue;
+ pObj = Aig_ManPo(p->pAig, 0);
+ Lits[0] = toLitCond( p->pCnf->pVarNums[pObj->Id], 0 );
+ RetValue = sat_solver_solve( p->pSatMain, Lits, Lits + 1, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+ if ( RetValue == l_False )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Return combinations appearing in the cut.]
+
+ Description [This procedure is taken from "Hacker's Delight" by H.S.Warren.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void transpose32a( unsigned a[32] )
+{
+ int j, k;
+ unsigned long m, t;
+ for ( j = 16, m = 0x0000FFFF; j; j >>= 1, m ^= m << j )
+ {
+ for ( k = 0; k < 32; k = ((k | j) + 1) & ~j )
+ {
+ t = (a[k] ^ (a[k|j] >> j)) & m;
+ a[k] ^= t;
+ a[k|j] ^= (t << j);
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Return combinations appearing in the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_ClausProcessClausesCut( Clu_Man_t * p, Fra_Sml_t * pSimMan, Dar_Cut_t * pCut, int * pScores )
+{
+ unsigned Matrix[32];
+ unsigned * pSims[16], uWord;
+ int nSeries, i, k, j;
+ int nWordsForSim = pSimMan->nWordsTotal - p->nSimWordsPref;
+ // compute parameters
+ assert( pCut->nLeaves > 1 && pCut->nLeaves < 5 );
+ assert( nWordsForSim % 8 == 0 );
+ // get parameters
+ for ( i = 0; i < (int)pCut->nLeaves; i++ )
+ pSims[i] = Fra_ObjSim( pSimMan, pCut->pLeaves[i] ) + p->nSimWordsPref;
+ // add combinational patterns
+ memset( pScores, 0, sizeof(int) * 16 );
+ nSeries = nWordsForSim / 8;
+ for ( i = 0; i < nSeries; i++ )
+ {
+ memset( Matrix, 0, sizeof(unsigned) * 32 );
+ for ( k = 0; k < 8; k++ )
+ for ( j = 0; j < (int)pCut->nLeaves; j++ )
+ Matrix[31-(k*4+j)] = pSims[j][i*8+k];
+ transpose32a( Matrix );
+ for ( k = 0; k < 32; k++ )
+ for ( j = 0, uWord = Matrix[k]; j < 8; j++, uWord >>= 4 )
+ pScores[uWord & 0xF]++;
+ }
+ // collect patterns
+ uWord = 0;
+ for ( i = 0; i < 16; i++ )
+ if ( pScores[i] )
+ uWord |= (1 << i);
+// Extra_PrintBinary( stdout, &uWord, 16 ); printf( "\n" );
+ return (int)uWord;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Return combinations appearing in the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_ClausProcessClausesCut2( Clu_Man_t * p, Fra_Sml_t * pSimMan, Dar_Cut_t * pCut, int * pScores )
+{
+ unsigned * pSims[16], uWord;
+ int iMint, i, k, b;
+ int nWordsForSim = pSimMan->nWordsTotal - p->nSimWordsPref;
+ // compute parameters
+ assert( pCut->nLeaves > 1 && pCut->nLeaves < 5 );
+ assert( nWordsForSim % 8 == 0 );
+ // get parameters
+ for ( i = 0; i < (int)pCut->nLeaves; i++ )
+ pSims[i] = Fra_ObjSim( pSimMan, pCut->pLeaves[i] ) + p->nSimWordsPref;
+ // add combinational patterns
+ memset( pScores, 0, sizeof(int) * 16 );
+ for ( i = 0; i < nWordsForSim; i++ )
+ for ( k = 0; k < 32; k++ )
+ {
+ iMint = 0;
+ for ( b = 0; b < (int)pCut->nLeaves; b++ )
+ if ( pSims[b][i] & (1 << k) )
+ iMint |= (1 << b);
+ pScores[iMint]++;
+ }
+ // collect patterns
+ uWord = 0;
+ for ( i = 0; i < 16; i++ )
+ if ( pScores[i] )
+ uWord |= (1 << i);
+// Extra_PrintBinary( stdout, &uWord, 16 ); printf( "\n" );
+ return (int)uWord;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Return the number of combinations appearing in the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClausProcessClausesCut3( Clu_Man_t * p, Fra_Sml_t * pSimMan, Aig_Cut_t * pCut, int * pScores )
+{
+ unsigned Matrix[32];
+ unsigned * pSims[16], uWord;
+ int iMint, i, j, k, b, nMints, nSeries;
+ int nWordsForSim = pSimMan->nWordsTotal - p->nSimWordsPref;
+
+ // compute parameters
+ assert( pCut->nFanins > 1 && pCut->nFanins < 17 );
+ assert( nWordsForSim % 8 == 0 );
+ // get parameters
+ for ( i = 0; i < (int)pCut->nFanins; i++ )
+ pSims[i] = Fra_ObjSim( pSimMan, pCut->pFanins[i] ) + p->nSimWordsPref;
+ // add combinational patterns
+ nMints = (1 << pCut->nFanins);
+ memset( pScores, 0, sizeof(int) * nMints );
+
+ if ( pCut->nLeafMax == 4 )
+ {
+ // convert the simulation patterns
+ nSeries = nWordsForSim / 8;
+ for ( i = 0; i < nSeries; i++ )
+ {
+ memset( Matrix, 0, sizeof(unsigned) * 32 );
+ for ( k = 0; k < 8; k++ )
+ for ( j = 0; j < (int)pCut->nFanins; j++ )
+ Matrix[31-(k*4+j)] = pSims[j][i*8+k];
+ transpose32a( Matrix );
+ for ( k = 0; k < 32; k++ )
+ for ( j = 0, uWord = Matrix[k]; j < 8; j++, uWord >>= 4 )
+ pScores[uWord & 0xF]++;
+ }
+ }
+ else
+ {
+ // go through the simulation patterns
+ for ( i = 0; i < nWordsForSim; i++ )
+ for ( k = 0; k < 32; k++ )
+ {
+ iMint = 0;
+ for ( b = 0; b < (int)pCut->nFanins; b++ )
+ if ( pSims[b][i] & (1 << k) )
+ iMint |= (1 << b);
+ pScores[iMint]++;
+ }
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns the cut-off cost.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_ClausSelectClauses( Clu_Man_t * p )
+{
+ int * pCostCount, nClauCount, Cost, CostMax, i, c;
+ assert( Vec_IntSize(p->vClauses) > p->nClausesMax );
+ // count how many implications have each cost
+ CostMax = p->nSimWords * 32 + 1;
+ pCostCount = ABC_ALLOC( int, CostMax );
+ memset( pCostCount, 0, sizeof(int) * CostMax );
+ Vec_IntForEachEntry( p->vCosts, Cost, i )
+ {
+ if ( Cost == -1 )
+ continue;
+ assert( Cost < CostMax );
+ pCostCount[ Cost ]++;
+ }
+ assert( pCostCount[0] == 0 );
+ // select the bound on the cost (above this bound, implication will be included)
+ nClauCount = 0;
+ for ( c = CostMax - 1; c > 0; c-- )
+ {
+ assert( pCostCount[c] >= 0 );
+ nClauCount += pCostCount[c];
+ if ( nClauCount >= p->nClausesMax )
+ break;
+ }
+ // collect implications with the given costs
+ nClauCount = 0;
+ Vec_IntForEachEntry( p->vCosts, Cost, i )
+ {
+ if ( Cost >= c && nClauCount < p->nClausesMax )
+ {
+ nClauCount++;
+ continue;
+ }
+ Vec_IntWriteEntry( p->vCosts, i, -1 );
+ }
+ ABC_FREE( pCostCount );
+ p->nClauses = nClauCount;
+if ( p->fVerbose )
+printf( "Selected %d clauses. Cost range: [%d < %d < %d]\n", nClauCount, 1, c, CostMax );
+ return c;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Processes the clauses.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClausRecordClause( Clu_Man_t * p, Dar_Cut_t * pCut, int iMint, int Cost )
+{
+ int i;
+ for ( i = 0; i < (int)pCut->nLeaves; i++ )
+ Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pCut->pLeaves[i]], (iMint&(1<<i)) ) );
+ Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) );
+ Vec_IntPush( p->vCosts, Cost );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Processes the clauses.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClausRecordClause2( Clu_Man_t * p, Aig_Cut_t * pCut, int iMint, int Cost )
+{
+ int i;
+ for ( i = 0; i < (int)pCut->nFanins; i++ )
+ Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pCut->pFanins[i]], (iMint&(1<<i)) ) );
+ Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) );
+ Vec_IntPush( p->vCosts, Cost );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if simulation info is composed of all zeros.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_ClausSmlNodeIsConst( Fra_Sml_t * pSeq, Aig_Obj_t * pObj )
+{
+ unsigned * pSims;
+ int i;
+ pSims = Fra_ObjSim(pSeq, pObj->Id);
+ for ( i = pSeq->nWordsPref; i < pSeq->nWordsTotal; i++ )
+ if ( pSims[i] )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if implications holds.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_ClausSmlNodesAreImp( Fra_Sml_t * pSeq, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2 )
+{
+ unsigned * pSimL, * pSimR;
+ int k;
+ pSimL = Fra_ObjSim(pSeq, pObj1->Id);
+ pSimR = Fra_ObjSim(pSeq, pObj2->Id);
+ for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ )
+ if ( pSimL[k] & ~pSimR[k] ) // !(Obj1 -> Obj2)
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if implications holds.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_ClausSmlNodesAreImpC( Fra_Sml_t * pSeq, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2 )
+{
+ unsigned * pSimL, * pSimR;
+ int k;
+ pSimL = Fra_ObjSim(pSeq, pObj1->Id);
+ pSimR = Fra_ObjSim(pSeq, pObj2->Id);
+ for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ )
+ if ( pSimL[k] & pSimR[k] )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Processes the clauses.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_ClausCollectLatchClauses( Clu_Man_t * p, Fra_Sml_t * pSeq )
+{
+ Aig_Obj_t * pObj1, * pObj2;
+ unsigned * pSims1, * pSims2;
+ int CostMax, i, k, nCountConst, nCountImps;
+
+ nCountConst = nCountImps = 0;
+ CostMax = p->nSimWords * 32;
+/*
+ // add the property
+ {
+ Aig_Obj_t * pObj;
+ int Lits[1];
+ pObj = Aig_ManPo( p->pAig, 0 );
+ Lits[0] = toLitCond( p->pCnf->pVarNums[pObj->Id], 1 );
+ Vec_IntPush( p->vLits, Lits[0] );
+ Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) );
+ Vec_IntPush( p->vCosts, CostMax );
+ nCountConst++;
+// printf( "Added the target property to the set of clauses to be inductively checked.\n" );
+ }
+*/
+
+ pSeq->nWordsPref = p->nSimWordsPref;
+ Aig_ManForEachLoSeq( p->pAig, pObj1, i )
+ {
+ pSims1 = Fra_ObjSim( pSeq, pObj1->Id );
+ if ( Fra_ClausSmlNodeIsConst( pSeq, pObj1 ) )
+ {
+ Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj1->Id], 1 ) );
+ Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) );
+ Vec_IntPush( p->vCosts, CostMax );
+ nCountConst++;
+ continue;
+ }
+ Aig_ManForEachLoSeq( p->pAig, pObj2, k )
+ {
+ pSims2 = Fra_ObjSim( pSeq, pObj2->Id );
+ if ( Fra_ClausSmlNodesAreImp( pSeq, pObj1, pObj2 ) )
+ {
+ Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj1->Id], 1 ) );
+ Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj2->Id], 0 ) );
+ Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) );
+ Vec_IntPush( p->vCosts, CostMax );
+ nCountImps++;
+ continue;
+ }
+ if ( Fra_ClausSmlNodesAreImp( pSeq, pObj2, pObj1 ) )
+ {
+ Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj2->Id], 1 ) );
+ Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj1->Id], 0 ) );
+ Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) );
+ Vec_IntPush( p->vCosts, CostMax );
+ nCountImps++;
+ continue;
+ }
+ if ( Fra_ClausSmlNodesAreImpC( pSeq, pObj1, pObj2 ) )
+ {
+ Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj1->Id], 1 ) );
+ Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj2->Id], 1 ) );
+ Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) );
+ Vec_IntPush( p->vCosts, CostMax );
+ nCountImps++;
+ continue;
+ }
+ }
+ if ( nCountConst + nCountImps > p->nClausesMax / 2 )
+ break;
+ }
+ pSeq->nWordsPref = 0;
+ if ( p->fVerbose )
+ printf( "Collected %d register constants and %d one-hotness implications.\n", nCountConst, nCountImps );
+ p->nOneHots = nCountConst + nCountImps;
+ p->nOneHotsProven = 0;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Processes the clauses.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_ClausProcessClauses( Clu_Man_t * p, int fRefs )
+{
+ Aig_MmFixed_t * pMemCuts;
+// Aig_ManCut_t * pManCut;
+ Fra_Sml_t * pComb, * pSeq;
+ Aig_Obj_t * pObj;
+ Dar_Cut_t * pCut;
+ int Scores[16], uScores, i, k, j, clk, nCuts = 0;
+
+ // simulate the AIG
+clk = clock();
+// srand( 0xAABBAABB );
+ Aig_ManRandom(1);
+ pSeq = Fra_SmlSimulateSeq( p->pAig, 0, p->nPref + p->nSimFrames, p->nSimWords/p->nSimFrames, 1 );
+ if ( p->fTarget && pSeq->fNonConstOut )
+ {
+ printf( "Property failed after sequential simulation!\n" );
+ Fra_SmlStop( pSeq );
+ return 0;
+ }
+if ( p->fVerbose )
+{
+ABC_PRT( "Sim-seq", clock() - clk );
+}
+
+
+clk = clock();
+ if ( fRefs )
+ {
+ Fra_ClausCollectLatchClauses( p, pSeq );
+if ( p->fVerbose )
+{
+ABC_PRT( "Lat-cla", clock() - clk );
+}
+ }
+
+
+ // generate cuts for all nodes, assign cost, and find best cuts
+clk = clock();
+ pMemCuts = Dar_ManComputeCuts( p->pAig, 10, 1 );
+// pManCut = Aig_ComputeCuts( p->pAig, 10, 4, 0, 1 );
+if ( p->fVerbose )
+{
+ABC_PRT( "Cuts ", clock() - clk );
+}
+
+ // collect sequential info for each cut
+clk = clock();
+ Aig_ManForEachNode( p->pAig, pObj, i )
+ Dar_ObjForEachCut( pObj, pCut, k )
+ if ( pCut->nLeaves > 1 )
+ {
+ pCut->uTruth = Fra_ClausProcessClausesCut( p, pSeq, pCut, Scores );
+// uScores = Fra_ClausProcessClausesCut2( p, pSeq, pCut, Scores );
+// if ( uScores != pCut->uTruth )
+// {
+// int x = 0;
+// }
+ }
+if ( p->fVerbose )
+{
+ABC_PRT( "Infoseq", clock() - clk );
+}
+ Fra_SmlStop( pSeq );
+
+ // perform combinational simulation
+clk = clock();
+// srand( 0xAABBAABB );
+ Aig_ManRandom(1);
+ pComb = Fra_SmlSimulateComb( p->pAig, p->nSimWords + p->nSimWordsPref );
+if ( p->fVerbose )
+{
+ABC_PRT( "Sim-cmb", clock() - clk );
+}
+
+ // collect combinational info for each cut
+clk = clock();
+ Aig_ManForEachNode( p->pAig, pObj, i )
+ Dar_ObjForEachCut( pObj, pCut, k )
+ if ( pCut->nLeaves > 1 )
+ {
+ nCuts++;
+ uScores = Fra_ClausProcessClausesCut( p, pComb, pCut, Scores );
+ uScores &= ~pCut->uTruth; pCut->uTruth = 0;
+ if ( uScores == 0 )
+ continue;
+ // write the clauses
+ for ( j = 0; j < (1<<pCut->nLeaves); j++ )
+ if ( uScores & (1 << j) )
+ Fra_ClausRecordClause( p, pCut, j, Scores[j] );
+
+ }
+ Fra_SmlStop( pComb );
+ Aig_MmFixedStop( pMemCuts, 0 );
+// Aig_ManCutStop( pManCut );
+if ( p->fVerbose )
+{
+ABC_PRT( "Infocmb", clock() - clk );
+}
+
+ if ( p->fVerbose )
+ printf( "Node = %5d. Non-triv cuts = %7d. Clauses = %6d. Clause per cut = %6.2f.\n",
+ Aig_ManNodeNum(p->pAig), nCuts, Vec_IntSize(p->vClauses), 1.0*Vec_IntSize(p->vClauses)/nCuts );
+
+ if ( Vec_IntSize(p->vClauses) > p->nClausesMax )
+ Fra_ClausSelectClauses( p );
+ else
+ p->nClauses = Vec_IntSize( p->vClauses );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Processes the clauses.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_ClausProcessClauses2( Clu_Man_t * p, int fRefs )
+{
+// Aig_MmFixed_t * pMemCuts;
+ Aig_ManCut_t * pManCut;
+ Fra_Sml_t * pComb, * pSeq;
+ Aig_Obj_t * pObj;
+ Aig_Cut_t * pCut;
+ int i, k, j, clk, nCuts = 0;
+ int ScoresSeq[1<<12], ScoresComb[1<<12];
+ assert( p->nLutSize < 13 );
+
+ // simulate the AIG
+clk = clock();
+// srand( 0xAABBAABB );
+ Aig_ManRandom(1);
+ pSeq = Fra_SmlSimulateSeq( p->pAig, 0, p->nPref + p->nSimFrames, p->nSimWords/p->nSimFrames, 1 );
+ if ( p->fTarget && pSeq->fNonConstOut )
+ {
+ printf( "Property failed after sequential simulation!\n" );
+ Fra_SmlStop( pSeq );
+ return 0;
+ }
+if ( p->fVerbose )
+{
+//ABC_PRT( "Sim-seq", clock() - clk );
+}
+
+ // perform combinational simulation
+clk = clock();
+// srand( 0xAABBAABB );
+ Aig_ManRandom(1);
+ pComb = Fra_SmlSimulateComb( p->pAig, p->nSimWords + p->nSimWordsPref );
+if ( p->fVerbose )
+{
+//ABC_PRT( "Sim-cmb", clock() - clk );
+}
+
+
+clk = clock();
+ if ( fRefs )
+ {
+ Fra_ClausCollectLatchClauses( p, pSeq );
+if ( p->fVerbose )
+{
+//ABC_PRT( "Lat-cla", clock() - clk );
+}
+ }
+
+
+ // generate cuts for all nodes, assign cost, and find best cuts
+clk = clock();
+// pMemCuts = Dar_ManComputeCuts( p->pAig, 10, 1 );
+ pManCut = Aig_ComputeCuts( p->pAig, p->nCutsMax, p->nLutSize, 0, p->fVerbose );
+if ( p->fVerbose )
+{
+//ABC_PRT( "Cuts ", clock() - clk );
+}
+
+ // collect combinational info for each cut
+clk = clock();
+ Aig_ManForEachNode( p->pAig, pObj, i )
+ {
+ if ( pObj->Level > (unsigned)p->nLevels )
+ continue;
+ Aig_ObjForEachCut( pManCut, pObj, pCut, k )
+ if ( pCut->nFanins > 1 )
+ {
+ nCuts++;
+ Fra_ClausProcessClausesCut3( p, pSeq, pCut, ScoresSeq );
+ Fra_ClausProcessClausesCut3( p, pComb, pCut, ScoresComb );
+ // write the clauses
+ for ( j = 0; j < (1<<pCut->nFanins); j++ )
+ if ( ScoresComb[j] != 0 && ScoresSeq[j] == 0 )
+ Fra_ClausRecordClause2( p, pCut, j, ScoresComb[j] );
+
+ }
+ }
+ Fra_SmlStop( pSeq );
+ Fra_SmlStop( pComb );
+ p->nCuts = nCuts;
+// Aig_MmFixedStop( pMemCuts, 0 );
+ Aig_ManCutStop( pManCut );
+ p->pAig->pManCuts = NULL;
+
+ if ( p->fVerbose )
+ {
+ printf( "Node = %5d. Cuts = %7d. Clauses = %6d. Clause/cut = %6.2f.\n",
+ Aig_ManNodeNum(p->pAig), nCuts, Vec_IntSize(p->vClauses), 1.0*Vec_IntSize(p->vClauses)/nCuts );
+ ABC_PRT( "Processing sim-info to find candidate clauses (unoptimized)", clock() - clk );
+ }
+
+ // filter out clauses that are contained in the already proven clauses
+ assert( p->nClauses == 0 );
+ p->nClauses = Vec_IntSize( p->vClauses );
+ if ( Vec_IntSize( p->vClausesProven ) > 0 )
+ {
+ int RetValue, k, Beg;
+ int End = -1; // Suppress "might be used uninitialized"
+ int * pStart;
+ // reset the solver
+ if ( p->pSatMain ) sat_solver_delete( p->pSatMain );
+ p->pSatMain = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 );
+ if ( p->pSatMain == NULL )
+ {
+ printf( "Error: Main solver is unsat.\n" );
+ return -1;
+ }
+
+ // add the proven clauses
+ Beg = 0;
+ pStart = Vec_IntArray(p->vLitsProven);
+ Vec_IntForEachEntry( p->vClausesProven, End, i )
+ {
+ assert( End - Beg <= p->nLutSize );
+ // add the clause to all timeframes
+ RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End );
+ if ( RetValue == 0 )
+ {
+ printf( "Error: Solver is UNSAT after adding assumption clauses.\n" );
+ return -1;
+ }
+ Beg = End;
+ }
+ assert( End == Vec_IntSize(p->vLitsProven) );
+
+ // check the clauses
+ Beg = 0;
+ pStart = Vec_IntArray(p->vLits);
+ Vec_IntForEachEntry( p->vClauses, End, i )
+ {
+ assert( Vec_IntEntry( p->vCosts, i ) >= 0 );
+ assert( End - Beg <= p->nLutSize );
+ // check the clause
+ for ( k = Beg; k < End; k++ )
+ pStart[k] = lit_neg( pStart[k] );
+ RetValue = sat_solver_solve( p->pSatMain, pStart + Beg, pStart + End, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+ for ( k = Beg; k < End; k++ )
+ pStart[k] = lit_neg( pStart[k] );
+ // the clause holds
+ if ( RetValue == l_False )
+ {
+ Vec_IntWriteEntry( p->vCosts, i, -1 );
+ p->nClauses--;
+ }
+ Beg = End;
+ }
+ assert( End == Vec_IntSize(p->vLits) );
+ if ( p->fVerbose )
+ printf( "Already proved clauses filtered out %d candidate clauses (out of %d).\n",
+ Vec_IntSize(p->vClauses) - p->nClauses, Vec_IntSize(p->vClauses) );
+ }
+
+ p->fFiltering = 0;
+ if ( p->nClauses > p->nClausesMax )
+ {
+ Fra_ClausSelectClauses( p );
+ p->fFiltering = 1;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts AIG into the SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_ClausBmcClauses( Clu_Man_t * p )
+{
+ int * pStart, nLitsTot, RetValue, Beg, End, Counter, i, k, f;
+/*
+ for ( i = 0; i < Vec_IntSize(p->vLits); i++ )
+ printf( "%d ", p->vLits->pArray[i] );
+ printf( "\n" );
+*/
+ // add the clauses
+ Counter = 0;
+ // skip through the prefix variables
+ if ( p->nPref )
+ {
+ nLitsTot = p->nPref * 2 * p->pCnf->nVars;
+ for ( i = 0; i < Vec_IntSize(p->vLits); i++ )
+ p->vLits->pArray[i] += nLitsTot;
+ }
+ // go through the timeframes
+ nLitsTot = 2 * p->pCnf->nVars;
+ pStart = Vec_IntArray(p->vLits);
+ for ( f = 0; f < p->nFrames; f++ )
+ {
+ Beg = 0;
+ Vec_IntForEachEntry( p->vClauses, End, i )
+ {
+ if ( Vec_IntEntry( p->vCosts, i ) == -1 )
+ {
+ Beg = End;
+ continue;
+ }
+ assert( Vec_IntEntry( p->vCosts, i ) > 0 );
+ assert( End - Beg <= p->nLutSize );
+
+ for ( k = Beg; k < End; k++ )
+ pStart[k] = lit_neg( pStart[k] );
+ RetValue = sat_solver_solve( p->pSatBmc, pStart + Beg, pStart + End, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+ for ( k = Beg; k < End; k++ )
+ pStart[k] = lit_neg( pStart[k] );
+
+ if ( RetValue != l_False )
+ {
+ Beg = End;
+ Vec_IntWriteEntry( p->vCosts, i, -1 );
+ Counter++;
+ continue;
+ }
+/*
+ // add the clause
+ RetValue = sat_solver_addclause( p->pSatBmc, pStart + Beg, pStart + End );
+ // assert( RetValue == 1 );
+ if ( RetValue == 0 )
+ {
+ printf( "Error: Solver is UNSAT after adding BMC clauses.\n" );
+ return -1;
+ }
+*/
+ Beg = End;
+
+ // simplify the solver
+ if ( p->pSatBmc->qtail != p->pSatBmc->qhead )
+ {
+ RetValue = sat_solver_simplify(p->pSatBmc);
+ assert( RetValue != 0 );
+ assert( p->pSatBmc->qtail == p->pSatBmc->qhead );
+ }
+ }
+ // increment literals
+ for ( i = 0; i < Vec_IntSize(p->vLits); i++ )
+ p->vLits->pArray[i] += nLitsTot;
+ }
+
+ // return clauses back to normal
+ nLitsTot = (p->nPref + p->nFrames) * nLitsTot;
+ for ( i = 0; i < Vec_IntSize(p->vLits); i++ )
+ p->vLits->pArray[i] -= nLitsTot;
+/*
+ for ( i = 0; i < Vec_IntSize(p->vLits); i++ )
+ printf( "%d ", p->vLits->pArray[i] );
+ printf( "\n" );
+*/
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Cleans simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClausSimInfoClean( Clu_Man_t * p )
+{
+ assert( p->pCnf->nVars <= Vec_PtrSize(p->vCexes) );
+ Vec_PtrCleanSimInfo( p->vCexes, 0, p->nCexesAlloc/32 );
+ p->nCexes = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reallocs simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClausSimInfoRealloc( Clu_Man_t * p )
+{
+ assert( p->nCexes == p->nCexesAlloc );
+ Vec_PtrReallocSimInfo( p->vCexes );
+ Vec_PtrCleanSimInfo( p->vCexes, p->nCexesAlloc/32, 2 * p->nCexesAlloc/32 );
+ p->nCexesAlloc *= 2;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Records simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClausSimInfoRecord( Clu_Man_t * p, int * pModel )
+{
+ int i;
+ if ( p->nCexes == p->nCexesAlloc )
+ Fra_ClausSimInfoRealloc( p );
+ assert( p->nCexes < p->nCexesAlloc );
+ for ( i = 0; i < p->pCnf->nVars; i++ )
+ {
+ if ( pModel[i] == l_True )
+ {
+ assert( Abc_InfoHasBit( (unsigned *)Vec_PtrEntry(p->vCexes, i), p->nCexes ) == 0 );
+ Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(p->vCexes, i), p->nCexes );
+ }
+ }
+ p->nCexes++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Uses the simulation info.]
+
+ Description [Returns 1 if the simulation info disproved the clause.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_ClausSimInfoCheck( Clu_Man_t * p, int * pLits, int nLits )
+{
+ unsigned * pSims[16], uWord;
+ int nWords, iVar, i, w;
+ for ( i = 0; i < nLits; i++ )
+ {
+ iVar = lit_var(pLits[i]) - p->nFrames * p->pCnf->nVars;
+ assert( iVar > 0 && iVar < p->pCnf->nVars );
+ pSims[i] = (unsigned *)Vec_PtrEntry( p->vCexes, iVar );
+ }
+ nWords = p->nCexes / 32;
+ for ( w = 0; w < nWords; w++ )
+ {
+ uWord = ~(unsigned)0;
+ for ( i = 0; i < nLits; i++ )
+ uWord &= (lit_sign(pLits[i])? pSims[i][w] : ~pSims[i][w]);
+ if ( uWord )
+ return 1;
+ }
+ if ( p->nCexes % 32 )
+ {
+ uWord = ~(unsigned)0;
+ for ( i = 0; i < nLits; i++ )
+ uWord &= (lit_sign(pLits[i])? pSims[i][w] : ~pSims[i][w]);
+ if ( uWord & Abc_InfoMask( p->nCexes % 32 ) )
+ return 1;
+ }
+ return 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Converts AIG into the SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_ClausInductiveClauses( Clu_Man_t * p )
+{
+// Aig_Obj_t * pObjLi, * pObjLo;
+ int * pStart, nLitsTot, RetValue, Beg, End, Counter, i, k, f, fFlag;//, Lits[2];
+ p->fFail = 0;
+
+ // reset the solver
+ if ( p->pSatMain ) sat_solver_delete( p->pSatMain );
+ p->pSatMain = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, p->nFrames+1, 0 );
+ if ( p->pSatMain == NULL )
+ {
+ printf( "Error: Main solver is unsat.\n" );
+ return -1;
+ }
+ Fra_ClausSimInfoClean( p );
+
+/*
+ // check if the property holds
+ if ( Fra_ClausRunSat0( p ) )
+ printf( "Property holds without strengthening.\n" );
+ else
+ printf( "Property does not hold without strengthening.\n" );
+*/
+/*
+ // add constant registers
+ Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObjLo, i )
+ if ( Aig_ObjFanin0(pObjLi) == Aig_ManConst1(p->pAig) )
+ {
+ for ( k = 0; k < p->nFrames; k++ )
+ {
+ Lits[0] = k * 2 * p->pCnf->nVars + toLitCond( p->pCnf->pVarNums[pObjLo->Id], Aig_ObjFaninC0(pObjLi) );
+ RetValue = sat_solver_addclause( p->pSatMain, Lits, Lits + 1 );
+ if ( RetValue == 0 )
+ {
+ printf( "Error: Solver is UNSAT after adding constant-register clauses.\n" );
+ return -1;
+ }
+ }
+ }
+*/
+
+
+ // add the proven clauses
+ nLitsTot = 2 * p->pCnf->nVars;
+ pStart = Vec_IntArray(p->vLitsProven);
+ for ( f = 0; f < p->nFrames; f++ )
+ {
+ Beg = 0;
+ Vec_IntForEachEntry( p->vClausesProven, End, i )
+ {
+ assert( End - Beg <= p->nLutSize );
+ // add the clause to all timeframes
+ RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End );
+ if ( RetValue == 0 )
+ {
+ printf( "Error: Solver is UNSAT after adding assumption clauses.\n" );
+ return -1;
+ }
+ Beg = End;
+ }
+ // increment literals
+ for ( i = 0; i < Vec_IntSize(p->vLitsProven); i++ )
+ p->vLitsProven->pArray[i] += nLitsTot;
+ }
+ // return clauses back to normal
+ nLitsTot = (p->nFrames) * nLitsTot;
+ for ( i = 0; i < Vec_IntSize(p->vLitsProven); i++ )
+ p->vLitsProven->pArray[i] -= nLitsTot;
+
+/*
+ // add the proven clauses
+ nLitsTot = 2 * p->pCnf->nVars;
+ pStart = Vec_IntArray(p->vLitsProven);
+ Beg = 0;
+ Vec_IntForEachEntry( p->vClausesProven, End, i )
+ {
+ assert( End - Beg <= p->nLutSize );
+ // add the clause to all timeframes
+ RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End );
+ if ( RetValue == 0 )
+ {
+ printf( "Error: Solver is UNSAT after adding assumption clauses.\n" );
+ return -1;
+ }
+ Beg = End;
+ }
+*/
+
+ // add the clauses
+ nLitsTot = 2 * p->pCnf->nVars;
+ pStart = Vec_IntArray(p->vLits);
+ for ( f = 0; f < p->nFrames; f++ )
+ {
+ Beg = 0;
+ Vec_IntForEachEntry( p->vClauses, End, i )
+ {
+ if ( Vec_IntEntry( p->vCosts, i ) == -1 )
+ {
+ Beg = End;
+ continue;
+ }
+ assert( Vec_IntEntry( p->vCosts, i ) > 0 );
+ assert( End - Beg <= p->nLutSize );
+ // add the clause to all timeframes
+ RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End );
+ if ( RetValue == 0 )
+ {
+ printf( "Error: Solver is UNSAT after adding assumption clauses.\n" );
+ return -1;
+ }
+ Beg = End;
+ }
+ // increment literals
+ for ( i = 0; i < Vec_IntSize(p->vLits); i++ )
+ p->vLits->pArray[i] += nLitsTot;
+ }
+
+ // simplify the solver
+ if ( p->pSatMain->qtail != p->pSatMain->qhead )
+ {
+ RetValue = sat_solver_simplify(p->pSatMain);
+ assert( RetValue != 0 );
+ assert( p->pSatMain->qtail == p->pSatMain->qhead );
+ }
+
+ // check if the property holds
+ if ( p->fTarget )
+ {
+ if ( Fra_ClausRunSat0( p ) )
+ {
+ if ( p->fVerbose )
+ printf( " Property holds. " );
+ }
+ else
+ {
+ if ( p->fVerbose )
+ printf( " Property fails. " );
+ // return -2;
+ p->fFail = 1;
+ }
+ }
+
+/*
+ // add the property for the first K frames
+ for ( i = 0; i < p->nFrames; i++ )
+ {
+ Aig_Obj_t * pObj;
+ int Lits[2];
+ // set the output literals
+ pObj = Aig_ManPo(p->pAig, 0);
+ Lits[0] = i * nLitsTot + toLitCond( p->pCnf->pVarNums[pObj->Id], 1 );
+ // add the clause
+ RetValue = sat_solver_addclause( p->pSatMain, Lits, Lits + 1 );
+// assert( RetValue == 1 );
+ if ( RetValue == 0 )
+ {
+ printf( "Error: Solver is UNSAT after adding property for the first K frames.\n" );
+ return -1;
+ }
+ }
+*/
+
+ // simplify the solver
+ if ( p->pSatMain->qtail != p->pSatMain->qhead )
+ {
+ RetValue = sat_solver_simplify(p->pSatMain);
+ assert( RetValue != 0 );
+ assert( p->pSatMain->qtail == p->pSatMain->qhead );
+ }
+
+
+ // check the clause in the last timeframe
+ Beg = 0;
+ Counter = 0;
+ Vec_IntForEachEntry( p->vClauses, End, i )
+ {
+ if ( Vec_IntEntry( p->vCosts, i ) == -1 )
+ {
+ Beg = End;
+ continue;
+ }
+ assert( Vec_IntEntry( p->vCosts, i ) > 0 );
+ assert( End - Beg <= p->nLutSize );
+
+ if ( Fra_ClausSimInfoCheck(p, pStart + Beg, End - Beg) )
+ {
+ fFlag = 1;
+// printf( "s-" );
+
+ Beg = End;
+ Vec_IntWriteEntry( p->vCosts, i, -1 );
+ Counter++;
+ continue;
+ }
+ else
+ {
+ fFlag = 0;
+// printf( "s?" );
+ }
+
+ for ( k = Beg; k < End; k++ )
+ pStart[k] = lit_neg( pStart[k] );
+ RetValue = sat_solver_solve( p->pSatMain, pStart + Beg, pStart + End, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+ for ( k = Beg; k < End; k++ )
+ pStart[k] = lit_neg( pStart[k] );
+
+ // the problem is not solved
+ if ( RetValue != l_False )
+ {
+// printf( "S- " );
+// Fra_ClausSimInfoRecord( p, (int*)p->pSatMain->model.ptr + p->nFrames * p->pCnf->nVars );
+ Fra_ClausSimInfoRecord( p, (int*)p->pSatMain->model + p->nFrames * p->pCnf->nVars );
+// RetValue = Fra_ClausSimInfoCheck(p, pStart + Beg, End - Beg);
+// assert( RetValue );
+
+ Beg = End;
+ Vec_IntWriteEntry( p->vCosts, i, -1 );
+ Counter++;
+ continue;
+ }
+// printf( "S+ " );
+// assert( !fFlag );
+
+/*
+ // add the clause
+ RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End );
+// assert( RetValue == 1 );
+ if ( RetValue == 0 )
+ {
+ printf( "Error: Solver is UNSAT after adding proved clauses.\n" );
+ return -1;
+ }
+*/
+ Beg = End;
+
+ // simplify the solver
+ if ( p->pSatMain->qtail != p->pSatMain->qhead )
+ {
+ RetValue = sat_solver_simplify(p->pSatMain);
+ assert( RetValue != 0 );
+ assert( p->pSatMain->qtail == p->pSatMain->qhead );
+ }
+ }
+
+ // return clauses back to normal
+ nLitsTot = p->nFrames * nLitsTot;
+ for ( i = 0; i < Vec_IntSize(p->vLits); i++ )
+ p->vLits->pArray[i] -= nLitsTot;
+
+// if ( fFail )
+// return -2;
+ return Counter;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Converts AIG into the SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Clu_Man_t * Fra_ClausAlloc( Aig_Man_t * pAig, int nFrames, int nPref, int nClausesMax, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fTarget, int fVerbose, int fVeryVerbose )
+{
+ Clu_Man_t * p;
+ p = ABC_ALLOC( Clu_Man_t, 1 );
+ memset( p, 0, sizeof(Clu_Man_t) );
+ p->pAig = pAig;
+ p->nFrames = nFrames;
+ p->nPref = nPref;
+ p->nClausesMax = nClausesMax;
+ p->nLutSize = nLutSize;
+ p->nLevels = nLevels;
+ p->nCutsMax = nCutsMax;
+ p->nBatches = nBatches;
+ p->fStepUp = fStepUp;
+ p->fTarget = fTarget;
+ p->fVerbose = fVerbose;
+ p->fVeryVerbose = fVeryVerbose;
+ p->nSimWords = 512;//1024;//64;
+ p->nSimFrames = 32;//8;//32;
+ p->nSimWordsPref = p->nPref*p->nSimWords/p->nSimFrames;
+
+ p->vLits = Vec_IntAlloc( 1<<14 );
+ p->vClauses = Vec_IntAlloc( 1<<12 );
+ p->vCosts = Vec_IntAlloc( 1<<12 );
+
+ p->vLitsProven = Vec_IntAlloc( 1<<14 );
+ p->vClausesProven= Vec_IntAlloc( 1<<12 );
+
+ p->nCexesAlloc = 1024;
+ p->vCexes = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p->pAig)+1, p->nCexesAlloc/32 );
+ Vec_PtrCleanSimInfo( p->vCexes, 0, p->nCexesAlloc/32 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts AIG into the SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClausFree( Clu_Man_t * p )
+{
+ if ( p->vCexes ) Vec_PtrFree( p->vCexes );
+ if ( p->vLits ) Vec_IntFree( p->vLits );
+ if ( p->vClauses ) Vec_IntFree( p->vClauses );
+ if ( p->vLitsProven ) Vec_IntFree( p->vLitsProven );
+ if ( p->vClausesProven ) Vec_IntFree( p->vClausesProven );
+ if ( p->vCosts ) Vec_IntFree( p->vCosts );
+ if ( p->pCnf ) Cnf_DataFree( p->pCnf );
+ if ( p->pSatMain ) sat_solver_delete( p->pSatMain );
+ if ( p->pSatBmc ) sat_solver_delete( p->pSatBmc );
+ ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Converts AIG into the SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClausAddToStorage( Clu_Man_t * p )
+{
+ int * pStart;
+ int Beg, End, Counter, i, k;
+ Beg = 0;
+ Counter = 0;
+ pStart = Vec_IntArray( p->vLits );
+ Vec_IntForEachEntry( p->vClauses, End, i )
+ {
+ if ( Vec_IntEntry( p->vCosts, i ) == -1 )
+ {
+ Beg = End;
+ continue;
+ }
+ assert( Vec_IntEntry( p->vCosts, i ) > 0 );
+ assert( End - Beg <= p->nLutSize );
+ for ( k = Beg; k < End; k++ )
+ Vec_IntPush( p->vLitsProven, pStart[k] );
+ Vec_IntPush( p->vClausesProven, Vec_IntSize(p->vLitsProven) );
+ Beg = End;
+ Counter++;
+
+ if ( i < p->nOneHots )
+ p->nOneHotsProven++;
+ }
+ if ( p->fVerbose )
+ printf( "Added to storage %d proved clauses (including %d one-hot clauses)\n", Counter, p->nOneHotsProven );
+
+ Vec_IntClear( p->vClauses );
+ Vec_IntClear( p->vLits );
+ Vec_IntClear( p->vCosts );
+ p->nClauses = 0;
+
+ p->fNothingNew = (int)(Counter == 0);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts AIG into the SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClausPrintIndClauses( Clu_Man_t * p )
+{
+ int Counters[9] = {0};
+ int * pStart;
+ int Beg, End, i;
+ Beg = 0;
+ pStart = Vec_IntArray( p->vLitsProven );
+ Vec_IntForEachEntry( p->vClausesProven, End, i )
+ {
+ if ( End - Beg >= 8 )
+ Counters[8]++;
+ else
+ Counters[End - Beg]++;
+//printf( "%d ", End-Beg );
+ Beg = End;
+ }
+ printf( "SUMMARY: Total proved clauses = %d. ", Vec_IntSize(p->vClausesProven) );
+ printf( "Clause per lit: " );
+ for ( i = 0; i < 8; i++ )
+ if ( Counters[i] )
+ printf( "%d=%d ", i, Counters[i] );
+ if ( Counters[8] )
+ printf( ">7=%d ", Counters[8] );
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the clauses into an AIGER file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Obj_t * Fra_ClausGetLiteral( Clu_Man_t * p, int * pVar2Id, int Lit )
+{
+ Aig_Obj_t * pLiteral;
+ int NodeId = pVar2Id[ lit_var(Lit) ];
+ assert( NodeId >= 0 );
+ pLiteral = (Aig_Obj_t *)Aig_ManObj( p->pAig, NodeId )->pData;
+ return Aig_NotCond( pLiteral, lit_sign(Lit) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes the clauses into an AIGER file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClausWriteIndClauses( Clu_Man_t * p )
+{
+ extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact );
+ Aig_Man_t * pNew;
+ Aig_Obj_t * pClause, * pLiteral;
+ char * pName;
+ int * pStart, * pVar2Id;
+ int Beg, End, i, k;
+ // create mapping from SAT vars to node IDs
+ pVar2Id = ABC_ALLOC( int, p->pCnf->nVars );
+ memset( pVar2Id, 0xFF, sizeof(int) * p->pCnf->nVars );
+ for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ )
+ if ( p->pCnf->pVarNums[i] >= 0 )
+ {
+ assert( p->pCnf->pVarNums[i] < p->pCnf->nVars );
+ pVar2Id[ p->pCnf->pVarNums[i] ] = i;
+ }
+ // start the manager
+ pNew = Aig_ManDupWithoutPos( p->pAig );
+ // add the clauses
+ Beg = 0;
+ pStart = Vec_IntArray( p->vLitsProven );
+ Vec_IntForEachEntry( p->vClausesProven, End, i )
+ {
+ pClause = Fra_ClausGetLiteral( p, pVar2Id, pStart[Beg] );
+ for ( k = Beg + 1; k < End; k++ )
+ {
+ pLiteral = Fra_ClausGetLiteral( p, pVar2Id, pStart[k] );
+ pClause = Aig_Or( pNew, pClause, pLiteral );
+ }
+ Aig_ObjCreatePo( pNew, pClause );
+ Beg = End;
+ }
+ ABC_FREE( pVar2Id );
+ Aig_ManCleanup( pNew );
+ pName = Ioa_FileNameGenericAppend( p->pAig->pName, "_care.aig" );
+ printf( "Care one-hotness clauses will be written into file \"%s\".\n", pName );
+ Ioa_WriteAiger( pNew, pName, 0, 1 );
+ Aig_ManStop( pNew );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks if the clause holds using the given simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClausEstimateCoverageOne( Fra_Sml_t * pSim, int * pLits, int nLits, int * pVar2Id, unsigned * pResult )
+{
+ unsigned * pSims[16];
+ int iVar, i, w;
+ for ( i = 0; i < nLits; i++ )
+ {
+ iVar = lit_var(pLits[i]);
+ pSims[i] = Fra_ObjSim( pSim, pVar2Id[iVar] );
+ }
+ for ( w = 0; w < pSim->nWordsTotal; w++ )
+ {
+ pResult[w] = ~(unsigned)0;
+ for ( i = 0; i < nLits; i++ )
+ pResult[w] &= (lit_sign(pLits[i])? pSims[i][w] : ~pSims[i][w]);
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Estimates the coverage of state space by clauses.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClausEstimateCoverage( Clu_Man_t * p )
+{
+ int nCombSimWords = (1<<11);
+ Fra_Sml_t * pComb;
+ unsigned * pResultTot, * pResultOne;
+ int nCovered, Beg, End, i, w;
+ int * pStart, * pVar2Id;
+ int clk = clock();
+ // simulate the circuit with nCombSimWords * 32 = 64K patterns
+// srand( 0xAABBAABB );
+ Aig_ManRandom(1);
+ pComb = Fra_SmlSimulateComb( p->pAig, nCombSimWords );
+ // create mapping from SAT vars to node IDs
+ pVar2Id = ABC_ALLOC( int, p->pCnf->nVars );
+ memset( pVar2Id, 0, sizeof(int) * p->pCnf->nVars );
+ for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ )
+ if ( p->pCnf->pVarNums[i] >= 0 )
+ {
+ assert( p->pCnf->pVarNums[i] < p->pCnf->nVars );
+ pVar2Id[ p->pCnf->pVarNums[i] ] = i;
+ }
+ // get storage for one assignment and all assignments
+ assert( Aig_ManPoNum(p->pAig) > 2 );
+ pResultOne = Fra_ObjSim( pComb, Aig_ManPo(p->pAig, 0)->Id );
+ pResultTot = Fra_ObjSim( pComb, Aig_ManPo(p->pAig, 1)->Id );
+ // start the OR of don't-cares
+ for ( w = 0; w < nCombSimWords; w++ )
+ pResultTot[w] = 0;
+ // check clauses
+ Beg = 0;
+ pStart = Vec_IntArray( p->vLitsProven );
+ Vec_IntForEachEntry( p->vClausesProven, End, i )
+ {
+ Fra_ClausEstimateCoverageOne( pComb, pStart + Beg, End-Beg, pVar2Id, pResultOne );
+ Beg = End;
+ for ( w = 0; w < nCombSimWords; w++ )
+ pResultTot[w] |= pResultOne[w];
+ }
+ // count the total number of patterns contained in the don't-care
+ nCovered = 0;
+ for ( w = 0; w < nCombSimWords; w++ )
+ nCovered += Aig_WordCountOnes( pResultTot[w] );
+ Fra_SmlStop( pComb );
+ ABC_FREE( pVar2Id );
+ // print the result
+ printf( "Care states ratio = %f. ", 1.0 * (nCombSimWords * 32 - nCovered) / (nCombSimWords * 32) );
+ printf( "(%d out of %d patterns) ", nCombSimWords * 32 - nCovered, nCombSimWords * 32 );
+ ABC_PRT( "Time", clock() - clk );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Converts AIG into the SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_Claus( Aig_Man_t * pAig, int nFrames, int nPref, int nClausesMax, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fBmc, int fRefs, int fTarget, int fVerbose, int fVeryVerbose )
+{
+ Clu_Man_t * p;
+ int clk, clkTotal = clock(), clkInd;
+ int b, Iter, Counter, nPrefOld;
+ int nClausesBeg = 0;
+
+ // create the manager
+ p = Fra_ClausAlloc( pAig, nFrames, nPref, nClausesMax, nLutSize, nLevels, nCutsMax, nBatches, fStepUp, fTarget, fVerbose, fVeryVerbose );
+if ( p->fVerbose )
+{
+ printf( "PARAMETERS: Frames = %d. Pref = %d. Clauses max = %d. Cut size = %d.\n", nFrames, nPref, nClausesMax, nLutSize );
+ printf( "Level max = %d. Cuts max = %d. Batches = %d. Increment cut size = %s.\n", nLevels, nCutsMax, nBatches, fStepUp? "yes":"no" );
+//ABC_PRT( "Sim-seq", clock() - clk );
+}
+
+ assert( !p->fTarget || Aig_ManPoNum(pAig) - Aig_ManRegNum(pAig) == 1 );
+
+clk = clock();
+ // derive CNF
+// if ( p->fTarget )
+// p->pAig->nRegs++;
+ p->pCnf = Cnf_DeriveSimple( p->pAig, Aig_ManPoNum(p->pAig) );
+// if ( p->fTarget )
+// p->pAig->nRegs--;
+if ( fVerbose )
+{
+//ABC_PRT( "CNF ", clock() - clk );
+}
+
+ // check BMC
+clk = clock();
+ p->pSatBmc = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, p->nPref + p->nFrames, 1 );
+ if ( p->pSatBmc == NULL )
+ {
+ printf( "Error: BMC solver is unsat.\n" );
+ Fra_ClausFree( p );
+ return 1;
+ }
+ if ( p->fTarget && !Fra_ClausRunBmc( p ) )
+ {
+ printf( "Problem fails the base case after %d frame expansion.\n", p->nPref + p->nFrames );
+ Fra_ClausFree( p );
+ return 1;
+ }
+if ( fVerbose )
+{
+//ABC_PRT( "SAT-bmc", clock() - clk );
+}
+
+ // start the SAT solver
+clk = clock();
+ p->pSatMain = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, p->nFrames+1, 0 );
+ if ( p->pSatMain == NULL )
+ {
+ printf( "Error: Main solver is unsat.\n" );
+ Fra_ClausFree( p );
+ return 1;
+ }
+
+
+ for ( b = 0; b < p->nBatches; b++ )
+ {
+// if ( fVerbose )
+ printf( "*** BATCH %d: ", b+1 );
+ if ( b && p->nLutSize < 12 && (!p->fFiltering || p->fNothingNew || p->fStepUp) )
+ p->nLutSize++;
+ printf( "Using %d-cuts.\n", p->nLutSize );
+
+ // try solving without additional clauses
+ if ( p->fTarget && Fra_ClausRunSat( p ) )
+ {
+ printf( "Problem is inductive without strengthening.\n" );
+ Fra_ClausFree( p );
+ return 1;
+ }
+ if ( fVerbose )
+ {
+// ABC_PRT( "SAT-ind", clock() - clk );
+ }
+
+ // collect the candidate inductive clauses using 4-cuts
+ clk = clock();
+ nPrefOld = p->nPref; p->nPref = 0; p->nSimWordsPref = 0;
+ // Fra_ClausProcessClauses( p, fRefs );
+ Fra_ClausProcessClauses2( p, fRefs );
+ p->nPref = nPrefOld;
+ p->nSimWordsPref = p->nPref*p->nSimWords/p->nSimFrames;
+ nClausesBeg = p->nClauses;
+
+ //ABC_PRT( "Clauses", clock() - clk );
+
+
+ // check clauses using BMC
+ if ( fBmc )
+ {
+ clk = clock();
+ Counter = Fra_ClausBmcClauses( p );
+ p->nClauses -= Counter;
+ if ( fVerbose )
+ {
+ printf( "BMC disproved %d clauses. ", Counter );
+ ABC_PRT( "Time", clock() - clk );
+ }
+ }
+
+
+ // prove clauses inductively
+ clkInd = clk = clock();
+ Counter = 1;
+ for ( Iter = 0; Counter > 0; Iter++ )
+ {
+ if ( fVerbose )
+ printf( "Iter %3d : Begin = %5d. ", Iter, p->nClauses );
+ Counter = Fra_ClausInductiveClauses( p );
+ if ( Counter > 0 )
+ p->nClauses -= Counter;
+ if ( fVerbose )
+ {
+ printf( "End = %5d. Exs = %5d. ", p->nClauses, p->nCexes );
+ // printf( "\n" );
+ ABC_PRT( "Time", clock() - clk );
+ }
+ clk = clock();
+ }
+ // add proved clauses to storage
+ Fra_ClausAddToStorage( p );
+ // report the results
+ if ( p->fTarget )
+ {
+ if ( Counter == -1 )
+ printf( "Fra_Claus(): Internal error. " );
+ else if ( p->fFail )
+ printf( "Property FAILS during refinement. " );
+ else
+ printf( "Property HOLDS inductively after strengthening. " );
+ ABC_PRT( "Time ", clock() - clkTotal );
+ if ( !p->fFail )
+ break;
+ }
+ else
+ {
+ printf( "Finished proving inductive clauses. " );
+ ABC_PRT( "Time ", clock() - clkTotal );
+ }
+ }
+
+ // verify the computed interpolant
+ Fra_InvariantVerify( pAig, nFrames, p->vClausesProven, p->vLitsProven );
+// printf( "THIS COMMAND IS KNOWN TO HAVE A BUG!\n" );
+
+// if ( !p->fTarget && p->fVerbose )
+ if ( p->fVerbose )
+ {
+ Fra_ClausPrintIndClauses( p );
+ Fra_ClausEstimateCoverage( p );
+ }
+
+ if ( !p->fTarget )
+ {
+ Fra_ClausWriteIndClauses( p );
+ }
+/*
+ // print the statistic into a file
+ {
+ FILE * pTable;
+ assert( p->nBatches == 1 );
+ pTable = fopen( "stats.txt", "a+" );
+ fprintf( pTable, "%s ", pAig->pName );
+ fprintf( pTable, "%d ", Aig_ManPiNum(pAig)-Aig_ManRegNum(pAig) );
+ fprintf( pTable, "%d ", Aig_ManPoNum(pAig)-Aig_ManRegNum(pAig) );
+ fprintf( pTable, "%d ", Aig_ManRegNum(pAig) );
+ fprintf( pTable, "%d ", Aig_ManNodeNum(pAig) );
+ fprintf( pTable, "%d ", p->nCuts );
+ fprintf( pTable, "%d ", nClausesBeg );
+ fprintf( pTable, "%d ", p->nClauses );
+ fprintf( pTable, "%d ", Iter );
+ fprintf( pTable, "%.2f ", (float)(clkInd-clkTotal)/(float)(CLOCKS_PER_SEC) );
+ fprintf( pTable, "%.2f ", (float)(clock()-clkInd)/(float)(CLOCKS_PER_SEC) );
+ fprintf( pTable, "%.2f ", (float)(clock()-clkTotal)/(float)(CLOCKS_PER_SEC) );
+ fprintf( pTable, "\n" );
+ fclose( pTable );
+ }
+*/
+ // clean the manager
+ Fra_ClausFree( p );
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fra/fraCnf.c b/src/proof/fra/fraCnf.c
new file mode 100644
index 00000000..5021e750
--- /dev/null
+++ b/src/proof/fra/fraCnf.c
@@ -0,0 +1,289 @@
+/**CFile****************************************************************
+
+ FileName [fraCnf.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: fraCnf.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+ Synopsis [Addes clauses to the solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_AddClausesMux( Fra_Man_t * p, Aig_Obj_t * pNode )
+{
+ Aig_Obj_t * pNodeI, * pNodeT, * pNodeE;
+ int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE;
+
+ assert( !Aig_IsComplement( pNode ) );
+ assert( Aig_ObjIsMuxType( pNode ) );
+ // get nodes (I = if, T = then, E = else)
+ pNodeI = Aig_ObjRecognizeMux( pNode, &pNodeT, &pNodeE );
+ // get the variable numbers
+ VarF = Fra_ObjSatNum(pNode);
+ VarI = Fra_ObjSatNum(pNodeI);
+ VarT = Fra_ObjSatNum(Aig_Regular(pNodeT));
+ VarE = Fra_ObjSatNum(Aig_Regular(pNodeE));
+ // get the complementation flags
+ fCompT = Aig_IsComplement(pNodeT);
+ fCompE = Aig_IsComplement(pNodeE);
+
+ // f = ITE(i, t, e)
+
+ // i' + t' + f
+ // i' + t + f'
+ // i + e' + f
+ // i + e + f'
+
+ // create four clauses
+ pLits[0] = toLitCond(VarI, 1);
+ pLits[1] = toLitCond(VarT, 1^fCompT);
+ pLits[2] = toLitCond(VarF, 0);
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+ pLits[0] = toLitCond(VarI, 1);
+ pLits[1] = toLitCond(VarT, 0^fCompT);
+ pLits[2] = toLitCond(VarF, 1);
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+ pLits[0] = toLitCond(VarI, 0);
+ pLits[1] = toLitCond(VarE, 1^fCompE);
+ pLits[2] = toLitCond(VarF, 0);
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+ pLits[0] = toLitCond(VarI, 0);
+ pLits[1] = toLitCond(VarE, 0^fCompE);
+ pLits[2] = toLitCond(VarF, 1);
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+
+ // two additional clauses
+ // t' & e' -> f'
+ // t & e -> f
+
+ // t + e + f'
+ // t' + e' + f
+
+ if ( VarT == VarE )
+ {
+// assert( fCompT == !fCompE );
+ return;
+ }
+
+ pLits[0] = toLitCond(VarT, 0^fCompT);
+ pLits[1] = toLitCond(VarE, 0^fCompE);
+ pLits[2] = toLitCond(VarF, 1);
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+ pLits[0] = toLitCond(VarT, 1^fCompT);
+ pLits[1] = toLitCond(VarE, 1^fCompE);
+ pLits[2] = toLitCond(VarF, 0);
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Addes clauses to the solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_AddClausesSuper( Fra_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vSuper )
+{
+ Aig_Obj_t * pFanin;
+ int * pLits, nLits, RetValue, i;
+ assert( !Aig_IsComplement(pNode) );
+ assert( Aig_ObjIsNode( pNode ) );
+ // create storage for literals
+ nLits = Vec_PtrSize(vSuper) + 1;
+ pLits = ABC_ALLOC( int, nLits );
+ // suppose AND-gate is A & B = C
+ // add !A => !C or A + !C
+ Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i )
+ {
+ pLits[0] = toLitCond(Fra_ObjSatNum(Aig_Regular(pFanin)), Aig_IsComplement(pFanin));
+ pLits[1] = toLitCond(Fra_ObjSatNum(pNode), 1);
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+ assert( RetValue );
+ }
+ // add A & B => C or !A + !B + C
+ Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i )
+ pLits[i] = toLitCond(Fra_ObjSatNum(Aig_Regular(pFanin)), !Aig_IsComplement(pFanin));
+ pLits[nLits-1] = toLitCond(Fra_ObjSatNum(pNode), 0);
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits );
+ assert( RetValue );
+ ABC_FREE( pLits );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_CollectSuper_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes )
+{
+ // if the new node is complemented or a PI, another gate begins
+ if ( Aig_IsComplement(pObj) || Aig_ObjIsPi(pObj) || (!fFirst && Aig_ObjRefs(pObj) > 1) ||
+ (fUseMuxes && Aig_ObjIsMuxType(pObj)) )
+ {
+ Vec_PtrPushUnique( vSuper, pObj );
+ return;
+ }
+ // go through the branches
+ Fra_CollectSuper_rec( Aig_ObjChild0(pObj), vSuper, 0, fUseMuxes );
+ Fra_CollectSuper_rec( Aig_ObjChild1(pObj), vSuper, 0, fUseMuxes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Fra_CollectSuper( Aig_Obj_t * pObj, int fUseMuxes )
+{
+ Vec_Ptr_t * vSuper;
+ assert( !Aig_IsComplement(pObj) );
+ assert( !Aig_ObjIsPi(pObj) );
+ vSuper = Vec_PtrAlloc( 4 );
+ Fra_CollectSuper_rec( pObj, vSuper, 1, fUseMuxes );
+ return vSuper;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the solver clause database.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ObjAddToFrontier( Fra_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vFrontier )
+{
+ assert( !Aig_IsComplement(pObj) );
+ if ( Fra_ObjSatNum(pObj) )
+ return;
+ assert( Fra_ObjSatNum(pObj) == 0 );
+ assert( Fra_ObjFaninVec(pObj) == NULL );
+ if ( Aig_ObjIsConst1(pObj) )
+ return;
+ Fra_ObjSetSatNum( pObj, p->nSatVars++ );
+ if ( Aig_ObjIsNode(pObj) )
+ Vec_PtrPush( vFrontier, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the solver clause database.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_CnfNodeAddToSolver( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew )
+{
+ Vec_Ptr_t * vFrontier, * vFanins;
+ Aig_Obj_t * pNode, * pFanin;
+ int i, k, fUseMuxes = 1;
+ assert( pOld || pNew );
+ // quit if CNF is ready
+ if ( (!pOld || Fra_ObjFaninVec(pOld)) && (!pNew || Fra_ObjFaninVec(pNew)) )
+ return;
+ // start the frontier
+ vFrontier = Vec_PtrAlloc( 100 );
+ if ( pOld ) Fra_ObjAddToFrontier( p, pOld, vFrontier );
+ if ( pNew ) Fra_ObjAddToFrontier( p, pNew, vFrontier );
+ // explore nodes in the frontier
+ Vec_PtrForEachEntry( Aig_Obj_t *, vFrontier, pNode, i )
+ {
+ // create the supergate
+ assert( Fra_ObjSatNum(pNode) );
+ assert( Fra_ObjFaninVec(pNode) == NULL );
+ if ( fUseMuxes && Aig_ObjIsMuxType(pNode) )
+ {
+ vFanins = Vec_PtrAlloc( 4 );
+ Vec_PtrPushUnique( vFanins, Aig_ObjFanin0( Aig_ObjFanin0(pNode) ) );
+ Vec_PtrPushUnique( vFanins, Aig_ObjFanin0( Aig_ObjFanin1(pNode) ) );
+ Vec_PtrPushUnique( vFanins, Aig_ObjFanin1( Aig_ObjFanin0(pNode) ) );
+ Vec_PtrPushUnique( vFanins, Aig_ObjFanin1( Aig_ObjFanin1(pNode) ) );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vFanins, pFanin, k )
+ Fra_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier );
+ Fra_AddClausesMux( p, pNode );
+ }
+ else
+ {
+ vFanins = Fra_CollectSuper( pNode, fUseMuxes );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vFanins, pFanin, k )
+ Fra_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier );
+ Fra_AddClausesSuper( p, pNode, vFanins );
+ }
+ assert( Vec_PtrSize(vFanins) > 1 );
+ Fra_ObjSetFaninVec( pNode, vFanins );
+ }
+ Vec_PtrFree( vFrontier );
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fra/fraCore.c b/src/proof/fra/fraCore.c
new file mode 100644
index 00000000..d3b60ab7
--- /dev/null
+++ b/src/proof/fra/fraCore.c
@@ -0,0 +1,490 @@
+/**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_ObjIsPi(Aig_Regular(pChild)) && Aig_ObjPioNum(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_ManPoNum(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_ManPiNum(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_ManForEachPi( 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_ManForEachPo( 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;
+ int clk;
+ if ( Aig_ManNodeNum(pManAig) == 0 )
+ return Aig_ManDupOrdered(pManAig);
+clk = 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 )
+ {
+int clk2 = 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 += clock() - clk2;
+ }
+ else
+ {
+ Fra_ClassesCopyReprs( p->pCla, p->vTimeouts );
+ Aig_ManCleanup( p->pManFraig );
+ pManAigNew = p->pManFraig;
+ p->pManFraig = NULL;
+ }
+p->timeTotal = 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
+
diff --git a/src/proof/fra/fraHot.c b/src/proof/fra/fraHot.c
new file mode 100644
index 00000000..29c9c33d
--- /dev/null
+++ b/src/proof/fra/fraHot.c
@@ -0,0 +1,476 @@
+/**CFile****************************************************************
+
+ FileName [fraHot.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [New FRAIG package.]
+
+ Synopsis [Computing and using one-hotness conditions.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 30, 2007.]
+
+ Revision [$Id: fraHot.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int Fra_RegToLit( int n, int c ) { return c? -n-1 : n+1; }
+static inline int Fra_LitReg( int n ) { return (n>0)? n-1 : -n-1; }
+static inline int Fra_LitSign( int n ) { return (n<0); }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if simulation info is composed of all zeros.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_OneHotNodeIsConst( Fra_Sml_t * pSeq, Aig_Obj_t * pObj )
+{
+ unsigned * pSims;
+ int i;
+ pSims = Fra_ObjSim(pSeq, pObj->Id);
+ for ( i = pSeq->nWordsPref; i < pSeq->nWordsTotal; i++ )
+ if ( pSims[i] )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if simulation infos are equal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_OneHotNodesAreEqual( Fra_Sml_t * pSeq, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
+{
+ unsigned * pSims0, * pSims1;
+ int i;
+ pSims0 = Fra_ObjSim(pSeq, pObj0->Id);
+ pSims1 = Fra_ObjSim(pSeq, pObj1->Id);
+ for ( i = pSeq->nWordsPref; i < pSeq->nWordsTotal; i++ )
+ if ( pSims0[i] != pSims1[i] )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if implications holds.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_OneHotNodesAreClause( Fra_Sml_t * pSeq, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2, int fCompl1, int fCompl2 )
+{
+ unsigned * pSim1, * pSim2;
+ int k;
+ pSim1 = Fra_ObjSim(pSeq, pObj1->Id);
+ pSim2 = Fra_ObjSim(pSeq, pObj2->Id);
+ if ( fCompl1 && fCompl2 )
+ {
+ for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ )
+ if ( pSim1[k] & pSim2[k] )
+ return 0;
+ }
+ else if ( fCompl1 )
+ {
+ for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ )
+ if ( pSim1[k] & ~pSim2[k] )
+ return 0;
+ }
+ else if ( fCompl2 )
+ {
+ for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ )
+ if ( ~pSim1[k] & pSim2[k] )
+ return 0;
+ }
+ else
+ assert( 0 );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes one-hot implications.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Fra_OneHotCompute( Fra_Man_t * p, Fra_Sml_t * pSim )
+{
+ int fSkipConstEqu = 1;
+ Vec_Int_t * vOneHots;
+ Aig_Obj_t * pObj1, * pObj2;
+ int i, k;
+ int nTruePis = Aig_ManPiNum(pSim->pAig) - Aig_ManRegNum(pSim->pAig);
+ assert( pSim->pAig == p->pManAig );
+ vOneHots = Vec_IntAlloc( 100 );
+ Aig_ManForEachLoSeq( pSim->pAig, pObj1, i )
+ {
+ if ( fSkipConstEqu && Fra_OneHotNodeIsConst(pSim, pObj1) )
+ continue;
+ assert( i-nTruePis >= 0 );
+// Aig_ManForEachLoSeq( pSim->pAig, pObj2, k )
+// Vec_PtrForEachEntryStart( Aig_Obj_t *, pSim->pAig->vPis, pObj2, k, Aig_ManPiNum(p)-Aig_ManRegNum(p) )
+ Vec_PtrForEachEntryStart( Aig_Obj_t *, pSim->pAig->vPis, pObj2, k, i+1 )
+ {
+ if ( fSkipConstEqu && Fra_OneHotNodeIsConst(pSim, pObj2) )
+ continue;
+ if ( fSkipConstEqu && Fra_OneHotNodesAreEqual( pSim, pObj1, pObj2 ) )
+ continue;
+ assert( k-nTruePis >= 0 );
+ if ( Fra_OneHotNodesAreClause( pSim, pObj1, pObj2, 1, 1 ) )
+ {
+ Vec_IntPush( vOneHots, Fra_RegToLit(i-nTruePis, 1) );
+ Vec_IntPush( vOneHots, Fra_RegToLit(k-nTruePis, 1) );
+ continue;
+ }
+ if ( Fra_OneHotNodesAreClause( pSim, pObj1, pObj2, 0, 1 ) )
+ {
+ Vec_IntPush( vOneHots, Fra_RegToLit(i-nTruePis, 0) );
+ Vec_IntPush( vOneHots, Fra_RegToLit(k-nTruePis, 1) );
+ continue;
+ }
+ if ( Fra_OneHotNodesAreClause( pSim, pObj1, pObj2, 1, 0 ) )
+ {
+ Vec_IntPush( vOneHots, Fra_RegToLit(i-nTruePis, 1) );
+ Vec_IntPush( vOneHots, Fra_RegToLit(k-nTruePis, 0) );
+ continue;
+ }
+ }
+ }
+ return vOneHots;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Assumes one-hot implications in the SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+**********************************************************************/
+void Fra_OneHotAssume( Fra_Man_t * p, Vec_Int_t * vOneHots )
+{
+ Aig_Obj_t * pObj1, * pObj2;
+ int i, Out1, Out2, pLits[2];
+ int nPiNum = Aig_ManPiNum(p->pManFraig) - Aig_ManRegNum(p->pManFraig);
+ assert( p->pPars->nFramesK == 1 ); // add to only one frame
+ for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 )
+ {
+ Out1 = Vec_IntEntry( vOneHots, i );
+ Out2 = Vec_IntEntry( vOneHots, i+1 );
+ if ( Out1 == 0 && Out2 == 0 )
+ continue;
+ pObj1 = Aig_ManPi( p->pManFraig, nPiNum + Fra_LitReg(Out1) );
+ pObj2 = Aig_ManPi( p->pManFraig, nPiNum + Fra_LitReg(Out2) );
+ pLits[0] = toLitCond( Fra_ObjSatNum(pObj1), Fra_LitSign(Out1) );
+ pLits[1] = toLitCond( Fra_ObjSatNum(pObj2), Fra_LitSign(Out2) );
+ // add constraint to solver
+ if ( !sat_solver_addclause( p->pSat, pLits, pLits + 2 ) )
+ {
+ printf( "Fra_OneHotAssume(): Adding clause makes SAT solver unsat.\n" );
+ sat_solver_delete( p->pSat );
+ p->pSat = NULL;
+ return;
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks one-hot implications.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+**********************************************************************/
+void Fra_OneHotCheck( Fra_Man_t * p, Vec_Int_t * vOneHots )
+{
+ Aig_Obj_t * pObj1, * pObj2;
+ int RetValue, i, Out1, Out2;
+ int nTruePos = Aig_ManPoNum(p->pManFraig) - Aig_ManRegNum(p->pManFraig);
+ for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 )
+ {
+ Out1 = Vec_IntEntry( vOneHots, i );
+ Out2 = Vec_IntEntry( vOneHots, i+1 );
+ if ( Out1 == 0 && Out2 == 0 )
+ continue;
+ pObj1 = Aig_ManPo( p->pManFraig, nTruePos + Fra_LitReg(Out1) );
+ pObj2 = Aig_ManPo( p->pManFraig, nTruePos + Fra_LitReg(Out2) );
+ RetValue = Fra_NodesAreClause( p, pObj1, pObj2, Fra_LitSign(Out1), Fra_LitSign(Out2) );
+ if ( RetValue != 1 )
+ {
+ p->pCla->fRefinement = 1;
+ if ( RetValue == 0 )
+ Fra_SmlResimulate( p );
+ if ( Vec_IntEntry(vOneHots, i) != 0 )
+ printf( "Fra_OneHotCheck(): Clause is not refined!\n" );
+ assert( Vec_IntEntry(vOneHots, i) == 0 );
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes those implications that no longer hold.]
+
+ Description [Returns 1 if refinement has happened.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_OneHotRefineUsingCex( Fra_Man_t * p, Vec_Int_t * vOneHots )
+{
+ Aig_Obj_t * pObj1, * pObj2;
+ int i, Out1, Out2, RetValue = 0;
+ int nPiNum = Aig_ManPiNum(p->pManAig) - Aig_ManRegNum(p->pManAig);
+ assert( p->pSml->pAig == p->pManAig );
+ for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 )
+ {
+ Out1 = Vec_IntEntry( vOneHots, i );
+ Out2 = Vec_IntEntry( vOneHots, i+1 );
+ if ( Out1 == 0 && Out2 == 0 )
+ continue;
+ // get the corresponding nodes
+ pObj1 = Aig_ManPi( p->pManAig, nPiNum + Fra_LitReg(Out1) );
+ pObj2 = Aig_ManPi( p->pManAig, nPiNum + Fra_LitReg(Out2) );
+ // check if implication holds using this simulation info
+ if ( !Fra_OneHotNodesAreClause( p->pSml, pObj1, pObj2, Fra_LitSign(Out1), Fra_LitSign(Out2) ) )
+ {
+ Vec_IntWriteEntry( vOneHots, i, 0 );
+ Vec_IntWriteEntry( vOneHots, i+1, 0 );
+ RetValue = 1;
+ }
+ }
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes those implications that no longer hold.]
+
+ Description [Returns 1 if refinement has happened.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_OneHotCount( Fra_Man_t * p, Vec_Int_t * vOneHots )
+{
+ int i, Out1, Out2, Counter = 0;
+ for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 )
+ {
+ Out1 = Vec_IntEntry( vOneHots, i );
+ Out2 = Vec_IntEntry( vOneHots, i+1 );
+ if ( Out1 == 0 && Out2 == 0 )
+ continue;
+ Counter++;
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Estimates the coverage of state space by clauses.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_OneHotEstimateCoverage( Fra_Man_t * p, Vec_Int_t * vOneHots )
+{
+ int nSimWords = (1<<14);
+ int nRegs = Aig_ManRegNum(p->pManAig);
+ Vec_Ptr_t * vSimInfo;
+ unsigned * pSim1, * pSim2, * pSimTot;
+ int i, w, Out1, Out2, nCovered, Counter = 0;
+ int clk = clock();
+
+ // generate random sim-info at register outputs
+ vSimInfo = Vec_PtrAllocSimInfo( nRegs + 1, nSimWords );
+// srand( 0xAABBAABB );
+ Aig_ManRandom(1);
+ for ( i = 0; i < nRegs; i++ )
+ {
+ pSim1 = (unsigned *)Vec_PtrEntry( vSimInfo, i );
+ for ( w = 0; w < nSimWords; w++ )
+ pSim1[w] = Fra_ObjRandomSim();
+ }
+ pSimTot = (unsigned *)Vec_PtrEntry( vSimInfo, nRegs );
+
+ // collect simulation info
+ memset( pSimTot, 0, sizeof(unsigned) * nSimWords );
+ for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 )
+ {
+ Out1 = Vec_IntEntry( vOneHots, i );
+ Out2 = Vec_IntEntry( vOneHots, i+1 );
+ if ( Out1 == 0 && Out2 == 0 )
+ continue;
+//printf( "(%c%d,%c%d) ",
+//Fra_LitSign(Out1)? '-': '+', Fra_LitReg(Out1),
+//Fra_LitSign(Out2)? '-': '+', Fra_LitReg(Out2) );
+ Counter++;
+ pSim1 = (unsigned *)Vec_PtrEntry( vSimInfo, Fra_LitReg(Out1) );
+ pSim2 = (unsigned *)Vec_PtrEntry( vSimInfo, Fra_LitReg(Out2) );
+ if ( Fra_LitSign(Out1) && Fra_LitSign(Out2) )
+ for ( w = 0; w < nSimWords; w++ )
+ pSimTot[w] |= pSim1[w] & pSim2[w];
+ else if ( Fra_LitSign(Out1) )
+ for ( w = 0; w < nSimWords; w++ )
+ pSimTot[w] |= pSim1[w] & ~pSim2[w];
+ else if ( Fra_LitSign(Out2) )
+ for ( w = 0; w < nSimWords; w++ )
+ pSimTot[w] |= ~pSim1[w] & pSim2[w];
+ else
+ assert( 0 );
+ }
+//printf( "\n" );
+ // count the total number of patterns contained in the don't-care
+ nCovered = 0;
+ for ( w = 0; w < nSimWords; w++ )
+ nCovered += Aig_WordCountOnes( pSimTot[w] );
+ Vec_PtrFree( vSimInfo );
+ // print the result
+ printf( "Care states ratio = %f. ", 1.0 * (nSimWords * 32 - nCovered) / (nSimWords * 32) );
+ printf( "(%d out of %d patterns) ", nSimWords * 32 - nCovered, nSimWords * 32 );
+ ABC_PRT( "Time", clock() - clk );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates one-hotness EXDC.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Fra_OneHotCreateExdc( Fra_Man_t * p, Vec_Int_t * vOneHots )
+{
+ Aig_Man_t * pNew;
+ Aig_Obj_t * pObj1, * pObj2, * pObj;
+ int i, Out1, Out2, nTruePis;
+ pNew = Aig_ManStart( Vec_IntSize(vOneHots)/2 );
+// for ( i = 0; i < Aig_ManRegNum(p->pManAig); i++ )
+// Aig_ObjCreatePi(pNew);
+ Aig_ManForEachPi( p->pManAig, pObj, i )
+ Aig_ObjCreatePi(pNew);
+ nTruePis = Aig_ManPiNum(p->pManAig) - Aig_ManRegNum(p->pManAig);
+ for ( i = 0; i < Vec_IntSize(vOneHots); i += 2 )
+ {
+ Out1 = Vec_IntEntry( vOneHots, i );
+ Out2 = Vec_IntEntry( vOneHots, i+1 );
+ if ( Out1 == 0 && Out2 == 0 )
+ continue;
+ pObj1 = Aig_ManPi( pNew, nTruePis + Fra_LitReg(Out1) );
+ pObj2 = Aig_ManPi( pNew, nTruePis + Fra_LitReg(Out2) );
+ pObj1 = Aig_NotCond( pObj1, Fra_LitSign(Out1) );
+ pObj2 = Aig_NotCond( pObj2, Fra_LitSign(Out2) );
+ pObj = Aig_Or( pNew, pObj1, pObj2 );
+ Aig_ObjCreatePo( pNew, pObj );
+ }
+ Aig_ManCleanup(pNew);
+// printf( "Created AIG with %d nodes and %d outputs.\n", Aig_ManNodeNum(pNew), Aig_ManPoNum(pNew) );
+ return pNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Assumes one-hot implications in the SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+**********************************************************************/
+void Fra_OneHotAddKnownConstraint( Fra_Man_t * p, Vec_Ptr_t * vOnehots )
+{
+ Vec_Int_t * vGroup;
+ Aig_Obj_t * pObj1, * pObj2;
+ int k, i, j, Out1, Out2, pLits[2];
+ //
+ // these constrants should be added to different timeframes!
+ // (also note that PIs follow first - then registers)
+ //
+ Vec_PtrForEachEntry( Vec_Int_t *, vOnehots, vGroup, k )
+ {
+ Vec_IntForEachEntry( vGroup, Out1, i )
+ Vec_IntForEachEntryStart( vGroup, Out2, j, i+1 )
+ {
+ pObj1 = Aig_ManPi( p->pManFraig, Out1 );
+ pObj2 = Aig_ManPi( p->pManFraig, Out2 );
+ pLits[0] = toLitCond( Fra_ObjSatNum(pObj1), 1 );
+ pLits[1] = toLitCond( Fra_ObjSatNum(pObj2), 1 );
+ // add constraint to solver
+ if ( !sat_solver_addclause( p->pSat, pLits, pLits + 2 ) )
+ {
+ printf( "Fra_OneHotAddKnownConstraint(): Adding clause makes SAT solver unsat.\n" );
+ sat_solver_delete( p->pSat );
+ p->pSat = NULL;
+ return;
+ }
+ }
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fra/fraImp.c b/src/proof/fra/fraImp.c
new file mode 100644
index 00000000..9877ceaa
--- /dev/null
+++ b/src/proof/fra/fraImp.c
@@ -0,0 +1,731 @@
+/**CFile****************************************************************
+
+ FileName [fraImp.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [New FRAIG package.]
+
+ Synopsis [Detecting and proving implications.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 30, 2007.]
+
+ Revision [$Id: fraImp.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of 1s in each siminfo of each node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Fra_SmlCountOnesOne( Fra_Sml_t * p, int Node )
+{
+ unsigned * pSim;
+ int k, Counter = 0;
+ pSim = Fra_ObjSim( p, Node );
+ for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
+ Counter += Aig_WordCountOnes( pSim[k] );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of 1s in each siminfo of each node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int * Fra_SmlCountOnes( Fra_Sml_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i, * pnBits;
+ pnBits = ABC_ALLOC( int, Aig_ManObjNumMax(p->pAig) );
+ memset( pnBits, 0, sizeof(int) * Aig_ManObjNumMax(p->pAig) );
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ pnBits[i] = Fra_SmlCountOnesOne( p, i );
+ return pnBits;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if implications holds.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Sml_NodeCheckImp( Fra_Sml_t * p, int Left, int Right )
+{
+ unsigned * pSimL, * pSimR;
+ int k;
+ pSimL = Fra_ObjSim( p, Left );
+ pSimR = Fra_ObjSim( p, Right );
+ for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
+ if ( pSimL[k] & ~pSimR[k] )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of 1s in the complement of the implication.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Sml_NodeNotImpWeight( Fra_Sml_t * p, int Left, int Right )
+{
+ unsigned * pSimL, * pSimR;
+ int k, Counter = 0;
+ pSimL = Fra_ObjSim( p, Left );
+ pSimR = Fra_ObjSim( p, Right );
+ for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
+ Counter += Aig_WordCountOnes( pSimL[k] & ~pSimR[k] );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the complement of the implication.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Sml_NodeSaveNotImpPatterns( Fra_Sml_t * p, int Left, int Right, unsigned * pResult )
+{
+ unsigned * pSimL, * pSimR;
+ int k;
+ pSimL = Fra_ObjSim( p, Left );
+ pSimR = Fra_ObjSim( p, Right );
+ for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
+ pResult[k] |= pSimL[k] & ~pSimR[k];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of nodes sorted by the number of 1s.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Fra_SmlSortUsingOnes( Fra_Sml_t * p, int fLatchCorr )
+{
+ Aig_Obj_t * pObj;
+ Vec_Ptr_t * vNodes;
+ int i, nNodes, nTotal, nBits, * pnNodes, * pnBits, * pMemory;
+ assert( p->nWordsTotal > 0 );
+ // count 1s in each node's siminfo
+ pnBits = Fra_SmlCountOnes( p );
+ // count number of nodes having that many 1s
+ nNodes = 0;
+ nBits = p->nWordsTotal * 32;
+ pnNodes = ABC_ALLOC( int, nBits + 1 );
+ memset( pnNodes, 0, sizeof(int) * (nBits + 1) );
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ {
+ if ( i == 0 ) continue;
+ // skip non-PI and non-internal nodes
+ if ( fLatchCorr )
+ {
+ if ( !Aig_ObjIsPi(pObj) )
+ continue;
+ }
+ else
+ {
+ if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) )
+ continue;
+ }
+ // skip nodes participating in the classes
+// if ( Fra_ClassObjRepr(pObj) )
+// continue;
+ assert( pnBits[i] <= nBits ); // "<" because of normalized info
+ pnNodes[pnBits[i]]++;
+ nNodes++;
+ }
+ // allocate memory for all the nodes
+ pMemory = ABC_ALLOC( int, nNodes + nBits + 1 );
+ // markup the memory for each node
+ vNodes = Vec_PtrAlloc( nBits + 1 );
+ Vec_PtrPush( vNodes, pMemory );
+ for ( i = 1; i <= nBits; i++ )
+ {
+ pMemory += pnNodes[i-1] + 1;
+ Vec_PtrPush( vNodes, pMemory );
+ }
+ // add the nodes
+ memset( pnNodes, 0, sizeof(int) * (nBits + 1) );
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ {
+ if ( i == 0 ) continue;
+ // skip non-PI and non-internal nodes
+ if ( fLatchCorr )
+ {
+ if ( !Aig_ObjIsPi(pObj) )
+ continue;
+ }
+ else
+ {
+ if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) )
+ continue;
+ }
+ // skip nodes participating in the classes
+// if ( Fra_ClassObjRepr(pObj) )
+// continue;
+ pMemory = (int *)Vec_PtrEntry( vNodes, pnBits[i] );
+ pMemory[ pnNodes[pnBits[i]]++ ] = i;
+ }
+ // add 0s in the end
+ nTotal = 0;
+ Vec_PtrForEachEntry( int *, vNodes, pMemory, i )
+ {
+ pMemory[ pnNodes[i]++ ] = 0;
+ nTotal += pnNodes[i];
+ }
+ assert( nTotal == nNodes + nBits + 1 );
+ ABC_FREE( pnNodes );
+ ABC_FREE( pnBits );
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of implications with the highest cost.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Fra_SmlSelectMaxCost( Vec_Int_t * vImps, int * pCosts, int nCostMax, int nImpLimit, int * pCostRange )
+{
+ Vec_Int_t * vImpsNew;
+ int * pCostCount, nImpCount, Imp, i, c;
+ assert( Vec_IntSize(vImps) >= nImpLimit );
+ // count how many implications have each cost
+ pCostCount = ABC_ALLOC( int, nCostMax + 1 );
+ memset( pCostCount, 0, sizeof(int) * (nCostMax + 1) );
+ for ( i = 0; i < Vec_IntSize(vImps); i++ )
+ {
+ assert( pCosts[i] <= nCostMax );
+ pCostCount[ pCosts[i] ]++;
+ }
+ assert( pCostCount[0] == 0 );
+ // select the bound on the cost (above this bound, implication will be included)
+ nImpCount = 0;
+ for ( c = nCostMax; c > 0; c-- )
+ {
+ nImpCount += pCostCount[c];
+ if ( nImpCount >= nImpLimit )
+ break;
+ }
+// printf( "Cost range >= %d.\n", c );
+ // collect implications with the given costs
+ vImpsNew = Vec_IntAlloc( nImpLimit );
+ Vec_IntForEachEntry( vImps, Imp, i )
+ {
+ if ( pCosts[i] < c )
+ continue;
+ Vec_IntPush( vImpsNew, Imp );
+ if ( Vec_IntSize( vImpsNew ) == nImpLimit )
+ break;
+ }
+ ABC_FREE( pCostCount );
+ if ( pCostRange )
+ *pCostRange = c;
+ return vImpsNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares two implications using their largest ID.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Sml_CompareMaxId( unsigned short * pImp1, unsigned short * pImp2 )
+{
+ int Max1 = Abc_MaxInt( pImp1[0], pImp1[1] );
+ int Max2 = Abc_MaxInt( pImp2[0], pImp2[1] );
+ if ( Max1 < Max2 )
+ return -1;
+ if ( Max1 > Max2 )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives implication candidates.]
+
+ Description [Implication candidates have the property that
+ (1) they hold using sequential simulation information
+ (2) they do not hold using combinational simulation information
+ (3) they have as high expressive power as possible (heuristically)
+ that is, they are easy to disprove combinationally
+ meaning they cover relatively larger sequential subspace.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Fra_ImpDerive( Fra_Man_t * p, int nImpMaxLimit, int nImpUseLimit, int fLatchCorr )
+{
+ int nSimWords = 64;
+ Fra_Sml_t * pSeq, * pComb;
+ Vec_Int_t * vImps, * vTemp;
+ Vec_Ptr_t * vNodes;
+ int * pImpCosts, * pNodesI, * pNodesK;
+ int nImpsTotal = 0, nImpsTried = 0, nImpsNonSeq = 0, nImpsComb = 0, nImpsCollected = 0;
+ int CostMin = ABC_INFINITY, CostMax = 0;
+ int i, k, Imp, CostRange, clk = clock();
+ assert( Aig_ManObjNumMax(p->pManAig) < (1 << 15) );
+ assert( nImpMaxLimit > 0 && nImpUseLimit > 0 && nImpUseLimit <= nImpMaxLimit );
+ // normalize both managers
+ pComb = Fra_SmlSimulateComb( p->pManAig, nSimWords );
+ pSeq = Fra_SmlSimulateSeq( p->pManAig, p->pPars->nFramesP, nSimWords, 1, 1 );
+ // get the nodes sorted by the number of 1s
+ vNodes = Fra_SmlSortUsingOnes( pSeq, fLatchCorr );
+ // count the total number of implications
+ for ( k = nSimWords * 32; k > 0; k-- )
+ for ( i = k - 1; i > 0; i-- )
+ for ( pNodesI = (int *)Vec_PtrEntry( vNodes, i ); *pNodesI; pNodesI++ )
+ for ( pNodesK = (int *)Vec_PtrEntry( vNodes, k ); *pNodesK; pNodesK++ )
+ nImpsTotal++;
+
+ // compute implications and their costs
+ pImpCosts = ABC_ALLOC( int, nImpMaxLimit );
+ vImps = Vec_IntAlloc( nImpMaxLimit );
+ for ( k = pSeq->nWordsTotal * 32; k > 0; k-- )
+ for ( i = k - 1; i > 0; i-- )
+ {
+ // HERE WE ARE MISSING SOME POTENTIAL IMPLICATIONS (with complement!)
+
+ for ( pNodesI = (int *)Vec_PtrEntry( vNodes, i ); *pNodesI; pNodesI++ )
+ for ( pNodesK = (int *)Vec_PtrEntry( vNodes, k ); *pNodesK; pNodesK++ )
+ {
+ nImpsTried++;
+ if ( !Sml_NodeCheckImp(pSeq, *pNodesI, *pNodesK) )
+ {
+ nImpsNonSeq++;
+ continue;
+ }
+ if ( Sml_NodeCheckImp(pComb, *pNodesI, *pNodesK) )
+ {
+ nImpsComb++;
+ continue;
+ }
+ nImpsCollected++;
+ Imp = Fra_ImpCreate( *pNodesI, *pNodesK );
+ pImpCosts[ Vec_IntSize(vImps) ] = Sml_NodeNotImpWeight(pComb, *pNodesI, *pNodesK);
+ CostMin = Abc_MinInt( CostMin, pImpCosts[ Vec_IntSize(vImps) ] );
+ CostMax = Abc_MaxInt( CostMax, pImpCosts[ Vec_IntSize(vImps) ] );
+ Vec_IntPush( vImps, Imp );
+ if ( Vec_IntSize(vImps) == nImpMaxLimit )
+ goto finish;
+ }
+ }
+finish:
+ Fra_SmlStop( pComb );
+ Fra_SmlStop( pSeq );
+
+ // select implications with the highest cost
+ CostRange = CostMin;
+ if ( Vec_IntSize(vImps) > nImpUseLimit )
+ {
+ vImps = Fra_SmlSelectMaxCost( vTemp = vImps, pImpCosts, nSimWords * 32, nImpUseLimit, &CostRange );
+ Vec_IntFree( vTemp );
+ }
+
+ // dealloc
+ ABC_FREE( pImpCosts );
+ {
+ void * pTemp = Vec_PtrEntry(vNodes, 0);
+ ABC_FREE( pTemp );
+ }
+ Vec_PtrFree( vNodes );
+ // reorder implications topologically
+ qsort( (void *)Vec_IntArray(vImps), Vec_IntSize(vImps), sizeof(int),
+ (int (*)(const void *, const void *)) Sml_CompareMaxId );
+if ( p->pPars->fVerbose )
+{
+printf( "Implications: All = %d. Try = %d. NonSeq = %d. Comb = %d. Res = %d.\n",
+ nImpsTotal, nImpsTried, nImpsNonSeq, nImpsComb, nImpsCollected );
+printf( "Implication weight: Min = %d. Pivot = %d. Max = %d. ",
+ CostMin, CostRange, CostMax );
+ABC_PRT( "Time", clock() - clk );
+}
+ return vImps;
+}
+
+
+// the following three procedures are called to
+// - add implications to the SAT solver
+// - check implications using the SAT solver
+// - refine implications using after a cex is generated
+
+/**Function*************************************************************
+
+ Synopsis [Add implication clauses to the SAT solver.]
+
+ Description [Note that implications should be checked in the first frame!]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ImpAddToSolver( Fra_Man_t * p, Vec_Int_t * vImps, int * pSatVarNums )
+{
+ sat_solver * pSat = p->pSat;
+ Aig_Obj_t * pLeft, * pRight;
+ Aig_Obj_t * pLeftF, * pRightF;
+ int pLits[2], Imp, Left, Right, i, f, status;
+ int fComplL, fComplR;
+ Vec_IntForEachEntry( vImps, Imp, i )
+ {
+ // get the corresponding nodes
+ pLeft = Aig_ManObj( p->pManAig, Fra_ImpLeft(Imp) );
+ pRight = Aig_ManObj( p->pManAig, Fra_ImpRight(Imp) );
+ // check if all the nodes are present
+ for ( f = 0; f < p->pPars->nFramesK; f++ )
+ {
+ // map these info fraig
+ pLeftF = Fra_ObjFraig( pLeft, f );
+ pRightF = Fra_ObjFraig( pRight, f );
+ if ( Aig_ObjIsNone(Aig_Regular(pLeftF)) || Aig_ObjIsNone(Aig_Regular(pRightF)) )
+ {
+ Vec_IntWriteEntry( vImps, i, 0 );
+ break;
+ }
+ }
+ if ( f < p->pPars->nFramesK )
+ continue;
+ // add constraints in each timeframe
+ for ( f = 0; f < p->pPars->nFramesK; f++ )
+ {
+ // map these info fraig
+ pLeftF = Fra_ObjFraig( pLeft, f );
+ pRightF = Fra_ObjFraig( pRight, f );
+ // get the corresponding SAT numbers
+ Left = pSatVarNums[ Aig_Regular(pLeftF)->Id ];
+ Right = pSatVarNums[ Aig_Regular(pRightF)->Id ];
+ assert( Left > 0 && Left < p->nSatVars );
+ assert( Right > 0 && Right < p->nSatVars );
+ // get the complemented attributes
+ fComplL = pLeft->fPhase ^ Aig_IsComplement(pLeftF);
+ fComplR = pRight->fPhase ^ Aig_IsComplement(pRightF);
+ // get the constraint
+ // L => R L' v R (complement = L & R')
+ pLits[0] = 2 * Left + !fComplL;
+ pLits[1] = 2 * Right + fComplR;
+ // add constraint to solver
+ if ( !sat_solver_addclause( pSat, pLits, pLits + 2 ) )
+ {
+ sat_solver_delete( pSat );
+ p->pSat = NULL;
+ return;
+ }
+ }
+ }
+ status = sat_solver_simplify(pSat);
+ if ( status == 0 )
+ {
+ sat_solver_delete( pSat );
+ p->pSat = NULL;
+ }
+// printf( "Total imps = %d. ", Vec_IntSize(vImps) );
+ Fra_ImpCompactArray( vImps );
+// printf( "Valid imps = %d. \n", Vec_IntSize(vImps) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Check implications for the node (if they are present).]
+
+ Description [Returns the new position in the array.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_ImpCheckForNode( Fra_Man_t * p, Vec_Int_t * vImps, Aig_Obj_t * pNode, int Pos )
+{
+ Aig_Obj_t * pLeft, * pRight;
+ Aig_Obj_t * pLeftF, * pRightF;
+ int i, Imp, Left, Right, Max, RetValue;
+ int fComplL, fComplR;
+ Vec_IntForEachEntryStart( vImps, Imp, i, Pos )
+ {
+ if ( Imp == 0 )
+ continue;
+ Left = Fra_ImpLeft(Imp);
+ Right = Fra_ImpRight(Imp);
+ Max = Abc_MaxInt( Left, Right );
+ assert( Max >= pNode->Id );
+ if ( Max > pNode->Id )
+ return i;
+ // get the corresponding nodes
+ pLeft = Aig_ManObj( p->pManAig, Left );
+ pRight = Aig_ManObj( p->pManAig, Right );
+ // get the corresponding FRAIG nodes
+ pLeftF = Fra_ObjFraig( pLeft, p->pPars->nFramesK );
+ pRightF = Fra_ObjFraig( pRight, p->pPars->nFramesK );
+ // get the complemented attributes
+ fComplL = pLeft->fPhase ^ Aig_IsComplement(pLeftF);
+ fComplR = pRight->fPhase ^ Aig_IsComplement(pRightF);
+ // check equality
+ if ( Aig_Regular(pLeftF) == Aig_Regular(pRightF) )
+ {
+ if ( fComplL == fComplR ) // x => x - always true
+ continue;
+ assert( fComplL != fComplR );
+ // consider 4 possibilities:
+ // NOT(1) => 1 or 0 => 1 - always true
+ // 1 => NOT(1) or 1 => 0 - never true
+ // NOT(x) => x or x - not always true
+ // x => NOT(x) or NOT(x) - not always true
+ if ( Aig_ObjIsConst1(Aig_Regular(pLeftF)) && fComplL ) // proved implication
+ continue;
+ // disproved implication
+ p->pCla->fRefinement = 1;
+ Vec_IntWriteEntry( vImps, i, 0 );
+ continue;
+ }
+ // check the implication
+ // - if true, a clause is added
+ // - if false, a cex is simulated
+ // make sure the implication is refined
+ RetValue = Fra_NodesAreImp( p, Aig_Regular(pLeftF), Aig_Regular(pRightF), fComplL, fComplR );
+ if ( RetValue != 1 )
+ {
+ p->pCla->fRefinement = 1;
+ if ( RetValue == 0 )
+ Fra_SmlResimulate( p );
+ if ( Vec_IntEntry(vImps, i) != 0 )
+ printf( "Fra_ImpCheckForNode(): Implication is not refined!\n" );
+ assert( Vec_IntEntry(vImps, i) == 0 );
+ }
+ }
+ return i;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes those implications that no longer hold.]
+
+ Description [Returns 1 if refinement has happened.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_ImpRefineUsingCex( Fra_Man_t * p, Vec_Int_t * vImps )
+{
+ Aig_Obj_t * pLeft, * pRight;
+ int Imp, i, RetValue = 0;
+ Vec_IntForEachEntry( vImps, Imp, i )
+ {
+ if ( Imp == 0 )
+ continue;
+ // get the corresponding nodes
+ pLeft = Aig_ManObj( p->pManAig, Fra_ImpLeft(Imp) );
+ pRight = Aig_ManObj( p->pManAig, Fra_ImpRight(Imp) );
+ // check if implication holds using this simulation info
+ if ( !Sml_NodeCheckImp(p->pSml, pLeft->Id, pRight->Id) )
+ {
+ Vec_IntWriteEntry( vImps, i, 0 );
+ RetValue = 1;
+ }
+ }
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes empty implications.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ImpCompactArray( Vec_Int_t * vImps )
+{
+ int i, k, Imp;
+ k = 0;
+ Vec_IntForEachEntry( vImps, Imp, i )
+ if ( Imp )
+ Vec_IntWriteEntry( vImps, k++, Imp );
+ Vec_IntShrink( vImps, k );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Determines the ratio of the state space by computed implications.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+double Fra_ImpComputeStateSpaceRatio( Fra_Man_t * p )
+{
+ int nSimWords = 64;
+ Fra_Sml_t * pComb;
+ unsigned * pResult;
+ double Ratio = 0.0;
+ int Left, Right, Imp, i;
+ if ( p->pCla->vImps == NULL || Vec_IntSize(p->pCla->vImps) == 0 )
+ return Ratio;
+ // simulate the AIG manager with combinational patterns
+ pComb = Fra_SmlSimulateComb( p->pManAig, nSimWords );
+ // go through the implications and collect where they do not hold
+ pResult = Fra_ObjSim( pComb, 0 );
+ assert( pResult[0] == 0 );
+ Vec_IntForEachEntry( p->pCla->vImps, Imp, i )
+ {
+ Left = Fra_ImpLeft(Imp);
+ Right = Fra_ImpRight(Imp);
+ Sml_NodeSaveNotImpPatterns( pComb, Left, Right, pResult );
+ }
+ // count the number of ones in this area
+ Ratio = 100.0 * Fra_SmlCountOnesOne( pComb, 0 ) / (32*(pComb->nWordsTotal-pComb->nWordsPref));
+ Fra_SmlStop( pComb );
+ return Ratio;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of failed implications.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_ImpVerifyUsingSimulation( Fra_Man_t * p )
+{
+ int nFrames = 2000;
+ int nSimWords = 8;
+ Fra_Sml_t * pSeq;
+ char * pfFails;
+ int Left, Right, Imp, i, Counter;
+ if ( p->pCla->vImps == NULL || Vec_IntSize(p->pCla->vImps) == 0 )
+ return 0;
+ // simulate the AIG manager with combinational patterns
+ pSeq = Fra_SmlSimulateSeq( p->pManAig, p->pPars->nFramesP, nFrames, nSimWords, 1 );
+ // go through the implications and check how many of them do not hold
+ pfFails = ABC_ALLOC( char, Vec_IntSize(p->pCla->vImps) );
+ memset( pfFails, 0, sizeof(char) * Vec_IntSize(p->pCla->vImps) );
+ Vec_IntForEachEntry( p->pCla->vImps, Imp, i )
+ {
+ Left = Fra_ImpLeft(Imp);
+ Right = Fra_ImpRight(Imp);
+ pfFails[i] = !Sml_NodeCheckImp( pSeq, Left, Right );
+ }
+ // count how many has failed
+ Counter = 0;
+ for ( i = 0; i < Vec_IntSize(p->pCla->vImps); i++ )
+ Counter += pfFails[i];
+ ABC_FREE( pfFails );
+ Fra_SmlStop( pSeq );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Record proven implications in the AIG manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ImpRecordInManager( Fra_Man_t * p, Aig_Man_t * pNew )
+{
+ Aig_Obj_t * pLeft, * pRight, * pMiter;
+ int nPosOld, Imp, i;
+ if ( p->pCla->vImps == NULL || Vec_IntSize(p->pCla->vImps) == 0 )
+ return;
+ // go through the implication
+ nPosOld = Aig_ManPoNum(pNew);
+ Vec_IntForEachEntry( p->pCla->vImps, Imp, i )
+ {
+ pLeft = Aig_ManObj( p->pManAig, Fra_ImpLeft(Imp) );
+ pRight = Aig_ManObj( p->pManAig, Fra_ImpRight(Imp) );
+ // record the implication: L' + R
+ pMiter = Aig_Or( pNew,
+ Aig_NotCond((Aig_Obj_t *)pLeft->pData, !pLeft->fPhase),
+ Aig_NotCond((Aig_Obj_t *)pRight->pData, pRight->fPhase) );
+ Aig_ObjCreatePo( pNew, pMiter );
+ }
+ pNew->nAsserts = Aig_ManPoNum(pNew) - nPosOld;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fra/fraInd.c b/src/proof/fra/fraInd.c
new file mode 100644
index 00000000..1224bab3
--- /dev/null
+++ b/src/proof/fra/fraInd.c
@@ -0,0 +1,709 @@
+/**CFile****************************************************************
+
+ FileName [fraInd.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [New FRAIG package.]
+
+ Synopsis [Inductive prover.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 30, 2007.]
+
+ Revision [$Id: fraInd.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+#include "src/sat/cnf/cnf.h"
+#include "src/opt/dar/dar.h"
+#include "src/aig/saig/saig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs AIG rewriting on the constraint manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_FraigInductionRewrite( Fra_Man_t * p )
+{
+ Aig_Man_t * pTemp;
+ Aig_Obj_t * pObj, * pObjPo;
+ int nTruePis, k, i, clk = clock();
+ // perform AIG rewriting on the speculated frames
+// pTemp = Dar_ManRwsat( pTemp, 1, 0 );
+ pTemp = Dar_ManRewriteDefault( p->pManFraig );
+// printf( "Before = %6d. After = %6d.\n", Aig_ManNodeNum(p->pManFraig), Aig_ManNodeNum(pTemp) );
+//Aig_ManDumpBlif( p->pManFraig, "1.blif", NULL, NULL );
+//Aig_ManDumpBlif( pTemp, "2.blif", NULL, NULL );
+// Fra_FramesWriteCone( pTemp );
+// Aig_ManStop( pTemp );
+ // transfer PI/register pointers
+ assert( p->pManFraig->nRegs == pTemp->nRegs );
+ assert( p->pManFraig->nAsserts == pTemp->nAsserts );
+ nTruePis = Aig_ManPiNum(p->pManAig) - Aig_ManRegNum(p->pManAig);
+ memset( p->pMemFraig, 0, sizeof(Aig_Obj_t *) * p->nSizeAlloc * p->nFramesAll );
+ Fra_ObjSetFraig( Aig_ManConst1(p->pManAig), p->pPars->nFramesK, Aig_ManConst1(pTemp) );
+ Aig_ManForEachPiSeq( p->pManAig, pObj, i )
+ Fra_ObjSetFraig( pObj, p->pPars->nFramesK, Aig_ManPi(pTemp,nTruePis*p->pPars->nFramesK+i) );
+ k = 0;
+ assert( Aig_ManRegNum(p->pManAig) == Aig_ManPoNum(pTemp) - pTemp->nAsserts );
+ Aig_ManForEachLoSeq( p->pManAig, pObj, i )
+ {
+ pObjPo = Aig_ManPo(pTemp, pTemp->nAsserts + k++);
+ Fra_ObjSetFraig( pObj, p->pPars->nFramesK, Aig_ObjChild0(pObjPo) );
+ }
+ // exchange
+ Aig_ManStop( p->pManFraig );
+ p->pManFraig = pTemp;
+p->timeRwr += clock() - clk;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs speculative reduction for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Fra_FramesConstrainNode( Aig_Man_t * pManFraig, Aig_Obj_t * pObj, int iFrame )
+{
+ Aig_Obj_t * pObjNew, * pObjNew2, * pObjRepr, * pObjReprNew, * pMiter;
+ // skip nodes without representative
+ if ( (pObjRepr = Fra_ClassObjRepr(pObj)) == NULL )
+ return;
+ assert( pObjRepr->Id < pObj->Id );
+ // get the new node
+ pObjNew = Fra_ObjFraig( pObj, iFrame );
+ // get the new node of the representative
+ pObjReprNew = Fra_ObjFraig( pObjRepr, iFrame );
+ // if this is the same node, no need to add constraints
+ if ( Aig_Regular(pObjNew) == Aig_Regular(pObjReprNew) )
+ return;
+ // these are different nodes - perform speculative reduction
+ pObjNew2 = Aig_NotCond( pObjReprNew, pObj->fPhase ^ pObjRepr->fPhase );
+ // set the new node
+ Fra_ObjSetFraig( pObj, iFrame, pObjNew2 );
+ // add the constraint
+ pMiter = Aig_Exor( pManFraig, pObjNew, pObjReprNew );
+ pMiter = Aig_NotCond( pMiter, !Aig_ObjPhaseReal(pMiter) );
+ assert( Aig_ObjPhaseReal(pMiter) == 1 );
+ Aig_ObjCreatePo( pManFraig, pMiter );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the inductive case with speculative reduction.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Fra_FramesWithClasses( Fra_Man_t * p )
+{
+ Aig_Man_t * pManFraig;
+ Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew;
+ int i, k, f;
+ assert( p->pManFraig == NULL );
+ assert( Aig_ManRegNum(p->pManAig) > 0 );
+ assert( Aig_ManRegNum(p->pManAig) < Aig_ManPiNum(p->pManAig) );
+
+ // start the fraig package
+ pManFraig = Aig_ManStart( Aig_ManObjNumMax(p->pManAig) * p->nFramesAll );
+ pManFraig->pName = Abc_UtilStrsav( p->pManAig->pName );
+ pManFraig->pSpec = Abc_UtilStrsav( p->pManAig->pSpec );
+ pManFraig->nRegs = p->pManAig->nRegs;
+ // create PI nodes for the frames
+ for ( f = 0; f < p->nFramesAll; f++ )
+ Fra_ObjSetFraig( Aig_ManConst1(p->pManAig), f, Aig_ManConst1(pManFraig) );
+ for ( f = 0; f < p->nFramesAll; f++ )
+ Aig_ManForEachPiSeq( p->pManAig, pObj, i )
+ Fra_ObjSetFraig( pObj, f, Aig_ObjCreatePi(pManFraig) );
+ // create latches for the first frame
+ Aig_ManForEachLoSeq( p->pManAig, pObj, i )
+ Fra_ObjSetFraig( pObj, 0, Aig_ObjCreatePi(pManFraig) );
+
+ // add timeframes
+// pManFraig->fAddStrash = 1;
+ for ( f = 0; f < p->nFramesAll - 1; f++ )
+ {
+ // set the constraints on the latch outputs
+ Aig_ManForEachLoSeq( p->pManAig, pObj, i )
+ Fra_FramesConstrainNode( pManFraig, pObj, f );
+ // add internal nodes of this frame
+ Aig_ManForEachNode( p->pManAig, pObj, i )
+ {
+ pObjNew = Aig_And( pManFraig, Fra_ObjChild0Fra(pObj,f), Fra_ObjChild1Fra(pObj,f) );
+ Fra_ObjSetFraig( pObj, f, pObjNew );
+ Fra_FramesConstrainNode( pManFraig, pObj, f );
+ }
+ // transfer latch input to the latch outputs
+ Aig_ManForEachLiLoSeq( p->pManAig, pObjLi, pObjLo, k )
+ Fra_ObjSetFraig( pObjLo, f+1, Fra_ObjChild0Fra(pObjLi,f) );
+ }
+// pManFraig->fAddStrash = 0;
+ // mark the asserts
+ pManFraig->nAsserts = Aig_ManPoNum(pManFraig);
+ // add the POs for the latch outputs of the last frame
+ Aig_ManForEachLoSeq( p->pManAig, pObj, i )
+ Aig_ObjCreatePo( pManFraig, Fra_ObjFraig(pObj,p->nFramesAll-1) );
+
+ // remove dangling nodes
+ Aig_ManCleanup( pManFraig );
+ // make sure the satisfying assignment is node assigned
+ assert( pManFraig->pData == NULL );
+ return pManFraig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the inductive case with speculative reduction.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_FramesAddMore( Aig_Man_t * p, int nFrames )
+{
+ Aig_Obj_t * pObj, ** pLatches;
+ int i, k, f, nNodesOld;
+ // set copy pointer of each object to point to itself
+ Aig_ManForEachObj( p, pObj, i )
+ pObj->pData = pObj;
+ // iterate and add objects
+ nNodesOld = Aig_ManObjNumMax(p);
+ pLatches = ABC_ALLOC( Aig_Obj_t *, Aig_ManRegNum(p) );
+ for ( f = 0; f < nFrames; f++ )
+ {
+ // clean latch inputs and outputs
+ Aig_ManForEachLiSeq( p, pObj, i )
+ pObj->pData = NULL;
+ Aig_ManForEachLoSeq( p, pObj, i )
+ pObj->pData = NULL;
+ // save the latch input values
+ k = 0;
+ Aig_ManForEachLiSeq( p, pObj, i )
+ {
+ if ( Aig_ObjFanin0(pObj)->pData )
+ pLatches[k++] = Aig_ObjChild0Copy(pObj);
+ else
+ pLatches[k++] = NULL;
+ }
+ // insert them as the latch output values
+ k = 0;
+ Aig_ManForEachLoSeq( p, pObj, i )
+ pObj->pData = pLatches[k++];
+ // create the next time frame of nodes
+ Aig_ManForEachNode( p, pObj, i )
+ {
+ if ( i > nNodesOld )
+ break;
+ if ( Aig_ObjFanin0(pObj)->pData && Aig_ObjFanin1(pObj)->pData )
+ pObj->pData = Aig_And( p, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+ else
+ pObj->pData = NULL;
+ }
+ }
+ ABC_FREE( pLatches );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs partitioned sequential SAT sweepingG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Fra_FraigInductionPart( Aig_Man_t * pAig, Fra_Ssw_t * pPars )
+{
+ int fPrintParts = 0;
+ char Buffer[100];
+ Aig_Man_t * pTemp, * pNew;
+ Vec_Ptr_t * vResult;
+ Vec_Int_t * vPart;
+ int * pMapBack;
+ int i, nCountPis, nCountRegs;
+ int nClasses, nPartSize, fVerbose;
+ int clk = clock();
+
+ // save parameters
+ nPartSize = pPars->nPartSize; pPars->nPartSize = 0;
+ fVerbose = pPars->fVerbose; pPars->fVerbose = 0;
+ // generate partitions
+ if ( pAig->vClockDoms )
+ {
+ // divide large clock domains into separate partitions
+ vResult = Vec_PtrAlloc( 100 );
+ Vec_PtrForEachEntry( Vec_Int_t *, (Vec_Ptr_t *)pAig->vClockDoms, vPart, i )
+ {
+ if ( nPartSize && Vec_IntSize(vPart) > nPartSize )
+ Aig_ManPartDivide( vResult, vPart, nPartSize, pPars->nOverSize );
+ else
+ Vec_PtrPush( vResult, Vec_IntDup(vPart) );
+ }
+ }
+ else
+ vResult = Aig_ManRegPartitionSimple( pAig, nPartSize, pPars->nOverSize );
+// vResult = Aig_ManPartitionSmartRegisters( pAig, nPartSize, 0 );
+// vResult = Aig_ManRegPartitionSmart( pAig, nPartSize );
+ if ( fPrintParts )
+ {
+ // print partitions
+ printf( "Simple partitioning. %d partitions are saved:\n", Vec_PtrSize(vResult) );
+ Vec_PtrForEachEntry( Vec_Int_t *, vResult, vPart, i )
+ {
+ sprintf( Buffer, "part%03d.aig", i );
+ pTemp = Aig_ManRegCreatePart( pAig, vPart, &nCountPis, &nCountRegs, NULL );
+ Ioa_WriteAiger( pTemp, Buffer, 0, 0 );
+ printf( "part%03d.aig : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d.\n",
+ i, Vec_IntSize(vPart), Aig_ManPiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Aig_ManNodeNum(pTemp) );
+ Aig_ManStop( pTemp );
+ }
+ }
+
+ // perform SSW with partitions
+ Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) );
+ Vec_PtrForEachEntry( Vec_Int_t *, vResult, vPart, i )
+ {
+ pTemp = Aig_ManRegCreatePart( pAig, vPart, &nCountPis, &nCountRegs, &pMapBack );
+ // create the projection of 1-hot registers
+ if ( pAig->vOnehots )
+ pTemp->vOnehots = Aig_ManRegProjectOnehots( pAig, pTemp, pAig->vOnehots, fVerbose );
+ // run SSW
+ pNew = Fra_FraigInduction( pTemp, pPars );
+ nClasses = Aig_TransferMappedClasses( pAig, pTemp, pMapBack );
+ if ( fVerbose )
+ printf( "%3d : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d. It = %3d. Cl = %5d.\n",
+ i, Vec_IntSize(vPart), Aig_ManPiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Aig_ManNodeNum(pTemp), pPars->nIters, nClasses );
+ Aig_ManStop( pNew );
+ Aig_ManStop( pTemp );
+ ABC_FREE( pMapBack );
+ }
+ // remap the AIG
+ pNew = Aig_ManDupRepr( pAig, 0 );
+ Aig_ManSeqCleanup( pNew );
+// Aig_ManPrintStats( pAig );
+// Aig_ManPrintStats( pNew );
+ Vec_VecFree( (Vec_Vec_t *)vResult );
+ pPars->nPartSize = nPartSize;
+ pPars->fVerbose = fVerbose;
+ if ( fVerbose )
+ {
+ ABC_PRT( "Total time", clock() - clk );
+ }
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs sequential SAT sweeping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Fra_FraigInduction( Aig_Man_t * pManAig, Fra_Ssw_t * pParams )
+{
+ int fUseSimpleCnf = 0;
+ int fUseOldSimulation = 0;
+ // other paramaters affecting performance
+ // - presence of FRAIGing in Abc_NtkDarSeqSweep()
+ // - using distance-1 patterns in Fra_SmlAssignDist1()
+ // - the number of simulation patterns
+ // - the number of BMC frames
+
+ Fra_Man_t * p;
+ Fra_Par_t Pars, * pPars = &Pars;
+ Aig_Obj_t * pObj;
+ Cnf_Dat_t * pCnf;
+ Aig_Man_t * pManAigNew = NULL;
+ int nNodesBeg, nRegsBeg;
+ int nIter = -1; // Suppress "might be used uninitialized"
+ int i, clk = clock(), clk2;
+ int TimeToStop = (pParams->TimeLimit == 0.0)? 0 : clock() + (int)(pParams->TimeLimit * CLOCKS_PER_SEC);
+
+ if ( Aig_ManNodeNum(pManAig) == 0 )
+ {
+ pParams->nIters = 0;
+ // Ntl_ManFinalize() needs the following to satisfy an assertion
+ Aig_ManReprStart(pManAig,Aig_ManObjNumMax(pManAig));
+ return Aig_ManDupOrdered(pManAig);
+ }
+ assert( Aig_ManRegNum(pManAig) > 0 );
+ assert( pParams->nFramesK > 0 );
+//Aig_ManShow( pManAig, 0, NULL );
+
+ if ( pParams->fWriteImps && pParams->nPartSize > 0 )
+ {
+ pParams->nPartSize = 0;
+ printf( "Partitioning was disabled to allow implication writing.\n" );
+ }
+ // perform partitioning
+ if ( (pParams->nPartSize > 0 && pParams->nPartSize < Aig_ManRegNum(pManAig))
+ || (pManAig->vClockDoms && Vec_VecSize(pManAig->vClockDoms) > 0) )
+ return Fra_FraigInductionPart( pManAig, pParams );
+
+ nNodesBeg = Aig_ManNodeNum(pManAig);
+ nRegsBeg = Aig_ManRegNum(pManAig);
+
+ // enhance the AIG by adding timeframes
+// Fra_FramesAddMore( pManAig, 3 );
+
+ // get parameters
+ Fra_ParamsDefaultSeq( pPars );
+ pPars->nFramesP = pParams->nFramesP;
+ pPars->nFramesK = pParams->nFramesK;
+ pPars->nMaxImps = pParams->nMaxImps;
+ pPars->nMaxLevs = pParams->nMaxLevs;
+ pPars->fVerbose = pParams->fVerbose;
+ pPars->fRewrite = pParams->fRewrite;
+ pPars->fLatchCorr = pParams->fLatchCorr;
+ pPars->fUseImps = pParams->fUseImps;
+ pPars->fWriteImps = pParams->fWriteImps;
+ pPars->fUse1Hot = pParams->fUse1Hot;
+
+ assert( !(pPars->nFramesP > 0 && pPars->fUse1Hot) );
+ assert( !(pPars->nFramesK > 1 && pPars->fUse1Hot) );
+
+ // start the fraig manager for this run
+ p = Fra_ManStart( pManAig, pPars );
+ p->pPars->nBTLimitNode = 0;
+ // derive and refine e-classes using K initialized frames
+ if ( fUseOldSimulation )
+ {
+ if ( pPars->nFramesP > 0 )
+ {
+ pPars->nFramesP = 0;
+ printf( "Fra_FraigInduction(): Prefix cannot be used.\n" );
+ }
+ p->pSml = Fra_SmlStart( pManAig, 0, pPars->nFramesK + 1, pPars->nSimWords );
+ Fra_SmlSimulate( p, 1 );
+ }
+ else
+ {
+ // bug: r iscas/blif/s5378.blif ; st; ssw -v
+ // bug: r iscas/blif/s1238.blif ; st; ssw -v
+ // refine the classes with more simulation rounds
+if ( pPars->fVerbose )
+printf( "Simulating %d AIG nodes for %d cycles ... ", Aig_ManNodeNum(pManAig), pPars->nFramesP + 32 );
+ p->pSml = Fra_SmlSimulateSeq( pManAig, pPars->nFramesP, 32, 1, 1 ); //pPars->nFramesK + 1, 1 );
+if ( pPars->fVerbose )
+{
+ABC_PRT( "Time", clock() - clk );
+}
+ Fra_ClassesPrepare( p->pCla, p->pPars->fLatchCorr, p->pPars->nMaxLevs );
+// Fra_ClassesPostprocess( p->pCla );
+ // compute one-hotness conditions
+ if ( p->pPars->fUse1Hot )
+ p->vOneHots = Fra_OneHotCompute( p, p->pSml );
+ // allocate new simulation manager for simulating counter-examples
+ Fra_SmlStop( p->pSml );
+ p->pSml = Fra_SmlStart( pManAig, 0, pPars->nFramesK + 1, pPars->nSimWords );
+ }
+
+ // select the most expressive implications
+ if ( pPars->fUseImps )
+ p->pCla->vImps = Fra_ImpDerive( p, 5000000, pPars->nMaxImps, pPars->fLatchCorr );
+
+ if ( pParams->TimeLimit != 0.0 && clock() > TimeToStop )
+ {
+ if ( !pParams->fSilent )
+ printf( "Fra_FraigInduction(): Runtime limit exceeded.\n" );
+ goto finish;
+ }
+
+ // perform BMC (for the min number of frames)
+ Fra_BmcPerform( p, pPars->nFramesP, pPars->nFramesK+1 ); // +1 is needed to prevent non-refinement
+//Fra_ClassesPrint( p->pCla, 1 );
+// if ( p->vCex == NULL )
+// p->vCex = Vec_IntAlloc( 1000 );
+
+ p->nLitsBeg = Fra_ClassesCountLits( p->pCla );
+ p->nNodesBeg = nNodesBeg; // Aig_ManNodeNum(pManAig);
+ p->nRegsBeg = nRegsBeg; // Aig_ManRegNum(pManAig);
+
+ // dump AIG of the timeframes
+// pManAigNew = Fra_ClassesDeriveAig( p->pCla, pPars->nFramesK );
+// Aig_ManDumpBlif( pManAigNew, "frame_aig.blif", NULL, NULL );
+// Fra_ManPartitionTest2( pManAigNew );
+// Aig_ManStop( pManAigNew );
+
+ // iterate the inductive case
+ p->pCla->fRefinement = 1;
+ for ( nIter = 0; p->pCla->fRefinement; nIter++ )
+ {
+ int nLitsOld = Fra_ClassesCountLits(p->pCla);
+ int nImpsOld = p->pCla->vImps? Vec_IntSize(p->pCla->vImps) : 0;
+ int nHotsOld = p->vOneHots? Fra_OneHotCount(p, p->vOneHots) : 0;
+ int clk3 = clock();
+
+ if ( pParams->TimeLimit != 0.0 && clock() > TimeToStop )
+ {
+ if ( !pParams->fSilent )
+ printf( "Fra_FraigInduction(): Runtime limit exceeded.\n" );
+ goto finish;
+ }
+
+ // mark the classes as non-refined
+ p->pCla->fRefinement = 0;
+ // derive non-init K-timeframes while implementing e-classes
+clk2 = clock();
+ p->pManFraig = Fra_FramesWithClasses( p );
+p->timeTrav += clock() - clk2;
+//Aig_ManDumpBlif( p->pManFraig, "testaig.blif", NULL, NULL );
+
+ // perform AIG rewriting
+ if ( p->pPars->fRewrite )
+ Fra_FraigInductionRewrite( p );
+
+ // convert the manager to SAT solver (the last nLatches outputs are inputs)
+ if ( fUseSimpleCnf || pPars->fUseImps )
+ pCnf = Cnf_DeriveSimple( p->pManFraig, Aig_ManRegNum(p->pManFraig) );
+ else
+ pCnf = Cnf_Derive( p->pManFraig, Aig_ManRegNum(p->pManFraig) );
+// Cnf_DataTranformPolarity( pCnf, 0 );
+//Cnf_DataWriteIntoFile( pCnf, "temp.cnf", 1 );
+
+ p->pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+ p->nSatVars = pCnf->nVars;
+ assert( p->pSat != NULL );
+ if ( p->pSat == NULL )
+ printf( "Fra_FraigInduction(): Computed CNF is not valid.\n" );
+ if ( pPars->fUseImps )
+ {
+ Fra_ImpAddToSolver( p, p->pCla->vImps, pCnf->pVarNums );
+ if ( p->pSat == NULL )
+ printf( "Fra_FraigInduction(): Adding implicationsn to CNF led to a conflict.\n" );
+ }
+
+ // set the pointers to the manager
+ Aig_ManForEachObj( p->pManFraig, pObj, i )
+ pObj->pData = p;
+
+ // prepare solver for fraiging the last timeframe
+ Fra_ManClean( p, Aig_ManObjNumMax(p->pManFraig) + Aig_ManNodeNum(p->pManAig) );
+
+ // transfer PI/LO variable numbers
+ Aig_ManForEachObj( p->pManFraig, pObj, i )
+ {
+ if ( pCnf->pVarNums[pObj->Id] == -1 )
+ continue;
+ Fra_ObjSetSatNum( pObj, pCnf->pVarNums[pObj->Id] );
+ Fra_ObjSetFaninVec( pObj, (Vec_Ptr_t *)1 );
+ }
+ Cnf_DataFree( pCnf );
+
+ // add one-hotness clauses
+ if ( p->pPars->fUse1Hot )
+ Fra_OneHotAssume( p, p->vOneHots );
+// if ( p->pManAig->vOnehots )
+// Fra_OneHotAddKnownConstraint( p, p->pManAig->vOnehots );
+
+ // report the intermediate results
+ if ( pPars->fVerbose )
+ {
+ printf( "%3d : C = %6d. Cl = %6d. L = %6d. LR = %6d. ",
+ nIter, Vec_PtrSize(p->pCla->vClasses1), Vec_PtrSize(p->pCla->vClasses),
+ Fra_ClassesCountLits(p->pCla), p->pManFraig->nAsserts );
+ if ( p->pCla->vImps )
+ printf( "I = %6d. ", Vec_IntSize(p->pCla->vImps) );
+ if ( p->pPars->fUse1Hot )
+ printf( "1h = %6d. ", Fra_OneHotCount(p, p->vOneHots) );
+ printf( "NR = %6d. ", Aig_ManNodeNum(p->pManFraig) );
+// printf( "\n" );
+ }
+
+ // perform sweeping
+ p->nSatCallsRecent = 0;
+ p->nSatCallsSkipped = 0;
+clk2 = clock();
+ if ( p->pPars->fUse1Hot )
+ Fra_OneHotCheck( p, p->vOneHots );
+ Fra_FraigSweep( p );
+ if ( pPars->fVerbose )
+ {
+ ABC_PRT( "T", clock() - clk3 );
+ }
+
+// Sat_SolverPrintStats( stdout, p->pSat );
+ // remove FRAIG and SAT solver
+ Aig_ManStop( p->pManFraig ); p->pManFraig = NULL;
+// printf( "Vars = %d. Clauses = %d. Learnts = %d.\n", p->pSat->size, p->pSat->clauses.size, p->pSat->learnts.size );
+ sat_solver_delete( p->pSat ); p->pSat = NULL;
+ memset( p->pMemFraig, 0, sizeof(Aig_Obj_t *) * p->nSizeAlloc * p->nFramesAll );
+// printf( "Recent SAT called = %d. Skipped = %d.\n", p->nSatCallsRecent, p->nSatCallsSkipped );
+ assert( p->vTimeouts == NULL );
+ if ( p->vTimeouts )
+ printf( "Fra_FraigInduction(): SAT solver timed out!\n" );
+ // check if refinement has happened
+// p->pCla->fRefinement = (int)(nLitsOld != Fra_ClassesCountLits(p->pCla));
+ if ( p->pCla->fRefinement &&
+ nLitsOld == Fra_ClassesCountLits(p->pCla) &&
+ nImpsOld == (p->pCla->vImps? Vec_IntSize(p->pCla->vImps) : 0) &&
+ nHotsOld == (p->vOneHots? Fra_OneHotCount(p, p->vOneHots) : 0) )
+ {
+ printf( "Fra_FraigInduction(): Internal error. The result may not verify.\n" );
+ break;
+ }
+ }
+/*
+ // verify implications using simulation
+ if ( p->pCla->vImps && Vec_IntSize(p->pCla->vImps) )
+ {
+ int Temp, clk = clock();
+ if ( Temp = Fra_ImpVerifyUsingSimulation( p ) )
+ printf( "Implications failing the simulation test = %d (out of %d). ", Temp, Vec_IntSize(p->pCla->vImps) );
+ else
+ printf( "All %d implications have passed the simulation test. ", Vec_IntSize(p->pCla->vImps) );
+ ABC_PRT( "Time", clock() - clk );
+ }
+*/
+
+ // move the classes into representatives and reduce AIG
+clk2 = clock();
+ if ( p->pPars->fWriteImps && p->vOneHots && Fra_OneHotCount(p, p->vOneHots) )
+ {
+ extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact );
+ Aig_Man_t * pNew;
+ char * pFileName = Ioa_FileNameGenericAppend( p->pManAig->pName, "_care.aig" );
+ printf( "Care one-hotness clauses will be written into file \"%s\".\n", pFileName );
+ pManAigNew = Aig_ManDupOrdered( pManAig );
+ pNew = Fra_OneHotCreateExdc( p, p->vOneHots );
+ Ioa_WriteAiger( pNew, pFileName, 0, 1 );
+ Aig_ManStop( pNew );
+ }
+ else
+ {
+ // Fra_ClassesPrint( p->pCla, 1 );
+ Fra_ClassesSelectRepr( p->pCla );
+ Fra_ClassesCopyReprs( p->pCla, p->vTimeouts );
+ pManAigNew = Aig_ManDupRepr( pManAig, 0 );
+ }
+ // add implications to the manager
+// if ( fWriteImps && p->pCla->vImps && Vec_IntSize(p->pCla->vImps) )
+// Fra_ImpRecordInManager( p, pManAigNew );
+ // cleanup the new manager
+ Aig_ManSeqCleanup( pManAigNew );
+ // remove pointers to the dead nodes
+// Aig_ManForEachObj( pManAig, pObj, i )
+// if ( pObj->pData && Aig_ObjIsNone(pObj->pData) )
+// pObj->pData = NULL;
+// Aig_ManCountMergeRegs( pManAigNew );
+p->timeTrav += clock() - clk2;
+p->timeTotal = clock() - clk;
+ // get the final stats
+ p->nLitsEnd = Fra_ClassesCountLits( p->pCla );
+ p->nNodesEnd = Aig_ManNodeNum(pManAigNew);
+ p->nRegsEnd = Aig_ManRegNum(pManAigNew);
+ // free the manager
+finish:
+ Fra_ManStop( p );
+ // check the output
+// if ( Aig_ManPoNum(pManAigNew) - Aig_ManRegNum(pManAigNew) == 1 )
+// if ( Aig_ObjChild0( Aig_ManPo(pManAigNew,0) ) == Aig_ManConst0(pManAigNew) )
+// printf( "Proved output constant 0.\n" );
+ pParams->nIters = nIter;
+ return pManAigNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Outputs a set of pairs of equivalent nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_FraigInductionTest( char * pFileName, Fra_Ssw_t * pParams )
+{
+ FILE * pFile;
+ char * pFilePairs;
+ Aig_Man_t * pMan, * pNew;
+ Aig_Obj_t * pObj, * pRepr;
+ int * pNum2Id;
+ int i, Counter = 0;
+ pMan = Saig_ManReadBlif( pFileName );
+ if ( pMan == NULL )
+ return 0;
+ // perform seq SAT sweeping
+ pNew = Fra_FraigInduction( pMan, pParams );
+ if ( pNew == NULL )
+ {
+ Aig_ManStop( pMan );
+ return 0;
+ }
+ if ( pParams->fVerbose )
+ {
+ printf( "Original AIG: " );
+ Aig_ManPrintStats( pMan );
+ printf( "Reduced AIG: " );
+ Aig_ManPrintStats( pNew );
+ }
+ Aig_ManStop( pNew );
+ pNum2Id = (int *)pMan->pData;
+ // write the output file
+ pFilePairs = Aig_FileNameGenericAppend( pFileName, ".pairs" );
+ pFile = fopen( pFilePairs, "w" );
+ Aig_ManForEachObj( pMan, pObj, i )
+ if ( (pRepr = pMan->pReprs[pObj->Id]) )
+ {
+ fprintf( pFile, "%d %d %c\n", pNum2Id[pObj->Id], pNum2Id[pRepr->Id], (Aig_ObjPhase(pObj) ^ Aig_ObjPhase(pRepr))? '-' : '+' );
+ Counter++;
+ }
+ fclose( pFile );
+ if ( pParams->fVerbose )
+ {
+ printf( "Result: %d pairs of seq equiv nodes are written into file \"%s\".\n", Counter, pFilePairs );
+ }
+ Aig_ManStop( pMan );
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fra/fraIndVer.c b/src/proof/fra/fraIndVer.c
new file mode 100644
index 00000000..64437607
--- /dev/null
+++ b/src/proof/fra/fraIndVer.c
@@ -0,0 +1,166 @@
+/**CFile****************************************************************
+
+ FileName [fraIndVer.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [New FRAIG package.]
+
+ Synopsis [Verification of the inductive invariant.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 30, 2007.]
+
+ Revision [$Id: fraIndVer.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+#include "src/sat/cnf/cnf.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Verifies the inductive invariant.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_InvariantVerify( Aig_Man_t * pAig, int nFrames, Vec_Int_t * vClauses, Vec_Int_t * vLits )
+{
+ Cnf_Dat_t * pCnf;
+ sat_solver * pSat;
+ int * pStart;
+ int RetValue, Beg, End, i, k;
+ int CounterBase = 0, CounterInd = 0;
+ int clk = clock();
+
+ if ( nFrames != 1 )
+ {
+ printf( "Invariant verification: Can only verify for K = 1\n" );
+ return 1;
+ }
+
+ // derive CNF
+ pCnf = Cnf_DeriveSimple( pAig, Aig_ManPoNum(pAig) );
+/*
+ // add the property
+ {
+ Aig_Obj_t * pObj;
+ int Lits[1];
+
+ pObj = Aig_ManPo( pAig, 0 );
+ Lits[0] = toLitCond( pCnf->pVarNums[pObj->Id], 1 );
+
+ Vec_IntPush( vLits, Lits[0] );
+ Vec_IntPush( vClauses, Vec_IntSize(vLits) );
+ printf( "Added the target property to the set of clauses to be inductively checked.\n" );
+ }
+*/
+ // derive initialized frames for the base case
+ pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, nFrames, 1 );
+ // check clauses in the base case
+ Beg = 0;
+ pStart = Vec_IntArray( vLits );
+ Vec_IntForEachEntry( vClauses, End, i )
+ {
+ // complement the literals
+ for ( k = Beg; k < End; k++ )
+ pStart[k] = lit_neg(pStart[k]);
+ RetValue = sat_solver_solve( pSat, pStart + Beg, pStart + End, 0, 0, 0, 0 );
+ for ( k = Beg; k < End; k++ )
+ pStart[k] = lit_neg(pStart[k]);
+ Beg = End;
+ if ( RetValue == l_False )
+ continue;
+// printf( "Clause %d failed the base case.\n", i );
+ CounterBase++;
+ }
+ sat_solver_delete( pSat );
+
+ // derive initialized frames for the base case
+ pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, nFrames + 1, 0 );
+ assert( pSat->size == 2 * pCnf->nVars );
+ // add clauses to the first frame
+ Beg = 0;
+ pStart = Vec_IntArray( vLits );
+ Vec_IntForEachEntry( vClauses, End, i )
+ {
+ RetValue = sat_solver_addclause( pSat, pStart + Beg, pStart + End );
+ Beg = End;
+ if ( RetValue == 0 )
+ {
+ Cnf_DataFree( pCnf );
+ sat_solver_delete( pSat );
+ printf( "Invariant verification: SAT solver is unsat after adding a clause.\n" );
+ return 0;
+ }
+ }
+ // simplify the solver
+ if ( pSat->qtail != pSat->qhead )
+ {
+ RetValue = sat_solver_simplify(pSat);
+ assert( RetValue != 0 );
+ assert( pSat->qtail == pSat->qhead );
+ }
+
+ // check clauses in the base case
+ Beg = 0;
+ pStart = Vec_IntArray( vLits );
+ Vec_IntForEachEntry( vClauses, End, i )
+ {
+ // complement the literals
+ for ( k = Beg; k < End; k++ )
+ {
+ pStart[k] += 2 * pCnf->nVars;
+ pStart[k] = lit_neg(pStart[k]);
+ }
+ RetValue = sat_solver_solve( pSat, pStart + Beg, pStart + End, 0, 0, 0, 0 );
+ for ( k = Beg; k < End; k++ )
+ {
+ pStart[k] = lit_neg(pStart[k]);
+ pStart[k] -= 2 * pCnf->nVars;
+ }
+ Beg = End;
+ if ( RetValue == l_False )
+ continue;
+// printf( "Clause %d failed the inductive case.\n", i );
+ CounterInd++;
+ }
+ sat_solver_delete( pSat );
+ Cnf_DataFree( pCnf );
+ if ( CounterBase )
+ printf( "Invariant verification: %d clauses (out of %d) FAILED the base case.\n", CounterBase, Vec_IntSize(vClauses) );
+ if ( CounterInd )
+ printf( "Invariant verification: %d clauses (out of %d) FAILED the inductive case.\n", CounterInd, Vec_IntSize(vClauses) );
+ if ( CounterBase || CounterInd )
+ return 0;
+ printf( "Invariant verification: %d clauses verified correctly. ", Vec_IntSize(vClauses) );
+ ABC_PRT( "Time", clock() - clk );
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fra/fraLcr.c b/src/proof/fra/fraLcr.c
new file mode 100644
index 00000000..b18a8fcd
--- /dev/null
+++ b/src/proof/fra/fraLcr.c
@@ -0,0 +1,709 @@
+/**CFile****************************************************************
+
+ FileName [fraLcorr.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [New FRAIG package.]
+
+ Synopsis [Latch correspondence computation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 30, 2007.]
+
+ Revision [$Id: fraLcorr.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Fra_Lcr_t_ Fra_Lcr_t;
+struct Fra_Lcr_t_
+{
+ // original AIG
+ Aig_Man_t * pAig;
+ // equivalence class representation
+ Fra_Cla_t * pCla;
+ // partitioning information
+ Vec_Ptr_t * vParts; // output partitions
+ int * pInToOutPart; // mapping of PI num into PO partition num
+ int * pInToOutNum; // mapping of PI num into the num of this PO in the partition
+ // AIGs for the partitions
+ Vec_Ptr_t * vFraigs;
+ // other variables
+ int fRefining;
+ // parameters
+ int nFramesP;
+ int fVerbose;
+ // statistics
+ int nIters;
+ int nLitsBeg;
+ int nLitsEnd;
+ int nNodesBeg;
+ int nNodesEnd;
+ int nRegsBeg;
+ int nRegsEnd;
+ // runtime
+ int timeSim;
+ int timePart;
+ int timeTrav;
+ int timeFraig;
+ int timeUpdate;
+ int timeTotal;
+};
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the retiming manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fra_Lcr_t * Lcr_ManAlloc( Aig_Man_t * pAig )
+{
+ Fra_Lcr_t * p;
+ p = ABC_ALLOC( Fra_Lcr_t, 1 );
+ memset( p, 0, sizeof(Fra_Lcr_t) );
+ p->pAig = pAig;
+ p->pInToOutPart = ABC_ALLOC( int, Aig_ManPiNum(pAig) );
+ memset( p->pInToOutPart, 0, sizeof(int) * Aig_ManPiNum(pAig) );
+ p->pInToOutNum = ABC_ALLOC( int, Aig_ManPiNum(pAig) );
+ memset( p->pInToOutNum, 0, sizeof(int) * Aig_ManPiNum(pAig) );
+ p->vFraigs = Vec_PtrAlloc( 1000 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints stats for the fraiging manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lcr_ManPrint( Fra_Lcr_t * p )
+{
+ printf( "Iterations = %d. LitBeg = %d. LitEnd = %d. (%6.2f %%).\n",
+ p->nIters, p->nLitsBeg, p->nLitsEnd, 100.0*p->nLitsEnd/p->nLitsBeg );
+ printf( "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n",
+ p->nNodesBeg, p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/p->nNodesBeg,
+ p->nRegsBeg, p->nRegsEnd, 100.0*(p->nRegsBeg-p->nRegsEnd)/p->nRegsBeg );
+ ABC_PRT( "AIG simulation ", p->timeSim );
+ ABC_PRT( "AIG partitioning", p->timePart );
+ ABC_PRT( "AIG rebuiding ", p->timeTrav );
+ ABC_PRT( "FRAIGing ", p->timeFraig );
+ ABC_PRT( "AIG updating ", p->timeUpdate );
+ ABC_PRT( "TOTAL RUNTIME ", p->timeTotal );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates the retiming manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Lcr_ManFree( Fra_Lcr_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ if ( p->fVerbose )
+ Lcr_ManPrint( p );
+ Aig_ManForEachPi( p->pAig, pObj, i )
+ pObj->pNext = NULL;
+ Vec_PtrFree( p->vFraigs );
+ if ( p->pCla ) Fra_ClassesStop( p->pCla );
+ if ( p->vParts ) Vec_VecFree( (Vec_Vec_t *)p->vParts );
+ ABC_FREE( p->pInToOutPart );
+ ABC_FREE( p->pInToOutNum );
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepare the AIG for class computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fra_Man_t * Fra_LcrAigPrepare( Aig_Man_t * pAig )
+{
+ Fra_Man_t * p;
+ Aig_Obj_t * pObj;
+ int i;
+ p = ABC_ALLOC( Fra_Man_t, 1 );
+ memset( p, 0, sizeof(Fra_Man_t) );
+// Aig_ManForEachPi( pAig, pObj, i )
+ Aig_ManForEachObj( pAig, pObj, i )
+ pObj->pData = p;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepare the AIG for class computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_LcrAigPrepareTwo( Aig_Man_t * pAig, Fra_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Aig_ManForEachPi( pAig, pObj, i )
+ pObj->pData = p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares two nodes for equivalence after partitioned fraiging.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_LcrNodesAreEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
+{
+ Fra_Man_t * pTemp = (Fra_Man_t *)pObj0->pData;
+ Fra_Lcr_t * pLcr = (Fra_Lcr_t *)pTemp->pBmc;
+ Aig_Man_t * pFraig;
+ Aig_Obj_t * pOut0, * pOut1;
+ int nPart0, nPart1;
+ assert( Aig_ObjIsPi(pObj0) );
+ assert( Aig_ObjIsPi(pObj1) );
+ // find the partition to which these nodes belong
+ nPart0 = pLcr->pInToOutPart[(long)pObj0->pNext];
+ nPart1 = pLcr->pInToOutPart[(long)pObj1->pNext];
+ // if this is the result of refinement of the class created const-1 nodes
+ // the nodes may end up in different partions - we assume them equivalent
+ if ( nPart0 != nPart1 )
+ {
+ assert( 0 );
+ return 1;
+ }
+ assert( nPart0 == nPart1 );
+ pFraig = (Aig_Man_t *)Vec_PtrEntry( pLcr->vFraigs, nPart0 );
+ // get the fraig outputs
+ pOut0 = Aig_ManPo( pFraig, pLcr->pInToOutNum[(long)pObj0->pNext] );
+ pOut1 = Aig_ManPo( pFraig, pLcr->pInToOutNum[(long)pObj1->pNext] );
+ return Aig_ObjFanin0(pOut0) == Aig_ObjFanin0(pOut1);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares the node with a constant after partioned fraiging.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_LcrNodeIsConst( Aig_Obj_t * pObj )
+{
+ Fra_Man_t * pTemp = (Fra_Man_t *)pObj->pData;
+ Fra_Lcr_t * pLcr = (Fra_Lcr_t *)pTemp->pBmc;
+ Aig_Man_t * pFraig;
+ Aig_Obj_t * pOut;
+ int nPart;
+ assert( Aig_ObjIsPi(pObj) );
+ // find the partition to which these nodes belong
+ nPart = pLcr->pInToOutPart[(long)pObj->pNext];
+ pFraig = (Aig_Man_t *)Vec_PtrEntry( pLcr->vFraigs, nPart );
+ // get the fraig outputs
+ pOut = Aig_ManPo( pFraig, pLcr->pInToOutNum[(long)pObj->pNext] );
+ return Aig_ObjFanin0(pOut) == Aig_ManConst1(pFraig);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates the AIG manager recursively.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Obj_t * Fra_LcrManDup_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+ Aig_Obj_t * pObjNew;
+ if ( pObj->pData )
+ return (Aig_Obj_t *)pObj->pData;
+ Fra_LcrManDup_rec( pNew, p, Aig_ObjFanin0(pObj) );
+ if ( Aig_ObjIsBuf(pObj) )
+ return (Aig_Obj_t *)(pObj->pData = Aig_ObjChild0Copy(pObj));
+ Fra_LcrManDup_rec( pNew, p, Aig_ObjFanin1(pObj) );
+ pObjNew = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) );
+ Aig_Regular(pObjNew)->pHaig = pObj->pHaig;
+ return (Aig_Obj_t *)(pObj->pData = pObjNew);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Give the AIG and classes, reduces AIG for partitioning.]
+
+ Description [Ignores registers that are not in the classes.
+ Places candidate equivalent classes of registers into single outputs
+ (for ease of partitioning). The resulting combinational AIG contains
+ outputs in the same order as equivalence classes of registers,
+ followed by constant-1 registers. Preserves the set of all inputs.
+ Complemented attributes of the outputs do not matter because we need
+ then only for collecting the structural info.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Fra_LcrDeriveAigForPartitioning( Fra_Lcr_t * pLcr )
+{
+ Aig_Man_t * pNew;
+ Aig_Obj_t * pObj, * pObjPo, * pObjNew, ** ppClass, * pMiter;
+ int i, c, Offset;
+ // remember the numbers of the inputs of the original AIG
+ Aig_ManForEachPi( pLcr->pAig, pObj, i )
+ {
+ pObj->pData = pLcr;
+ pObj->pNext = (Aig_Obj_t *)(long)i;
+ }
+ // compute the LO/LI offset
+ Offset = Aig_ManPoNum(pLcr->pAig) - Aig_ManPiNum(pLcr->pAig);
+ // create the PIs
+ Aig_ManCleanData( pLcr->pAig );
+ pNew = Aig_ManStartFrom( pLcr->pAig );
+ // go over the equivalence classes
+ Vec_PtrForEachEntry( Aig_Obj_t **, pLcr->pCla->vClasses, ppClass, i )
+ {
+ pMiter = Aig_ManConst0(pNew);
+ for ( c = 0; ppClass[c]; c++ )
+ {
+ assert( Aig_ObjIsPi(ppClass[c]) );
+ pObjPo = Aig_ManPo( pLcr->pAig, Offset+(long)ppClass[c]->pNext );
+ pObjNew = Fra_LcrManDup_rec( pNew, pLcr->pAig, Aig_ObjFanin0(pObjPo) );
+ pMiter = Aig_Exor( pNew, pMiter, pObjNew );
+ }
+ Aig_ObjCreatePo( pNew, pMiter );
+ }
+ // go over the constant candidates
+ Vec_PtrForEachEntry( Aig_Obj_t *, pLcr->pCla->vClasses1, pObj, i )
+ {
+ assert( Aig_ObjIsPi(pObj) );
+ pObjPo = Aig_ManPo( pLcr->pAig, Offset+(long)pObj->pNext );
+ pMiter = Fra_LcrManDup_rec( pNew, pLcr->pAig, Aig_ObjFanin0(pObjPo) );
+ Aig_ObjCreatePo( pNew, pMiter );
+ }
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Remaps partitions into the inputs of original AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_LcrRemapPartitions( Vec_Ptr_t * vParts, Fra_Cla_t * pCla, int * pInToOutPart, int * pInToOutNum )
+{
+ Vec_Int_t * vOne, * vOneNew;
+ Aig_Obj_t ** ppClass, * pObjPi;
+ int Out, Offset, i, k, c;
+ // compute the LO/LI offset
+ Offset = Aig_ManPoNum(pCla->pAig) - Aig_ManPiNum(pCla->pAig);
+ Vec_PtrForEachEntry( Vec_Int_t *, vParts, vOne, i )
+ {
+ vOneNew = Vec_IntAlloc( Vec_IntSize(vOne) );
+ Vec_IntForEachEntry( vOne, Out, k )
+ {
+ if ( Out < Vec_PtrSize(pCla->vClasses) )
+ {
+ ppClass = (Aig_Obj_t **)Vec_PtrEntry( pCla->vClasses, Out );
+ for ( c = 0; ppClass[c]; c++ )
+ {
+ pInToOutPart[(long)ppClass[c]->pNext] = i;
+ pInToOutNum[(long)ppClass[c]->pNext] = Vec_IntSize(vOneNew);
+ Vec_IntPush( vOneNew, Offset+(long)ppClass[c]->pNext );
+ }
+ }
+ else
+ {
+ pObjPi = (Aig_Obj_t *)Vec_PtrEntry( pCla->vClasses1, Out - Vec_PtrSize(pCla->vClasses) );
+ pInToOutPart[(long)pObjPi->pNext] = i;
+ pInToOutNum[(long)pObjPi->pNext] = Vec_IntSize(vOneNew);
+ Vec_IntPush( vOneNew, Offset+(long)pObjPi->pNext );
+ }
+ }
+ // replace the class
+ Vec_PtrWriteEntry( vParts, i, vOneNew );
+ Vec_IntFree( vOne );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates AIG of one partition with speculative reduction.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Obj_t * Fra_LcrCreatePart_rec( Fra_Cla_t * pCla, Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+ assert( !Aig_IsComplement(pObj) );
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ return (Aig_Obj_t *)pObj->pData;
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ if ( Aig_ObjIsPi(pObj) )
+ {
+// Aig_Obj_t * pRepr = Fra_ClassObjRepr(pObj);
+ Aig_Obj_t * pRepr = pCla->pMemRepr[pObj->Id];
+ if ( pRepr == NULL )
+ pObj->pData = Aig_ObjCreatePi( pNew );
+ else
+ {
+ pObj->pData = Fra_LcrCreatePart_rec( pCla, pNew, p, pRepr );
+ pObj->pData = Aig_NotCond( (Aig_Obj_t *)pObj->pData, pRepr->fPhase ^ pObj->fPhase );
+ }
+ return (Aig_Obj_t *)pObj->pData;
+ }
+ Fra_LcrCreatePart_rec( pCla, pNew, p, Aig_ObjFanin0(pObj) );
+ Fra_LcrCreatePart_rec( pCla, pNew, p, Aig_ObjFanin1(pObj) );
+ return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ));
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates AIG of one partition with speculative reduction.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Fra_LcrCreatePart( Fra_Lcr_t * p, Vec_Int_t * vPart )
+{
+ Aig_Man_t * pNew;
+ Aig_Obj_t * pObj, * pObjNew;
+ int Out, i;
+ // create new AIG for this partition
+ pNew = Aig_ManStartFrom( p->pAig );
+ Aig_ManIncrementTravId( p->pAig );
+ Aig_ObjSetTravIdCurrent( p->pAig, Aig_ManConst1(p->pAig) );
+ Aig_ManConst1(p->pAig)->pData = Aig_ManConst1(pNew);
+ Vec_IntForEachEntry( vPart, Out, i )
+ {
+ pObj = Aig_ManPo( p->pAig, Out );
+ if ( pObj->fMarkA )
+ {
+ pObjNew = Fra_LcrCreatePart_rec( p->pCla, pNew, p->pAig, Aig_ObjFanin0(pObj) );
+ pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObj) );
+ }
+ else
+ pObjNew = Aig_ManConst1( pNew );
+ Aig_ObjCreatePo( pNew, pObjNew );
+ }
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks the nodes belonging to the equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClassNodesMark( Fra_Lcr_t * p )
+{
+ Aig_Obj_t * pObj, ** ppClass;
+ int i, c, Offset;
+ // compute the LO/LI offset
+ Offset = Aig_ManPoNum(p->pCla->pAig) - Aig_ManPiNum(p->pCla->pAig);
+ // mark the nodes remaining in the classes
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->pCla->vClasses1, pObj, i )
+ {
+ pObj = Aig_ManPo( p->pCla->pAig, Offset+(long)pObj->pNext );
+ pObj->fMarkA = 1;
+ }
+ Vec_PtrForEachEntry( Aig_Obj_t **, p->pCla->vClasses, ppClass, i )
+ {
+ for ( c = 0; ppClass[c]; c++ )
+ {
+ pObj = Aig_ManPo( p->pCla->pAig, Offset+(long)ppClass[c]->pNext );
+ pObj->fMarkA = 1;
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Unmarks the nodes belonging to the equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ClassNodesUnmark( Fra_Lcr_t * p )
+{
+ Aig_Obj_t * pObj, ** ppClass;
+ int i, c, Offset;
+ // compute the LO/LI offset
+ Offset = Aig_ManPoNum(p->pCla->pAig) - Aig_ManPiNum(p->pCla->pAig);
+ // mark the nodes remaining in the classes
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->pCla->vClasses1, pObj, i )
+ {
+ pObj = Aig_ManPo( p->pCla->pAig, Offset+(long)pObj->pNext );
+ pObj->fMarkA = 0;
+ }
+ Vec_PtrForEachEntry( Aig_Obj_t **, p->pCla->vClasses, ppClass, i )
+ {
+ for ( c = 0; ppClass[c]; c++ )
+ {
+ pObj = Aig_ManPo( p->pCla->pAig, Offset+(long)ppClass[c]->pNext );
+ pObj->fMarkA = 0;
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs choicing of the AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Fra_FraigLatchCorrespondence( Aig_Man_t * pAig, int nFramesP, int nConfMax, int fProve, int fVerbose, int * pnIter, float TimeLimit )
+{
+ int nPartSize = 200;
+ int fReprSelect = 0;
+ Fra_Lcr_t * p;
+ Fra_Sml_t * pSml;
+ Fra_Man_t * pTemp;
+ Aig_Man_t * pAigPart, * pAigTemp, * pAigNew = NULL;
+ Vec_Int_t * vPart;
+ int i, nIter, timeSim, clk = clock(), clk2, clk3;
+ int TimeToStop = (TimeLimit == 0.0)? 0 : clock() + (int)(TimeLimit * CLOCKS_PER_SEC);
+ if ( Aig_ManNodeNum(pAig) == 0 )
+ {
+ if ( pnIter ) *pnIter = 0;
+ // Ntl_ManFinalize() requires the following to satisfy an assertion.
+ Aig_ManReprStart(pAig,Aig_ManObjNumMax(pAig));
+ return Aig_ManDupOrdered(pAig);
+ }
+ assert( Aig_ManRegNum(pAig) > 0 );
+
+ // simulate the AIG
+clk2 = clock();
+if ( fVerbose )
+printf( "Simulating AIG with %d nodes for %d cycles ... ", Aig_ManNodeNum(pAig), nFramesP + 32 );
+ pSml = Fra_SmlSimulateSeq( pAig, nFramesP, 32, 1, 1 );
+if ( fVerbose )
+{
+ABC_PRT( "Time", clock() - clk2 );
+}
+timeSim = clock() - clk2;
+
+ // check if simulation discovered non-constant-0 POs
+ if ( fProve && pSml->fNonConstOut )
+ {
+ pAig->pSeqModel = Fra_SmlGetCounterExample( pSml );
+ Fra_SmlStop( pSml );
+ return NULL;
+ }
+
+ // start the manager
+ p = Lcr_ManAlloc( pAig );
+ p->nFramesP = nFramesP;
+ p->fVerbose = fVerbose;
+ p->timeSim += timeSim;
+
+ pTemp = Fra_LcrAigPrepare( pAig );
+ pTemp->pBmc = (Fra_Bmc_t *)p;
+ pTemp->pSml = pSml;
+
+ // get preliminary info about equivalence classes
+ pTemp->pCla = p->pCla = Fra_ClassesStart( p->pAig );
+ Fra_ClassesPrepare( p->pCla, 1, 0 );
+ p->pCla->pFuncNodeIsConst = Fra_LcrNodeIsConst;
+ p->pCla->pFuncNodesAreEqual = Fra_LcrNodesAreEqual;
+ Fra_SmlStop( pTemp->pSml );
+
+ // partition the AIG for latch correspondence computation
+clk2 = clock();
+if ( fVerbose )
+printf( "Partitioning AIG ... " );
+ pAigPart = Fra_LcrDeriveAigForPartitioning( p );
+ p->vParts = (Vec_Ptr_t *)Aig_ManPartitionSmart( pAigPart, nPartSize, 0, NULL );
+ Fra_LcrRemapPartitions( p->vParts, p->pCla, p->pInToOutPart, p->pInToOutNum );
+ Aig_ManStop( pAigPart );
+if ( fVerbose )
+{
+ABC_PRT( "Time", clock() - clk2 );
+p->timePart += clock() - clk2;
+}
+
+ // get the initial stats
+ p->nLitsBeg = Fra_ClassesCountLits( p->pCla );
+ p->nNodesBeg = Aig_ManNodeNum(p->pAig);
+ p->nRegsBeg = Aig_ManRegNum(p->pAig);
+
+ // perforn interative reduction of the partitions
+ p->fRefining = 1;
+ for ( nIter = 0; p->fRefining; nIter++ )
+ {
+ p->fRefining = 0;
+ clk3 = clock();
+ // derive AIGs for each partition
+ Fra_ClassNodesMark( p );
+ Vec_PtrClear( p->vFraigs );
+ Vec_PtrForEachEntry( Vec_Int_t *, p->vParts, vPart, i )
+ {
+ int clk3 = clock();
+ if ( TimeLimit != 0.0 && clock() > TimeToStop )
+ {
+ Vec_PtrForEachEntry( Aig_Man_t *, p->vFraigs, pAigPart, i )
+ Aig_ManStop( pAigPart );
+ Aig_ManCleanMarkA( pAig );
+ Aig_ManCleanMarkB( pAig );
+ printf( "Fra_FraigLatchCorrespondence(): Runtime limit exceeded.\n" );
+ goto finish;
+ }
+clk2 = clock();
+ pAigPart = Fra_LcrCreatePart( p, vPart );
+p->timeTrav += clock() - clk2;
+clk2 = clock();
+ pAigTemp = Fra_FraigEquivence( pAigPart, nConfMax, 0 );
+p->timeFraig += clock() - clk2;
+ Vec_PtrPush( p->vFraigs, pAigTemp );
+/*
+ {
+ char Name[1000];
+ sprintf( Name, "part%04d.blif", i );
+ Aig_ManDumpBlif( pAigPart, Name, NULL, NULL );
+ }
+printf( "Finished part %4d (out of %4d). ", i, Vec_PtrSize(p->vParts) );
+ABC_PRT( "Time", clock() - clk3 );
+*/
+
+ Aig_ManStop( pAigPart );
+ }
+ Fra_ClassNodesUnmark( p );
+ // report the intermediate results
+ if ( fVerbose )
+ {
+ printf( "%3d : Const = %6d. Class = %6d. L = %6d. Part = %3d. ",
+ nIter, Vec_PtrSize(p->pCla->vClasses1), Vec_PtrSize(p->pCla->vClasses),
+ Fra_ClassesCountLits(p->pCla), Vec_PtrSize(p->vParts) );
+ ABC_PRT( "T", clock() - clk3 );
+ }
+ // refine the classes
+ Fra_LcrAigPrepareTwo( p->pAig, pTemp );
+ if ( Fra_ClassesRefine( p->pCla ) )
+ p->fRefining = 1;
+ if ( Fra_ClassesRefine1( p->pCla, 0, NULL ) )
+ p->fRefining = 1;
+ // clean the fraigs
+ Vec_PtrForEachEntry( Aig_Man_t *, p->vFraigs, pAigPart, i )
+ Aig_ManStop( pAigPart );
+
+ // repartition if needed
+ if ( 1 )
+ {
+clk2 = clock();
+ Vec_VecFree( (Vec_Vec_t *)p->vParts );
+ pAigPart = Fra_LcrDeriveAigForPartitioning( p );
+ p->vParts = (Vec_Ptr_t *)Aig_ManPartitionSmart( pAigPart, nPartSize, 0, NULL );
+ Fra_LcrRemapPartitions( p->vParts, p->pCla, p->pInToOutPart, p->pInToOutNum );
+ Aig_ManStop( pAigPart );
+p->timePart += clock() - clk2;
+ }
+ }
+ p->nIters = nIter;
+
+ // move the classes into representatives and reduce AIG
+clk2 = clock();
+// Fra_ClassesPrint( p->pCla, 1 );
+ if ( fReprSelect )
+ Fra_ClassesSelectRepr( p->pCla );
+ Fra_ClassesCopyReprs( p->pCla, NULL );
+ pAigNew = Aig_ManDupRepr( p->pAig, 0 );
+ Aig_ManSeqCleanup( pAigNew );
+// Aig_ManCountMergeRegs( pAigNew );
+p->timeUpdate += clock() - clk2;
+p->timeTotal = clock() - clk;
+ // get the final stats
+ p->nLitsEnd = Fra_ClassesCountLits( p->pCla );
+ p->nNodesEnd = Aig_ManNodeNum(pAigNew);
+ p->nRegsEnd = Aig_ManRegNum(pAigNew);
+finish:
+ ABC_FREE( pTemp );
+ Lcr_ManFree( p );
+ if ( pnIter ) *pnIter = nIter;
+ return pAigNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fra/fraMan.c b/src/proof/fra/fraMan.c
new file mode 100644
index 00000000..90e8b762
--- /dev/null
+++ b/src/proof/fra/fraMan.c
@@ -0,0 +1,314 @@
+/**CFile****************************************************************
+
+ FileName [fraMan.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [New FRAIG package.]
+
+ Synopsis [Starts the FRAIG manager.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 30, 2007.]
+
+ Revision [$Id: fraMan.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Sets the default solving parameters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ParamsDefault( Fra_Par_t * pPars )
+{
+ memset( pPars, 0, sizeof(Fra_Par_t) );
+ pPars->nSimWords = 32; // the number of words in the simulation info
+ pPars->dSimSatur = 0.005; // the ratio of refined classes when saturation is reached
+ pPars->fPatScores = 0; // enables simulation pattern scoring
+ pPars->MaxScore = 25; // max score after which resimulation is used
+ pPars->fDoSparse = 1; // skips sparse functions
+// pPars->dActConeRatio = 0.05; // the ratio of cone to be bumped
+// pPars->dActConeBumpMax = 5.0; // the largest bump of activity
+ pPars->dActConeRatio = 0.3; // the ratio of cone to be bumped
+ pPars->dActConeBumpMax = 10.0; // the largest bump of activity
+ pPars->nBTLimitNode = 100; // conflict limit at a node
+ pPars->nBTLimitMiter = 500000; // conflict limit at an output
+ pPars->nFramesK = 0; // the number of timeframes to unroll
+ pPars->fConeBias = 1;
+ pPars->fRewrite = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the default solving parameters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ParamsDefaultSeq( Fra_Par_t * pPars )
+{
+ memset( pPars, 0, sizeof(Fra_Par_t) );
+ pPars->nSimWords = 1; // the number of words in the simulation info
+ pPars->dSimSatur = 0.005; // the ratio of refined classes when saturation is reached
+ pPars->fPatScores = 0; // enables simulation pattern scoring
+ pPars->MaxScore = 25; // max score after which resimulation is used
+ pPars->fDoSparse = 1; // skips sparse functions
+ pPars->dActConeRatio = 0.3; // the ratio of cone to be bumped
+ pPars->dActConeBumpMax = 10.0; // the largest bump of activity
+ pPars->nBTLimitNode = 10000000; // conflict limit at a node
+ pPars->nBTLimitMiter = 500000; // conflict limit at an output
+ pPars->nFramesK = 1; // the number of timeframes to unroll
+ pPars->fConeBias = 0;
+ pPars->fRewrite = 0;
+ pPars->fLatchCorr = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the fraiging manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fra_Man_t * Fra_ManStart( Aig_Man_t * pManAig, Fra_Par_t * pPars )
+{
+ Fra_Man_t * p;
+ Aig_Obj_t * pObj;
+ int i;
+ // allocate the fraiging manager
+ p = ABC_ALLOC( Fra_Man_t, 1 );
+ memset( p, 0, sizeof(Fra_Man_t) );
+ p->pPars = pPars;
+ p->pManAig = pManAig;
+ p->nSizeAlloc = Aig_ManObjNumMax( pManAig );
+ p->nFramesAll = pPars->nFramesK + 1;
+ // allocate storage for sim pattern
+ p->nPatWords = Abc_BitWordNum( (Aig_ManPiNum(pManAig) - Aig_ManRegNum(pManAig)) * p->nFramesAll + Aig_ManRegNum(pManAig) );
+ p->pPatWords = ABC_ALLOC( unsigned, p->nPatWords );
+ p->vPiVars = Vec_PtrAlloc( 100 );
+ // equivalence classes
+ p->pCla = Fra_ClassesStart( pManAig );
+ // allocate other members
+ p->pMemFraig = ABC_ALLOC( Aig_Obj_t *, p->nSizeAlloc * p->nFramesAll );
+ memset( p->pMemFraig, 0, sizeof(Aig_Obj_t *) * p->nSizeAlloc * p->nFramesAll );
+ // set random number generator
+// srand( 0xABCABC );
+ Aig_ManRandom(1);
+ // set the pointer to the manager
+ Aig_ManForEachObj( p->pManAig, pObj, i )
+ pObj->pData = p;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the fraiging manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ManClean( Fra_Man_t * p, int nNodesMax )
+{
+ int i;
+ // remove old arrays
+ for ( i = 0; i < p->nMemAlloc; i++ )
+ if ( p->pMemFanins[i] && p->pMemFanins[i] != (void *)1 )
+ Vec_PtrFree( p->pMemFanins[i] );
+ // realloc for the new size
+ if ( p->nMemAlloc < nNodesMax )
+ {
+ int nMemAllocNew = nNodesMax + 5000;
+ p->pMemFanins = ABC_REALLOC( Vec_Ptr_t *, p->pMemFanins, nMemAllocNew );
+ p->pMemSatNums = ABC_REALLOC( int, p->pMemSatNums, nMemAllocNew );
+ p->nMemAlloc = nMemAllocNew;
+ }
+ // prepare for the new run
+ memset( p->pMemFanins, 0, sizeof(Vec_Ptr_t *) * p->nMemAlloc );
+ memset( p->pMemSatNums, 0, sizeof(int) * p->nMemAlloc );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the new manager to begin fraiging.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Fra_ManPrepareComb( Fra_Man_t * p )
+{
+ Aig_Man_t * pManFraig;
+ Aig_Obj_t * pObj;
+ int i;
+ assert( p->pManFraig == NULL );
+ // start the fraig package
+ pManFraig = Aig_ManStart( Aig_ManObjNumMax(p->pManAig) );
+ pManFraig->pName = Abc_UtilStrsav( p->pManAig->pName );
+ pManFraig->pSpec = Abc_UtilStrsav( p->pManAig->pSpec );
+ pManFraig->nRegs = p->pManAig->nRegs;
+ pManFraig->nAsserts = p->pManAig->nAsserts;
+ // set the pointers to the available fraig nodes
+ Fra_ObjSetFraig( Aig_ManConst1(p->pManAig), 0, Aig_ManConst1(pManFraig) );
+ Aig_ManForEachPi( p->pManAig, pObj, i )
+ Fra_ObjSetFraig( pObj, 0, Aig_ObjCreatePi(pManFraig) );
+ // set the pointers to the manager
+ Aig_ManForEachObj( pManFraig, pObj, i )
+ pObj->pData = p;
+ // allocate memory for mapping FRAIG nodes into SAT numbers and fanins
+ p->nMemAlloc = p->nSizeAlloc;
+ p->pMemFanins = ABC_ALLOC( Vec_Ptr_t *, p->nMemAlloc );
+ memset( p->pMemFanins, 0, sizeof(Vec_Ptr_t *) * p->nMemAlloc );
+ p->pMemSatNums = ABC_ALLOC( int, p->nMemAlloc );
+ memset( p->pMemSatNums, 0, sizeof(int) * p->nMemAlloc );
+ // make sure the satisfying assignment is node assigned
+ assert( pManFraig->pData == NULL );
+ return pManFraig;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finalizes the combinational miter after fraiging.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ManFinalizeComb( Fra_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ // add the POs
+ Aig_ManForEachPo( p->pManAig, pObj, i )
+ Aig_ObjCreatePo( p->pManFraig, Fra_ObjChild0Fra(pObj,0) );
+ // postprocess
+ Aig_ManCleanMarkB( p->pManFraig );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Stops the fraiging manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ManStop( Fra_Man_t * p )
+{
+ if ( p->pPars->fVerbose )
+ Fra_ManPrint( p );
+ // save mapping from original nodes into FRAIG nodes
+ if ( p->pManAig )
+ {
+ if ( p->pManAig->pObjCopies )
+ ABC_FREE( p->pManAig->pObjCopies );
+ p->pManAig->pObjCopies = p->pMemFraig;
+ p->pMemFraig = NULL;
+ }
+ Fra_ManClean( p, 0 );
+ if ( p->vTimeouts ) Vec_PtrFree( p->vTimeouts );
+ if ( p->vPiVars ) Vec_PtrFree( p->vPiVars );
+ if ( p->pSat ) sat_solver_delete( p->pSat );
+ if ( p->pCla ) Fra_ClassesStop( p->pCla );
+ if ( p->pSml ) Fra_SmlStop( p->pSml );
+ if ( p->vCex ) Vec_IntFree( p->vCex );
+ if ( p->vOneHots ) Vec_IntFree( p->vOneHots );
+ ABC_FREE( p->pMemFraig );
+ ABC_FREE( p->pMemFanins );
+ ABC_FREE( p->pMemSatNums );
+ ABC_FREE( p->pPatWords );
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints stats for the fraiging manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ManPrint( Fra_Man_t * p )
+{
+ double nMemory = 1.0*Aig_ManObjNumMax(p->pManAig)*(p->pSml->nWordsTotal*sizeof(unsigned)+6*sizeof(void*))/(1<<20);
+ printf( "SimWord = %d. Round = %d. Mem = %0.2f Mb. LitBeg = %d. LitEnd = %d. (%6.2f %%).\n",
+ p->pPars->nSimWords, p->pSml->nSimRounds, nMemory, p->nLitsBeg, p->nLitsEnd, 100.0*p->nLitsEnd/(p->nLitsBeg?p->nLitsBeg:1) );
+ printf( "Proof = %d. Cex = %d. Fail = %d. FailReal = %d. C-lim = %d. ImpRatio = %6.2f %%\n",
+ p->nSatProof, p->nSatCallsSat, p->nSatFails, p->nSatFailsReal, p->pPars->nBTLimitNode, Fra_ImpComputeStateSpaceRatio(p) );
+ printf( "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n",
+ p->nNodesBeg, p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/(p->nNodesBeg?p->nNodesBeg:1),
+ p->nRegsBeg, p->nRegsEnd, 100.0*(p->nRegsBeg-p->nRegsEnd)/(p->nRegsBeg?p->nRegsBeg:1) );
+ if ( p->pSat ) Sat_SolverPrintStats( stdout, p->pSat );
+ if ( p->pPars->fUse1Hot ) Fra_OneHotEstimateCoverage( p, p->vOneHots );
+ ABC_PRT( "AIG simulation ", p->pSml->timeSim );
+ ABC_PRT( "AIG traversal ", p->timeTrav );
+ if ( p->timeRwr )
+ {
+ ABC_PRT( "AIG rewriting ", p->timeRwr );
+ }
+ ABC_PRT( "SAT solving ", p->timeSat );
+ ABC_PRT( " Unsat ", p->timeSatUnsat );
+ ABC_PRT( " Sat ", p->timeSatSat );
+ ABC_PRT( " Fail ", p->timeSatFail );
+ ABC_PRT( "Class refining ", p->timeRef );
+ ABC_PRT( "TOTAL RUNTIME ", p->timeTotal );
+ if ( p->time1 ) { ABC_PRT( "time1 ", p->time1 ); }
+ if ( p->nSpeculs )
+ printf( "Speculations = %d.\n", p->nSpeculs );
+ fflush( stdout );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fra/fraPart.c b/src/proof/fra/fraPart.c
new file mode 100644
index 00000000..e9739f97
--- /dev/null
+++ b/src/proof/fra/fraPart.c
@@ -0,0 +1,268 @@
+/**CFile****************************************************************
+
+ FileName [fraPart.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [New FRAIG package.]
+
+ Synopsis [Partitioning for induction.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 30, 2007.]
+
+ Revision [$Id: fraPart.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ManPartitionTest( Aig_Man_t * p, int nComLim )
+{
+// Bar_Progress_t * pProgress;
+ Vec_Vec_t * vSupps, * vSuppsIn;
+ Vec_Ptr_t * vSuppsNew;
+ Vec_Int_t * vSupNew, * vSup, * vSup2, * vTemp;//, * vSupIn;
+ Vec_Int_t * vOverNew, * vQuantNew;
+ Aig_Obj_t * pObj;
+ int i, k, nCommon, CountOver, CountQuant;
+ int nTotalSupp, nTotalSupp2, Entry, Largest;//, iVar;
+ double Ratio, R;
+ int clk;
+
+ nTotalSupp = 0;
+ nTotalSupp2 = 0;
+ Ratio = 0.0;
+
+ // compute supports
+clk = clock();
+ vSupps = (Vec_Vec_t *)Aig_ManSupports( p );
+ABC_PRT( "Supports", clock() - clk );
+ // remove last entry
+ Aig_ManForEachPo( p, pObj, i )
+ {
+ vSup = Vec_VecEntryInt( vSupps, i );
+ Vec_IntPop( vSup );
+ // remember support
+// pObj->pNext = (Aig_Obj_t *)vSup;
+ }
+
+ // create reverse supports
+clk = clock();
+ vSuppsIn = Vec_VecStart( Aig_ManPiNum(p) );
+ Aig_ManForEachPo( p, pObj, i )
+ {
+ vSup = Vec_VecEntryInt( vSupps, i );
+ Vec_IntForEachEntry( vSup, Entry, k )
+ Vec_VecPush( vSuppsIn, Entry, (void *)(ABC_PTRUINT_T)i );
+ }
+ABC_PRT( "Inverse ", clock() - clk );
+
+clk = clock();
+ // compute extended supports
+ Largest = 0;
+ vSuppsNew = Vec_PtrAlloc( Aig_ManPoNum(p) );
+ vOverNew = Vec_IntAlloc( Aig_ManPoNum(p) );
+ vQuantNew = Vec_IntAlloc( Aig_ManPoNum(p) );
+// pProgress = Bar_ProgressStart( stdout, Aig_ManPoNum(p) );
+ Aig_ManForEachPo( p, pObj, i )
+ {
+// Bar_ProgressUpdate( pProgress, i, NULL );
+ // get old supports
+ vSup = Vec_VecEntryInt( vSupps, i );
+ if ( Vec_IntSize(vSup) < 2 )
+ continue;
+ // compute new supports
+ CountOver = CountQuant = 0;
+ vSupNew = Vec_IntDup( vSup );
+ // go through the nodes where the first var appears
+ Aig_ManForEachPo( p, pObj, k )
+// iVar = Vec_IntEntry( vSup, 0 );
+// vSupIn = Vec_VecEntry( vSuppsIn, iVar );
+// Vec_IntForEachEntry( vSupIn, Entry, k )
+ {
+// pObj = Aig_ManObj( p, Entry );
+ // get support of this output
+// vSup2 = (Vec_Int_t *)pObj->pNext;
+ vSup2 = Vec_VecEntryInt( vSupps, k );
+ // count the number of common vars
+ nCommon = Vec_IntTwoCountCommon(vSup, vSup2);
+ if ( nCommon < 2 )
+ continue;
+ if ( nCommon > nComLim )
+ {
+ vSupNew = Vec_IntTwoMerge( vTemp = vSupNew, vSup2 );
+ Vec_IntFree( vTemp );
+ CountOver++;
+ }
+ else
+ CountQuant++;
+ }
+ // save the results
+ Vec_PtrPush( vSuppsNew, vSupNew );
+ Vec_IntPush( vOverNew, CountOver );
+ Vec_IntPush( vQuantNew, CountQuant );
+
+ if ( Largest < Vec_IntSize(vSupNew) )
+ Largest = Vec_IntSize(vSupNew);
+
+ nTotalSupp += Vec_IntSize(vSup);
+ nTotalSupp2 += Vec_IntSize(vSupNew);
+ if ( Vec_IntSize(vSup) )
+ R = Vec_IntSize(vSupNew) / Vec_IntSize(vSup);
+ else
+ R = 0;
+ Ratio += R;
+
+ if ( R < 5.0 )
+ continue;
+
+ printf( "%6d : ", i );
+ printf( "S = %5d. ", Vec_IntSize(vSup) );
+ printf( "SNew = %5d. ", Vec_IntSize(vSupNew) );
+ printf( "R = %7.2f. ", R );
+ printf( "Over = %5d. ", CountOver );
+ printf( "Quant = %5d. ", CountQuant );
+ printf( "\n" );
+/*
+ Vec_IntForEachEntry( vSupNew, Entry, k )
+ printf( "%d ", Entry );
+ printf( "\n" );
+*/
+ }
+// Bar_ProgressStop( pProgress );
+ABC_PRT( "Scanning", clock() - clk );
+
+ // print cumulative statistics
+ printf( "PIs = %6d. POs = %6d. Lim = %3d. AveS = %3d. SN = %3d. R = %4.2f Max = %5d.\n",
+ Aig_ManPiNum(p), Aig_ManPoNum(p), nComLim,
+ nTotalSupp/Aig_ManPoNum(p), nTotalSupp2/Aig_ManPoNum(p),
+ Ratio/Aig_ManPoNum(p), Largest );
+
+ Vec_VecFree( vSupps );
+ Vec_VecFree( vSuppsIn );
+ Vec_VecFree( (Vec_Vec_t *)vSuppsNew );
+ Vec_IntFree( vOverNew );
+ Vec_IntFree( vQuantNew );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_ManPartitionTest2( Aig_Man_t * p )
+{
+ Vec_Vec_t * vSupps, * vSuppsIn;
+ Vec_Int_t * vSup, * vSup2, * vSup3;
+ Aig_Obj_t * pObj;
+ int Entry, Entry2, Entry3, Counter;
+ int i, k, m, n, clk;
+ char * pSupp;
+
+ // compute supports
+clk = clock();
+ vSupps = (Vec_Vec_t *)Aig_ManSupports( p );
+ABC_PRT( "Supports", clock() - clk );
+ // remove last entry
+ Aig_ManForEachPo( p, pObj, i )
+ {
+ vSup = Vec_VecEntryInt( vSupps, i );
+ Vec_IntPop( vSup );
+ // remember support
+// pObj->pNext = (Aig_Obj_t *)vSup;
+ }
+
+ // create reverse supports
+clk = clock();
+ vSuppsIn = Vec_VecStart( Aig_ManPiNum(p) );
+ Aig_ManForEachPo( p, pObj, i )
+ {
+ if ( i == p->nAsserts )
+ break;
+ vSup = Vec_VecEntryInt( vSupps, i );
+ Vec_IntForEachEntry( vSup, Entry, k )
+ Vec_VecPush( vSuppsIn, Entry, (void *)(ABC_PTRUINT_T)i );
+ }
+ABC_PRT( "Inverse ", clock() - clk );
+
+ // create affective supports
+clk = clock();
+ pSupp = ABC_ALLOC( char, Aig_ManPiNum(p) );
+ Aig_ManForEachPo( p, pObj, i )
+ {
+ if ( i % 50 != 0 )
+ continue;
+ vSup = Vec_VecEntryInt( vSupps, i );
+ memset( pSupp, 0, sizeof(char) * Aig_ManPiNum(p) );
+ // go through each input of this output
+ Vec_IntForEachEntry( vSup, Entry, k )
+ {
+ pSupp[Entry] = 1;
+ vSup2 = Vec_VecEntryInt( vSuppsIn, Entry );
+ // go though each assert of this input
+ Vec_IntForEachEntry( vSup2, Entry2, m )
+ {
+ vSup3 = Vec_VecEntryInt( vSupps, Entry2 );
+ // go through each input of this assert
+ Vec_IntForEachEntry( vSup3, Entry3, n )
+ {
+ pSupp[Entry3] = 1;
+ }
+ }
+ }
+ // count the entries
+ Counter = 0;
+ for ( m = 0; m < Aig_ManPiNum(p); m++ )
+ Counter += pSupp[m];
+ printf( "%d(%d) ", Vec_IntSize(vSup), Counter );
+ }
+ printf( "\n" );
+ABC_PRT( "Extension ", clock() - clk );
+
+ ABC_FREE( pSupp );
+ Vec_VecFree( vSupps );
+ Vec_VecFree( vSuppsIn );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fra/fraSat.c b/src/proof/fra/fraSat.c
new file mode 100644
index 00000000..fef642f5
--- /dev/null
+++ b/src/proof/fra/fraSat.c
@@ -0,0 +1,566 @@
+/**CFile****************************************************************
+
+ FileName [fraSat.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: fraSat.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <math.h>
+#include "fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Fra_SetActivityFactors( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Runs equivalence test for the two nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_NodesAreEquiv( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew )
+{
+ int pLits[4], RetValue, RetValue1, nBTLimit, clk;//, clk2 = clock();
+ int status;
+
+ // make sure the nodes are not complemented
+ assert( !Aig_IsComplement(pNew) );
+ assert( !Aig_IsComplement(pOld) );
+ assert( pNew != pOld );
+
+ // if at least one of the nodes is a failed node, perform adjustments:
+ // if the backtrack limit is small, simply skip this node
+ // if the backtrack limit is > 10, take the quare root of the limit
+ nBTLimit = p->pPars->nBTLimitNode;
+ if ( !p->pPars->fSpeculate && p->pPars->nFramesK == 0 && (nBTLimit > 0 && (pOld->fMarkB || pNew->fMarkB)) )
+ {
+ p->nSatFails++;
+ // fail immediately
+// return -1;
+ if ( nBTLimit <= 10 )
+ return -1;
+ nBTLimit = (int)pow(nBTLimit, 0.7);
+ }
+
+ p->nSatCalls++;
+ p->nSatCallsRecent++;
+
+ // make sure the solver is allocated and has enough variables
+ if ( p->pSat == NULL )
+ {
+ p->pSat = sat_solver_new();
+ p->nSatVars = 1;
+ sat_solver_setnvars( p->pSat, 1000 );
+ // var 0 is reserved for const1 node - add the clause
+ pLits[0] = toLit( 0 );
+ sat_solver_addclause( p->pSat, pLits, pLits + 1 );
+ }
+
+ // if the nodes do not have SAT variables, allocate them
+ Fra_CnfNodeAddToSolver( p, pOld, pNew );
+
+ if ( p->pSat->qtail != p->pSat->qhead )
+ {
+ status = sat_solver_simplify(p->pSat);
+ assert( status != 0 );
+ assert( p->pSat->qtail == p->pSat->qhead );
+ }
+
+ // prepare variable activity
+ if ( p->pPars->fConeBias )
+ Fra_SetActivityFactors( p, pOld, pNew );
+
+ // solve under assumptions
+ // A = 1; B = 0 OR A = 1; B = 1
+clk = clock();
+ pLits[0] = toLitCond( Fra_ObjSatNum(pOld), 0 );
+ pLits[1] = toLitCond( Fra_ObjSatNum(pNew), pOld->fPhase == pNew->fPhase );
+//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 );
+ RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2,
+ (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0,
+ p->nBTLimitGlobal, p->nInsLimitGlobal );
+p->timeSat += clock() - clk;
+ if ( RetValue1 == l_False )
+ {
+p->timeSatUnsat += clock() - clk;
+ pLits[0] = lit_neg( pLits[0] );
+ pLits[1] = lit_neg( pLits[1] );
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+ assert( RetValue );
+ // continue solving the other implication
+ p->nSatCallsUnsat++;
+ }
+ else if ( RetValue1 == l_True )
+ {
+p->timeSatSat += clock() - clk;
+ Fra_SmlSavePattern( p );
+ p->nSatCallsSat++;
+ return 0;
+ }
+ else // if ( RetValue1 == l_Undef )
+ {
+p->timeSatFail += clock() - clk;
+ // mark the node as the failed node
+ if ( pOld != p->pManFraig->pConst1 )
+ pOld->fMarkB = 1;
+ pNew->fMarkB = 1;
+ p->nSatFailsReal++;
+ return -1;
+ }
+
+ // if the old node was constant 0, we already know the answer
+ if ( pOld == p->pManFraig->pConst1 )
+ {
+ p->nSatProof++;
+ return 1;
+ }
+
+ // solve under assumptions
+ // A = 0; B = 1 OR A = 0; B = 0
+clk = clock();
+ pLits[0] = toLitCond( Fra_ObjSatNum(pOld), 1 );
+ pLits[1] = toLitCond( Fra_ObjSatNum(pNew), pOld->fPhase ^ pNew->fPhase );
+ RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2,
+ (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0,
+ p->nBTLimitGlobal, p->nInsLimitGlobal );
+p->timeSat += clock() - clk;
+ if ( RetValue1 == l_False )
+ {
+p->timeSatUnsat += clock() - clk;
+ pLits[0] = lit_neg( pLits[0] );
+ pLits[1] = lit_neg( pLits[1] );
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+ assert( RetValue );
+ p->nSatCallsUnsat++;
+ }
+ else if ( RetValue1 == l_True )
+ {
+p->timeSatSat += clock() - clk;
+ Fra_SmlSavePattern( p );
+ p->nSatCallsSat++;
+ return 0;
+ }
+ else // if ( RetValue1 == l_Undef )
+ {
+p->timeSatFail += clock() - clk;
+ // mark the node as the failed node
+ pOld->fMarkB = 1;
+ pNew->fMarkB = 1;
+ p->nSatFailsReal++;
+ return -1;
+ }
+/*
+ // check BDD proof
+ {
+ int RetVal;
+ ABC_PRT( "Sat", clock() - clk2 );
+ clk2 = clock();
+ RetVal = Fra_NodesAreEquivBdd( pOld, pNew );
+// printf( "%d ", RetVal );
+ assert( RetVal );
+ ABC_PRT( "Bdd", clock() - clk2 );
+ printf( "\n" );
+ }
+*/
+ // return SAT proof
+ p->nSatProof++;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Runs the result of test for pObj => pNew.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_NodesAreImp( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew, int fComplL, int fComplR )
+{
+ int pLits[4], RetValue, RetValue1, nBTLimit, clk;//, clk2 = clock();
+ int status;
+
+ // make sure the nodes are not complemented
+ assert( !Aig_IsComplement(pNew) );
+ assert( !Aig_IsComplement(pOld) );
+ assert( pNew != pOld );
+
+ // if at least one of the nodes is a failed node, perform adjustments:
+ // if the backtrack limit is small, simply skip this node
+ // if the backtrack limit is > 10, take the quare root of the limit
+ nBTLimit = p->pPars->nBTLimitNode;
+/*
+ if ( !p->pPars->fSpeculate && p->pPars->nFramesK == 0 && (nBTLimit > 0 && (pOld->fMarkB || pNew->fMarkB)) )
+ {
+ p->nSatFails++;
+ // fail immediately
+// return -1;
+ if ( nBTLimit <= 10 )
+ return -1;
+ nBTLimit = (int)pow(nBTLimit, 0.7);
+ }
+*/
+ p->nSatCalls++;
+
+ // make sure the solver is allocated and has enough variables
+ if ( p->pSat == NULL )
+ {
+ p->pSat = sat_solver_new();
+ p->nSatVars = 1;
+ sat_solver_setnvars( p->pSat, 1000 );
+ // var 0 is reserved for const1 node - add the clause
+ pLits[0] = toLit( 0 );
+ sat_solver_addclause( p->pSat, pLits, pLits + 1 );
+ }
+
+ // if the nodes do not have SAT variables, allocate them
+ Fra_CnfNodeAddToSolver( p, pOld, pNew );
+
+ if ( p->pSat->qtail != p->pSat->qhead )
+ {
+ status = sat_solver_simplify(p->pSat);
+ assert( status != 0 );
+ assert( p->pSat->qtail == p->pSat->qhead );
+ }
+
+ // prepare variable activity
+ if ( p->pPars->fConeBias )
+ Fra_SetActivityFactors( p, pOld, pNew );
+
+ // solve under assumptions
+ // A = 1; B = 0 OR A = 1; B = 1
+clk = clock();
+// pLits[0] = toLitCond( Fra_ObjSatNum(pOld), 0 );
+// pLits[1] = toLitCond( Fra_ObjSatNum(pNew), pOld->fPhase == pNew->fPhase );
+ pLits[0] = toLitCond( Fra_ObjSatNum(pOld), fComplL );
+ pLits[1] = toLitCond( Fra_ObjSatNum(pNew), !fComplR );
+//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 );
+ RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2,
+ (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0,
+ p->nBTLimitGlobal, p->nInsLimitGlobal );
+p->timeSat += clock() - clk;
+ if ( RetValue1 == l_False )
+ {
+p->timeSatUnsat += clock() - clk;
+ pLits[0] = lit_neg( pLits[0] );
+ pLits[1] = lit_neg( pLits[1] );
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+ assert( RetValue );
+ // continue solving the other implication
+ p->nSatCallsUnsat++;
+ }
+ else if ( RetValue1 == l_True )
+ {
+p->timeSatSat += clock() - clk;
+ Fra_SmlSavePattern( p );
+ p->nSatCallsSat++;
+ return 0;
+ }
+ else // if ( RetValue1 == l_Undef )
+ {
+p->timeSatFail += clock() - clk;
+ // mark the node as the failed node
+ if ( pOld != p->pManFraig->pConst1 )
+ pOld->fMarkB = 1;
+ pNew->fMarkB = 1;
+ p->nSatFailsReal++;
+ return -1;
+ }
+ // return SAT proof
+ p->nSatProof++;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Runs the result of test for pObj => pNew.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_NodesAreClause( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew, int fComplL, int fComplR )
+{
+ int pLits[4], RetValue, RetValue1, nBTLimit, clk;//, clk2 = clock();
+ int status;
+
+ // make sure the nodes are not complemented
+ assert( !Aig_IsComplement(pNew) );
+ assert( !Aig_IsComplement(pOld) );
+ assert( pNew != pOld );
+
+ // if at least one of the nodes is a failed node, perform adjustments:
+ // if the backtrack limit is small, simply skip this node
+ // if the backtrack limit is > 10, take the quare root of the limit
+ nBTLimit = p->pPars->nBTLimitNode;
+/*
+ if ( !p->pPars->fSpeculate && p->pPars->nFramesK == 0 && (nBTLimit > 0 && (pOld->fMarkB || pNew->fMarkB)) )
+ {
+ p->nSatFails++;
+ // fail immediately
+// return -1;
+ if ( nBTLimit <= 10 )
+ return -1;
+ nBTLimit = (int)pow(nBTLimit, 0.7);
+ }
+*/
+ p->nSatCalls++;
+
+ // make sure the solver is allocated and has enough variables
+ if ( p->pSat == NULL )
+ {
+ p->pSat = sat_solver_new();
+ p->nSatVars = 1;
+ sat_solver_setnvars( p->pSat, 1000 );
+ // var 0 is reserved for const1 node - add the clause
+ pLits[0] = toLit( 0 );
+ sat_solver_addclause( p->pSat, pLits, pLits + 1 );
+ }
+
+ // if the nodes do not have SAT variables, allocate them
+ Fra_CnfNodeAddToSolver( p, pOld, pNew );
+
+ if ( p->pSat->qtail != p->pSat->qhead )
+ {
+ status = sat_solver_simplify(p->pSat);
+ assert( status != 0 );
+ assert( p->pSat->qtail == p->pSat->qhead );
+ }
+
+ // prepare variable activity
+ if ( p->pPars->fConeBias )
+ Fra_SetActivityFactors( p, pOld, pNew );
+
+ // solve under assumptions
+ // A = 1; B = 0 OR A = 1; B = 1
+clk = clock();
+// pLits[0] = toLitCond( Fra_ObjSatNum(pOld), 0 );
+// pLits[1] = toLitCond( Fra_ObjSatNum(pNew), pOld->fPhase == pNew->fPhase );
+ pLits[0] = toLitCond( Fra_ObjSatNum(pOld), !fComplL );
+ pLits[1] = toLitCond( Fra_ObjSatNum(pNew), !fComplR );
+//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 );
+ RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2,
+ (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0,
+ p->nBTLimitGlobal, p->nInsLimitGlobal );
+p->timeSat += clock() - clk;
+ if ( RetValue1 == l_False )
+ {
+p->timeSatUnsat += clock() - clk;
+ pLits[0] = lit_neg( pLits[0] );
+ pLits[1] = lit_neg( pLits[1] );
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+ assert( RetValue );
+ // continue solving the other implication
+ p->nSatCallsUnsat++;
+ }
+ else if ( RetValue1 == l_True )
+ {
+p->timeSatSat += clock() - clk;
+ Fra_SmlSavePattern( p );
+ p->nSatCallsSat++;
+ return 0;
+ }
+ else // if ( RetValue1 == l_Undef )
+ {
+p->timeSatFail += clock() - clk;
+ // mark the node as the failed node
+ if ( pOld != p->pManFraig->pConst1 )
+ pOld->fMarkB = 1;
+ pNew->fMarkB = 1;
+ p->nSatFailsReal++;
+ return -1;
+ }
+ // return SAT proof
+ p->nSatProof++;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Runs equivalence test for one node.]
+
+ Description [Returns the fraiged node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_NodeIsConst( Fra_Man_t * p, Aig_Obj_t * pNew )
+{
+ int pLits[2], RetValue1, RetValue, clk;
+
+ // make sure the nodes are not complemented
+ assert( !Aig_IsComplement(pNew) );
+ assert( pNew != p->pManFraig->pConst1 );
+ p->nSatCalls++;
+
+ // make sure the solver is allocated and has enough variables
+ if ( p->pSat == NULL )
+ {
+ p->pSat = sat_solver_new();
+ p->nSatVars = 1;
+ sat_solver_setnvars( p->pSat, 1000 );
+ // var 0 is reserved for const1 node - add the clause
+ pLits[0] = toLit( 0 );
+ sat_solver_addclause( p->pSat, pLits, pLits + 1 );
+ }
+
+ // if the nodes do not have SAT variables, allocate them
+ Fra_CnfNodeAddToSolver( p, NULL, pNew );
+
+ // prepare variable activity
+ if ( p->pPars->fConeBias )
+ Fra_SetActivityFactors( p, NULL, pNew );
+
+ // solve under assumptions
+clk = clock();
+ pLits[0] = toLitCond( Fra_ObjSatNum(pNew), pNew->fPhase );
+ RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 1,
+ (ABC_INT64_T)p->pPars->nBTLimitMiter, (ABC_INT64_T)0,
+ p->nBTLimitGlobal, p->nInsLimitGlobal );
+p->timeSat += clock() - clk;
+ if ( RetValue1 == l_False )
+ {
+p->timeSatUnsat += clock() - clk;
+ pLits[0] = lit_neg( pLits[0] );
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 1 );
+ assert( RetValue );
+ // continue solving the other implication
+ p->nSatCallsUnsat++;
+ }
+ else if ( RetValue1 == l_True )
+ {
+p->timeSatSat += clock() - clk;
+ if ( p->pPatWords )
+ Fra_SmlSavePattern( p );
+ p->nSatCallsSat++;
+ return 0;
+ }
+ else // if ( RetValue1 == l_Undef )
+ {
+p->timeSatFail += clock() - clk;
+ // mark the node as the failed node
+ pNew->fMarkB = 1;
+ p->nSatFailsReal++;
+ return -1;
+ }
+
+ // return SAT proof
+ p->nSatProof++;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets variable activities in the cone.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_SetActivityFactors_rec( Fra_Man_t * p, Aig_Obj_t * pObj, int LevelMin, int LevelMax )
+{
+ Vec_Ptr_t * vFanins;
+ Aig_Obj_t * pFanin;
+ int i, Counter = 0;
+ assert( !Aig_IsComplement(pObj) );
+ assert( Fra_ObjSatNum(pObj) );
+ // skip visited variables
+ if ( Aig_ObjIsTravIdCurrent(p->pManFraig, pObj) )
+ return 0;
+ Aig_ObjSetTravIdCurrent(p->pManFraig, pObj);
+ // add the PI to the list
+ if ( pObj->Level <= (unsigned)LevelMin || Aig_ObjIsPi(pObj) )
+ return 0;
+ // set the factor of this variable
+ // (LevelMax-LevelMin) / (pObj->Level-LevelMin) = p->pPars->dActConeBumpMax / ThisBump
+ if ( p->pSat->factors == NULL )
+ p->pSat->factors = ABC_CALLOC( double, p->pSat->size );
+ p->pSat->factors[Fra_ObjSatNum(pObj)] = p->pPars->dActConeBumpMax * (pObj->Level - LevelMin)/(LevelMax - LevelMin);
+ veci_push(&p->pSat->act_vars, Fra_ObjSatNum(pObj));
+ // explore the fanins
+ vFanins = Fra_ObjFaninVec( pObj );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vFanins, pFanin, i )
+ Counter += Fra_SetActivityFactors_rec( p, Aig_Regular(pFanin), LevelMin, LevelMax );
+ return 1 + Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets variable activities in the cone.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_SetActivityFactors( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew )
+{
+ int clk, LevelMin, LevelMax;
+ assert( pOld || pNew );
+clk = clock();
+ // reset the active variables
+ veci_resize(&p->pSat->act_vars, 0);
+ // prepare for traversal
+ Aig_ManIncrementTravId( p->pManFraig );
+ // determine the min and max level to visit
+ assert( p->pPars->dActConeRatio > 0 && p->pPars->dActConeRatio < 1 );
+ LevelMax = Abc_MaxInt( (pNew ? pNew->Level : 0), (pOld ? pOld->Level : 0) );
+ LevelMin = (int)(LevelMax * (1.0 - p->pPars->dActConeRatio));
+ // traverse
+ if ( pOld && !Aig_ObjIsConst1(pOld) )
+ Fra_SetActivityFactors_rec( p, pOld, LevelMin, LevelMax );
+ if ( pNew && !Aig_ObjIsConst1(pNew) )
+ Fra_SetActivityFactors_rec( p, pNew, LevelMin, LevelMax );
+//Fra_PrintActivity( p );
+p->timeTrav += clock() - clk;
+ return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fra/fraSec.c b/src/proof/fra/fraSec.c
new file mode 100644
index 00000000..8067b8c2
--- /dev/null
+++ b/src/proof/fra/fraSec.c
@@ -0,0 +1,696 @@
+/**CFile****************************************************************
+
+ FileName [fraSec.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [New FRAIG package.]
+
+ Synopsis [Performs SEC based on seq sweeping.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 30, 2007.]
+
+ Revision [$Id: fraSec.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+#include "src/aig/ioa/ioa.h"
+#include "src/proof/int/int.h"
+#include "src/proof/ssw/ssw.h"
+#include "src/aig/saig/saig.h"
+#include "src/proof/bbr/bbr.h"
+#include "src/proof/pdr/pdr.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_SecSetDefaultParams( Fra_Sec_t * p )
+{
+ memset( p, 0, sizeof(Fra_Sec_t) );
+ p->fTryComb = 1; // try CEC call as a preprocessing step
+ p->fTryBmc = 1; // try BMC call as a preprocessing step
+ p->nFramesMax = 4; // the max number of frames used for induction
+ p->nBTLimit = 1000; // conflict limit at a node during induction
+ p->nBTLimitGlobal = 5000000; // global conflict limit during induction
+ p->nBTLimitInter = 10000; // conflict limit during interpolation
+ p->nBddVarsMax = 150; // the limit on the number of registers in BDD reachability
+ p->nBddMax = 50000; // the limit on the number of BDD nodes
+ p->nBddIterMax = 1000000; // the limit on the number of BDD iterations
+ p->fPhaseAbstract = 0; // enables phase abstraction
+ p->fRetimeFirst = 1; // enables most-forward retiming at the beginning
+ p->fRetimeRegs = 1; // enables min-register retiming at the beginning
+ p->fFraiging = 1; // enables fraiging at the beginning
+ p->fInduction = 1; // enables the use of induction (signal correspondence)
+ p->fInterpolation = 1; // enables interpolation
+ p->fInterSeparate = 0; // enables interpolation for each outputs separately
+ p->fReachability = 1; // enables BDD based reachability
+ p->fReorderImage = 1; // enables variable reordering during image computation
+ p->fStopOnFirstFail = 1; // enables stopping after first output of a miter has failed to prove
+ p->fUseNewProver = 0; // enables new prover
+ p->fUsePdr = 1; // enables PDR
+ p->nPdrTimeout = 60; // enabled PDR timeout
+ p->fSilent = 0; // disables all output
+ p->fVerbose = 0; // enables verbose reporting of statistics
+ p->fVeryVerbose = 0; // enables very verbose reporting
+ p->TimeLimit = 0; // enables the timeout
+ // internal parameters
+ p->fReportSolution = 0; // enables specialized format for reporting solution
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_FraigSec( Aig_Man_t * p, Fra_Sec_t * pParSec, Aig_Man_t ** ppResult )
+{
+ Ssw_Pars_t Pars2, * pPars2 = &Pars2;
+ Fra_Ssw_t Pars, * pPars = &Pars;
+ Fra_Sml_t * pSml;
+ Aig_Man_t * pNew, * pTemp;
+ int nFrames, RetValue, nIter, clk, clkTotal = clock();
+ int TimeOut = 0;
+ int fLatchCorr = 0;
+ float TimeLeft = 0.0;
+ pParSec->nSMnumber = -1;
+
+ // try the miter before solving
+ pNew = Aig_ManDupSimple( p );
+ RetValue = Fra_FraigMiterStatus( pNew );
+ if ( RetValue >= 0 )
+ goto finish;
+
+ // prepare parameters
+ memset( pPars, 0, sizeof(Fra_Ssw_t) );
+ pPars->fLatchCorr = fLatchCorr;
+ pPars->fVerbose = pParSec->fVeryVerbose;
+ if ( pParSec->fVerbose )
+ {
+ printf( "Original miter: Latches = %5d. Nodes = %6d.\n",
+ Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
+ }
+//Aig_ManDumpBlif( pNew, "after.blif", NULL, NULL );
+
+ // perform sequential cleanup
+clk = clock();
+ if ( pNew->nRegs )
+ pNew = Aig_ManReduceLaches( pNew, 0 );
+ if ( pNew->nRegs )
+ pNew = Aig_ManConstReduce( pNew, 0, -1, -1, 0, 0 );
+ if ( pParSec->fVerbose )
+ {
+ printf( "Sequential cleanup: Latches = %5d. Nodes = %6d. ",
+ Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
+ABC_PRT( "Time", clock() - clk );
+ }
+ RetValue = Fra_FraigMiterStatus( pNew );
+ if ( RetValue >= 0 )
+ goto finish;
+
+ // perform phase abstraction
+clk = clock();
+ if ( pParSec->fPhaseAbstract )
+ {
+ extern Aig_Man_t * Saig_ManPhaseAbstractAuto( Aig_Man_t * p, int fVerbose );
+ pNew->nTruePis = Aig_ManPiNum(pNew) - Aig_ManRegNum(pNew);
+ pNew->nTruePos = Aig_ManPoNum(pNew) - Aig_ManRegNum(pNew);
+ pNew = Saig_ManPhaseAbstractAuto( pTemp = pNew, 0 );
+ Aig_ManStop( pTemp );
+ if ( pParSec->fVerbose )
+ {
+ printf( "Phase abstraction: Latches = %5d. Nodes = %6d. ",
+ Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
+ABC_PRT( "Time", clock() - clk );
+ }
+ }
+
+ // perform forward retiming
+ if ( pParSec->fRetimeFirst && pNew->nRegs )
+ {
+clk = clock();
+// pNew = Rtm_ManRetime( pTemp = pNew, 1, 1000, 0 );
+ pNew = Saig_ManRetimeForward( pTemp = pNew, 100, 0 );
+ Aig_ManStop( pTemp );
+ if ( pParSec->fVerbose )
+ {
+ printf( "Forward retiming: Latches = %5d. Nodes = %6d. ",
+ Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
+ABC_PRT( "Time", clock() - clk );
+ }
+ }
+
+ // run latch correspondence
+clk = clock();
+ if ( pNew->nRegs )
+ {
+ pNew = Aig_ManDupOrdered( pTemp = pNew );
+// pNew = Aig_ManDupDfs( pTemp = pNew );
+ Aig_ManStop( pTemp );
+/*
+ if ( RetValue == -1 && pParSec->TimeLimit )
+ {
+ TimeLeft = (float)pParSec->TimeLimit - ((float)(clock()-clkTotal)/(float)(CLOCKS_PER_SEC));
+ TimeLeft = Abc_MaxInt( TimeLeft, 0.0 );
+ if ( TimeLeft == 0.0 )
+ {
+ if ( !pParSec->fSilent )
+ printf( "Runtime limit exceeded.\n" );
+ RetValue = -1;
+ TimeOut = 1;
+ goto finish;
+ }
+ }
+*/
+
+// pNew = Fra_FraigLatchCorrespondence( pTemp = pNew, 0, 1000, 1, pParSec->fVeryVerbose, &nIter, TimeLeft );
+//Aig_ManDumpBlif( pNew, "ex.blif", NULL, NULL );
+ Ssw_ManSetDefaultParamsLcorr( pPars2 );
+ pNew = Ssw_LatchCorrespondence( pTemp = pNew, pPars2 );
+ nIter = pPars2->nIters;
+
+ // prepare parameters for scorr
+ Ssw_ManSetDefaultParams( pPars2 );
+
+ if ( pTemp->pSeqModel )
+ {
+ if ( !Saig_ManVerifyCex( pTemp, pTemp->pSeqModel ) )
+ printf( "Fra_FraigSec(): Counter-example verification has FAILED.\n" );
+ if ( Saig_ManPiNum(p) != Saig_ManPiNum(pTemp) )
+ printf( "The counter-example is invalid because of phase abstraction.\n" );
+ else
+ {
+ ABC_FREE( p->pSeqModel );
+ p->pSeqModel = Abc_CexDup( pTemp->pSeqModel, Aig_ManRegNum(p) );
+ ABC_FREE( pTemp->pSeqModel );
+ }
+ }
+ if ( pNew == NULL )
+ {
+ if ( p->pSeqModel )
+ {
+ RetValue = 0;
+ if ( !pParSec->fSilent )
+ {
+ printf( "Networks are NOT EQUIVALENT after simulation. " );
+ABC_PRT( "Time", clock() - clkTotal );
+ }
+ if ( pParSec->fReportSolution && !pParSec->fRecursive )
+ {
+ printf( "SOLUTION: FAIL " );
+ABC_PRT( "Time", clock() - clkTotal );
+ }
+ Aig_ManStop( pTemp );
+ return RetValue;
+ }
+ pNew = pTemp;
+ RetValue = -1;
+ TimeOut = 1;
+ goto finish;
+ }
+ Aig_ManStop( pTemp );
+
+ if ( pParSec->fVerbose )
+ {
+ printf( "Latch-corr (I=%3d): Latches = %5d. Nodes = %6d. ",
+ nIter, Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
+ABC_PRT( "Time", clock() - clk );
+ }
+ }
+/*
+ if ( RetValue == -1 && pParSec->TimeLimit )
+ {
+ TimeLeft = (float)pParSec->TimeLimit - ((float)(clock()-clkTotal)/(float)(CLOCKS_PER_SEC));
+ TimeLeft = Abc_MaxInt( TimeLeft, 0.0 );
+ if ( TimeLeft == 0.0 )
+ {
+ if ( !pParSec->fSilent )
+ printf( "Runtime limit exceeded.\n" );
+ RetValue = -1;
+ TimeOut = 1;
+ goto finish;
+ }
+ }
+*/
+ // perform fraiging
+ if ( pParSec->fFraiging )
+ {
+clk = clock();
+ pNew = Fra_FraigEquivence( pTemp = pNew, 100, 0 );
+ Aig_ManStop( pTemp );
+ if ( pParSec->fVerbose )
+ {
+ printf( "Fraiging: Latches = %5d. Nodes = %6d. ",
+ Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
+ABC_PRT( "Time", clock() - clk );
+ }
+ }
+
+ if ( pNew->nRegs == 0 )
+ RetValue = Fra_FraigCec( &pNew, 100000, 0 );
+
+ RetValue = Fra_FraigMiterStatus( pNew );
+ if ( RetValue >= 0 )
+ goto finish;
+/*
+ if ( RetValue == -1 && pParSec->TimeLimit )
+ {
+ TimeLeft = (float)pParSec->TimeLimit - ((float)(clock()-clkTotal)/(float)(CLOCKS_PER_SEC));
+ TimeLeft = Abc_MaxInt( TimeLeft, 0.0 );
+ if ( TimeLeft == 0.0 )
+ {
+ if ( !pParSec->fSilent )
+ printf( "Runtime limit exceeded.\n" );
+ RetValue = -1;
+ TimeOut = 1;
+ goto finish;
+ }
+ }
+*/
+ // perform min-area retiming
+ if ( pParSec->fRetimeRegs && pNew->nRegs )
+ {
+// extern Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose );
+clk = clock();
+ pNew->nTruePis = Aig_ManPiNum(pNew) - Aig_ManRegNum(pNew);
+ pNew->nTruePos = Aig_ManPoNum(pNew) - Aig_ManRegNum(pNew);
+// pNew = Rtm_ManRetime( pTemp = pNew, 1, 1000, 0 );
+ pNew = Saig_ManRetimeMinArea( pTemp = pNew, 1000, 0, 0, 1, 0 );
+ Aig_ManStop( pTemp );
+ pNew = Aig_ManDupOrdered( pTemp = pNew );
+ Aig_ManStop( pTemp );
+ if ( pParSec->fVerbose )
+ {
+ printf( "Min-reg retiming: Latches = %5d. Nodes = %6d. ",
+ Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
+ABC_PRT( "Time", clock() - clk );
+ }
+ }
+
+ // perform seq sweeping while increasing the number of frames
+ RetValue = Fra_FraigMiterStatus( pNew );
+ if ( RetValue == -1 && pParSec->fInduction )
+ for ( nFrames = 1; nFrames <= pParSec->nFramesMax; nFrames *= 2 )
+ {
+/*
+ if ( RetValue == -1 && pParSec->TimeLimit )
+ {
+ TimeLeft = (float)pParSec->TimeLimit - ((float)(clock()-clkTotal)/(float)(CLOCKS_PER_SEC));
+ TimeLeft = Abc_MaxInt( TimeLeft, 0.0 );
+ if ( TimeLeft == 0.0 )
+ {
+ if ( !pParSec->fSilent )
+ printf( "Runtime limit exceeded.\n" );
+ RetValue = -1;
+ TimeOut = 1;
+ goto finish;
+ }
+ }
+*/
+
+clk = clock();
+ pPars->nFramesK = nFrames;
+ pPars->TimeLimit = TimeLeft;
+ pPars->fSilent = pParSec->fSilent;
+// pNew = Fra_FraigInduction( pTemp = pNew, pPars );
+
+ pPars2->nFramesK = nFrames;
+ pPars2->nBTLimit = pParSec->nBTLimit;
+ pPars2->nBTLimitGlobal = pParSec->nBTLimitGlobal;
+// pPars2->nBTLimit = 1000 * nFrames;
+
+ if ( RetValue == -1 && pPars2->nConflicts > pPars2->nBTLimitGlobal )
+ {
+ if ( !pParSec->fSilent )
+ printf( "Global conflict limit (%d) exceeded.\n", pPars2->nBTLimitGlobal );
+ RetValue = -1;
+ TimeOut = 1;
+ goto finish;
+ }
+
+ Aig_ManSetRegNum( pNew, pNew->nRegs );
+// pNew = Ssw_SignalCorrespondence( pTemp = pNew, pPars2 );
+ if ( Aig_ManRegNum(pNew) > 0 )
+ pNew = Ssw_SignalCorrespondence( pTemp = pNew, pPars2 );
+ else
+ pNew = Aig_ManDupSimpleDfs( pTemp = pNew );
+
+ if ( pNew == NULL )
+ {
+ pNew = pTemp;
+ RetValue = -1;
+ TimeOut = 1;
+ goto finish;
+ }
+
+// printf( "Total conflicts = %d.\n", pPars2->nConflicts );
+
+ Aig_ManStop( pTemp );
+ RetValue = Fra_FraigMiterStatus( pNew );
+ if ( pParSec->fVerbose )
+ {
+ printf( "K-step (K=%2d,I=%3d): Latches = %5d. Nodes = %6d. ",
+ nFrames, pPars2->nIters, Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
+ABC_PRT( "Time", clock() - clk );
+ }
+ if ( RetValue != -1 )
+ break;
+
+ // perform retiming
+// if ( pParSec->fRetimeFirst && pNew->nRegs )
+ if ( pNew->nRegs )
+ {
+// extern Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose );
+clk = clock();
+ pNew->nTruePis = Aig_ManPiNum(pNew) - Aig_ManRegNum(pNew);
+ pNew->nTruePos = Aig_ManPoNum(pNew) - Aig_ManRegNum(pNew);
+// pNew = Rtm_ManRetime( pTemp = pNew, 1, 1000, 0 );
+ pNew = Saig_ManRetimeMinArea( pTemp = pNew, 1000, 0, 0, 1, 0 );
+ Aig_ManStop( pTemp );
+ pNew = Aig_ManDupOrdered( pTemp = pNew );
+ Aig_ManStop( pTemp );
+ if ( pParSec->fVerbose )
+ {
+ printf( "Min-reg retiming: Latches = %5d. Nodes = %6d. ",
+ Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
+ABC_PRT( "Time", clock() - clk );
+ }
+ }
+
+ if ( pNew->nRegs )
+ pNew = Aig_ManConstReduce( pNew, 0, -1, -1, 0, 0 );
+
+ // perform rewriting
+clk = clock();
+ pNew = Aig_ManDupOrdered( pTemp = pNew );
+ Aig_ManStop( pTemp );
+// pNew = Dar_ManRewriteDefault( pTemp = pNew );
+ pNew = Dar_ManCompress2( pTemp = pNew, 1, 0, 1, 0, 0 );
+ Aig_ManStop( pTemp );
+ if ( pParSec->fVerbose )
+ {
+ printf( "Rewriting: Latches = %5d. Nodes = %6d. ",
+ Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
+ABC_PRT( "Time", clock() - clk );
+ }
+
+ // perform sequential simulation
+ if ( pNew->nRegs )
+ {
+clk = clock();
+ pSml = Fra_SmlSimulateSeq( pNew, 0, 128 * nFrames, 1 + 16/(1+Aig_ManNodeNum(pNew)/1000), 1 );
+ if ( pParSec->fVerbose )
+ {
+ printf( "Seq simulation : Latches = %5d. Nodes = %6d. ",
+ Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) );
+ABC_PRT( "Time", clock() - clk );
+ }
+ if ( pSml->fNonConstOut )
+ {
+ pNew->pSeqModel = Fra_SmlGetCounterExample( pSml );
+ // transfer to the original manager
+ if ( Saig_ManPiNum(p) != Saig_ManPiNum(pNew) )
+ printf( "The counter-example is invalid because of phase abstraction.\n" );
+ else
+ {
+ ABC_FREE( p->pSeqModel );
+ p->pSeqModel = Abc_CexDup( pNew->pSeqModel, Aig_ManRegNum(p) );
+ ABC_FREE( pNew->pSeqModel );
+ }
+
+ Fra_SmlStop( pSml );
+ Aig_ManStop( pNew );
+ RetValue = 0;
+ if ( !pParSec->fSilent )
+ {
+ printf( "Networks are NOT EQUIVALENT after simulation. " );
+ABC_PRT( "Time", clock() - clkTotal );
+ }
+ if ( pParSec->fReportSolution && !pParSec->fRecursive )
+ {
+ printf( "SOLUTION: FAIL " );
+ABC_PRT( "Time", clock() - clkTotal );
+ }
+ return RetValue;
+ }
+ Fra_SmlStop( pSml );
+ }
+ }
+
+ // get the miter status
+ RetValue = Fra_FraigMiterStatus( pNew );
+
+ // try interplation
+clk = clock();
+ Aig_ManSetRegNum( pNew, Aig_ManRegNum(pNew) );
+ if ( pParSec->fInterpolation && RetValue == -1 && Aig_ManRegNum(pNew) > 0 )
+ {
+ Inter_ManParams_t Pars, * pPars = &Pars;
+ int Depth;
+ ABC_FREE( pNew->pSeqModel );
+ Inter_ManSetDefaultParams( pPars );
+// pPars->nBTLimit = 100;
+ pPars->nBTLimit = pParSec->nBTLimitInter;
+ pPars->fVerbose = pParSec->fVeryVerbose;
+ if ( Saig_ManPoNum(pNew) == 1 )
+ {
+ RetValue = Inter_ManPerformInterpolation( pNew, pPars, &Depth );
+ }
+ else if ( pParSec->fInterSeparate )
+ {
+ Abc_Cex_t * pCex = NULL;
+ Aig_Man_t * pTemp, * pAux;
+ Aig_Obj_t * pObjPo;
+ int i, Counter = 0;
+ Saig_ManForEachPo( pNew, pObjPo, i )
+ {
+ if ( Aig_ObjFanin0(pObjPo) == Aig_ManConst1(pNew) )
+ continue;
+ if ( pPars->fVerbose )
+ printf( "Solving output %2d (out of %2d):\n", i, Saig_ManPoNum(pNew) );
+ pTemp = Aig_ManDupOneOutput( pNew, i, 1 );
+ pTemp = Aig_ManScl( pAux = pTemp, 1, 1, 0, -1, -1, 0, 0 );
+ Aig_ManStop( pAux );
+ if ( Saig_ManRegNum(pTemp) > 0 )
+ {
+ RetValue = Inter_ManPerformInterpolation( pTemp, pPars, &Depth );
+ if ( pTemp->pSeqModel )
+ {
+ pCex = p->pSeqModel = Abc_CexDup( pTemp->pSeqModel, Aig_ManRegNum(p) );
+ pCex->iPo = i;
+ Aig_ManStop( pTemp );
+ break;
+ }
+ // if solved, remove the output
+ if ( RetValue == 1 )
+ {
+ Aig_ObjPatchFanin0( pNew, pObjPo, Aig_ManConst0(pNew) );
+ // printf( "Output %3d : Solved ", i );
+ }
+ else
+ {
+ Counter++;
+ // printf( "Output %3d : Undec ", i );
+ }
+ }
+ else
+ Counter++;
+// Aig_ManPrintStats( pTemp );
+ Aig_ManStop( pTemp );
+ printf( "Solving output %3d (out of %3d) using interpolation.\r", i, Saig_ManPoNum(pNew) );
+ }
+ Aig_ManCleanup( pNew );
+ if ( pCex == NULL )
+ {
+ printf( "Interpolation left %d (out of %d) outputs unsolved \n", Counter, Saig_ManPoNum(pNew) );
+ if ( Counter )
+ RetValue = -1;
+ }
+ pNew = Aig_ManDupUnsolvedOutputs( pTemp = pNew, 1 );
+ Aig_ManStop( pTemp );
+ pNew = Aig_ManScl( pTemp = pNew, 1, 1, 0, -1, -1, 0, 0 );
+ Aig_ManStop( pTemp );
+ }
+ else
+ {
+ Aig_Man_t * pNewOrpos = Saig_ManDupOrpos( pNew );
+ RetValue = Inter_ManPerformInterpolation( pNewOrpos, pPars, &Depth );
+ if ( pNewOrpos->pSeqModel )
+ {
+ Abc_Cex_t * pCex;
+ pCex = pNew->pSeqModel = pNewOrpos->pSeqModel; pNewOrpos->pSeqModel = NULL;
+ pCex->iPo = Saig_ManFindFailedPoCex( pNew, pNew->pSeqModel );
+ }
+ Aig_ManStop( pNewOrpos );
+ }
+
+ if ( pParSec->fVerbose )
+ {
+ if ( RetValue == 1 )
+ printf( "Property proved using interpolation. " );
+ else if ( RetValue == 0 )
+ printf( "Property DISPROVED in frame %d using interpolation. ", Depth );
+ else if ( RetValue == -1 )
+ printf( "Property UNDECIDED after interpolation. " );
+ else
+ assert( 0 );
+ABC_PRT( "Time", clock() - clk );
+ }
+ }
+
+ // try reachability analysis
+ if ( pParSec->fReachability && RetValue == -1 && Aig_ManRegNum(pNew) > 0 && Aig_ManRegNum(pNew) < pParSec->nBddVarsMax )
+ {
+ Saig_ParBbr_t Pars, * pPars = &Pars;
+ Bbr_ManSetDefaultParams( pPars );
+ pPars->TimeLimit = 0;
+ pPars->nBddMax = pParSec->nBddMax;
+ pPars->nIterMax = pParSec->nBddIterMax;
+ pPars->fPartition = 1;
+ pPars->fReorder = 1;
+ pPars->fReorderImage = 1;
+ pPars->fVerbose = 0;
+ pPars->fSilent = pParSec->fSilent;
+ pNew->nTruePis = Aig_ManPiNum(pNew) - Aig_ManRegNum(pNew);
+ pNew->nTruePos = Aig_ManPoNum(pNew) - Aig_ManRegNum(pNew);
+ RetValue = Aig_ManVerifyUsingBdds( pNew, pPars );
+ }
+
+ // try PDR
+ if ( pParSec->fUsePdr && RetValue == -1 && Aig_ManRegNum(pNew) > 0 )
+ {
+ Abc_Cex_t * pCex = NULL;
+ Aig_Man_t * pNewOrpos = Saig_ManDupOrpos( pNew );
+ Pdr_Par_t Pars, * pPars = &Pars;
+ Pdr_ManSetDefaultParams( pPars );
+ pPars->nTimeOut = pParSec->nPdrTimeout;
+ pPars->fVerbose = pParSec->fVerbose;
+ if ( pParSec->fVerbose )
+ printf( "Running property directed reachability...\n" );
+ RetValue = Pdr_ManSolve( pNewOrpos, pPars, &pCex );
+ if ( pCex )
+ pCex->iPo = Saig_ManFindFailedPoCex( pNew, pCex );
+ Aig_ManStop( pNewOrpos );
+ pNew->pSeqModel = pCex;
+ }
+
+finish:
+ // report the miter
+ if ( RetValue == 1 )
+ {
+ if ( !pParSec->fSilent )
+ {
+ printf( "Networks are equivalent. " );
+ABC_PRT( "Time", clock() - clkTotal );
+ }
+ if ( pParSec->fReportSolution && !pParSec->fRecursive )
+ {
+ printf( "SOLUTION: PASS " );
+ABC_PRT( "Time", clock() - clkTotal );
+ }
+ }
+ else if ( RetValue == 0 )
+ {
+ if ( pNew->pSeqModel == NULL )
+ {
+ int i;
+ // if the CEX is not derives, it is because tricial CEX should be assumed
+ pNew->pSeqModel = Abc_CexAlloc( Aig_ManRegNum(pNew), pNew->nTruePis, 1 );
+ // if the CEX does not work, we need to change PIs to 1 because
+ // the only way it can happen is when a PO is equal to a PI...
+ if ( Saig_ManFindFailedPoCex( pNew, pNew->pSeqModel ) == -1 )
+ for ( i = 0; i < pNew->nTruePis; i++ )
+ Abc_InfoSetBit( pNew->pSeqModel->pData, i );
+ }
+ if ( !pParSec->fSilent )
+ {
+ printf( "Networks are NOT EQUIVALENT. " );
+ABC_PRT( "Time", clock() - clkTotal );
+ }
+ if ( pParSec->fReportSolution && !pParSec->fRecursive )
+ {
+ printf( "SOLUTION: FAIL " );
+ABC_PRT( "Time", clock() - clkTotal );
+ }
+ }
+ else
+ {
+ ///////////////////////////////////
+ // save intermediate result
+ extern void Abc_FrameSetSave1( void * pAig );
+ Abc_FrameSetSave1( Aig_ManDupSimple(pNew) );
+ ///////////////////////////////////
+ if ( !pParSec->fSilent )
+ {
+ printf( "Networks are UNDECIDED. " );
+ABC_PRT( "Time", clock() - clkTotal );
+ }
+ if ( pParSec->fReportSolution && !pParSec->fRecursive )
+ {
+ printf( "SOLUTION: UNDECIDED " );
+ABC_PRT( "Time", clock() - clkTotal );
+ }
+ if ( !TimeOut && !pParSec->fSilent )
+ {
+ static int Counter = 1;
+ char pFileName[1000];
+ pParSec->nSMnumber = Counter;
+ sprintf( pFileName, "sm%02d.aig", Counter++ );
+ Ioa_WriteAiger( pNew, pFileName, 0, 0 );
+ printf( "The unsolved reduced miter is written into file \"%s\".\n", pFileName );
+ }
+ }
+ if ( pNew->pSeqModel )
+ {
+ if ( Saig_ManPiNum(p) != Saig_ManPiNum(pNew) )
+ printf( "The counter-example is invalid because of phase abstraction.\n" );
+ else
+ {
+ ABC_FREE( p->pSeqModel );
+ p->pSeqModel = Abc_CexDup( pNew->pSeqModel, Aig_ManRegNum(p) );
+ ABC_FREE( pNew->pSeqModel );
+ }
+ }
+ if ( ppResult != NULL )
+ *ppResult = Aig_ManDupSimpleDfs( pNew );
+ if ( pNew )
+ Aig_ManStop( pNew );
+ return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fra/fraSim.c b/src/proof/fra/fraSim.c
new file mode 100644
index 00000000..eb42c665
--- /dev/null
+++ b/src/proof/fra/fraSim.c
@@ -0,0 +1,1023 @@
+/**CFile****************************************************************
+
+ FileName [fraSim.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: fraSim.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+#include "src/aig/saig/saig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes hash value of the node using its simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_SmlNodeHash( Aig_Obj_t * pObj, int nTableSize )
+{
+ Fra_Man_t * p = (Fra_Man_t *)pObj->pData;
+ static int s_FPrimes[128] = {
+ 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459,
+ 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997,
+ 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543,
+ 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089,
+ 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671,
+ 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243,
+ 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871,
+ 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471,
+ 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073,
+ 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689,
+ 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309,
+ 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933,
+ 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
+ };
+ unsigned * pSims;
+ unsigned uHash;
+ int i;
+// assert( p->pSml->nWordsTotal <= 128 );
+ uHash = 0;
+ pSims = Fra_ObjSim(p->pSml, pObj->Id);
+ for ( i = p->pSml->nWordsPref; i < p->pSml->nWordsTotal; i++ )
+ uHash ^= pSims[i] * s_FPrimes[i & 0x7F];
+ return uHash % nTableSize;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if simulation info is composed of all zeros.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_SmlNodeIsConst( Aig_Obj_t * pObj )
+{
+ Fra_Man_t * p = (Fra_Man_t *)pObj->pData;
+ unsigned * pSims;
+ int i;
+ pSims = Fra_ObjSim(p->pSml, pObj->Id);
+ for ( i = p->pSml->nWordsPref; i < p->pSml->nWordsTotal; i++ )
+ if ( pSims[i] )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if simulation infos are equal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_SmlNodesAreEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
+{
+ Fra_Man_t * p = (Fra_Man_t *)pObj0->pData;
+ unsigned * pSims0, * pSims1;
+ int i;
+ pSims0 = Fra_ObjSim(p->pSml, pObj0->Id);
+ pSims1 = Fra_ObjSim(p->pSml, pObj1->Id);
+ for ( i = p->pSml->nWordsPref; i < p->pSml->nWordsTotal; i++ )
+ if ( pSims0[i] != pSims1[i] )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of 1s in the XOR of simulation data.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_SmlNodeNotEquWeight( Fra_Sml_t * p, int Left, int Right )
+{
+ unsigned * pSimL, * pSimR;
+ int k, Counter = 0;
+ pSimL = Fra_ObjSim( p, Left );
+ pSimR = Fra_ObjSim( p, Right );
+ for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
+ Counter += Aig_WordCountOnes( pSimL[k] ^ pSimR[k] );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if simulation info is composed of all zeros.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_SmlNodeIsZero( Fra_Sml_t * p, Aig_Obj_t * pObj )
+{
+ unsigned * pSims;
+ int i;
+ pSims = Fra_ObjSim(p, pObj->Id);
+ for ( i = p->nWordsPref; i < p->nWordsTotal; i++ )
+ if ( pSims[i] )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of one's in the patten of the output.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_SmlNodeCountOnes( Fra_Sml_t * p, Aig_Obj_t * pObj )
+{
+ unsigned * pSims;
+ int i, Counter = 0;
+ pSims = Fra_ObjSim(p, pObj->Id);
+ for ( i = 0; i < p->nWordsTotal; i++ )
+ Counter += Aig_WordCountOnes( pSims[i] );
+ return Counter;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Generated const 0 pattern.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_SmlSavePattern0( Fra_Man_t * p, int fInit )
+{
+ memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords );
+}
+
+/**Function*************************************************************
+
+ Synopsis [[Generated const 1 pattern.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_SmlSavePattern1( Fra_Man_t * p, int fInit )
+{
+ Aig_Obj_t * pObj;
+ int i, k, nTruePis;
+ memset( p->pPatWords, 0xff, sizeof(unsigned) * p->nPatWords );
+ if ( !fInit )
+ return;
+ // clear the state bits to correspond to all-0 initial state
+ nTruePis = Aig_ManPiNum(p->pManAig) - Aig_ManRegNum(p->pManAig);
+ k = 0;
+ Aig_ManForEachLoSeq( p->pManAig, pObj, i )
+ Abc_InfoXorBit( p->pPatWords, nTruePis * p->nFramesAll + k++ );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Copy pattern from the solver into the internal storage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_SmlSavePattern( Fra_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords );
+ Aig_ManForEachPi( p->pManFraig, pObj, i )
+// if ( p->pSat->model.ptr[Fra_ObjSatNum(pObj)] == l_True )
+ if ( sat_solver_var_value(p->pSat, Fra_ObjSatNum(pObj)) )
+ Abc_InfoSetBit( p->pPatWords, i );
+
+ if ( p->vCex )
+ {
+ Vec_IntClear( p->vCex );
+ for ( i = 0; i < Aig_ManPiNum(p->pManAig) - Aig_ManRegNum(p->pManAig); i++ )
+ Vec_IntPush( p->vCex, Abc_InfoHasBit( p->pPatWords, i ) );
+ for ( i = Aig_ManPiNum(p->pManFraig) - Aig_ManRegNum(p->pManFraig); i < Aig_ManPiNum(p->pManFraig); i++ )
+ Vec_IntPush( p->vCex, Abc_InfoHasBit( p->pPatWords, i ) );
+ }
+
+/*
+ printf( "Pattern: " );
+ Aig_ManForEachPi( p->pManFraig, pObj, i )
+ printf( "%d", Abc_InfoHasBit( p->pPatWords, i ) );
+ printf( "\n" );
+*/
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Creates the counter-example from the successful pattern.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_SmlCheckOutputSavePattern( Fra_Man_t * p, Aig_Obj_t * pObjPo )
+{
+ Aig_Obj_t * pFanin, * pObjPi;
+ unsigned * pSims;
+ int i, k, BestPat, * pModel;
+ // find the word of the pattern
+ pFanin = Aig_ObjFanin0(pObjPo);
+ pSims = Fra_ObjSim(p->pSml, pFanin->Id);
+ for ( i = 0; i < p->pSml->nWordsTotal; i++ )
+ if ( pSims[i] )
+ break;
+ assert( i < p->pSml->nWordsTotal );
+ // find the bit of the pattern
+ for ( k = 0; k < 32; k++ )
+ if ( pSims[i] & (1 << k) )
+ break;
+ assert( k < 32 );
+ // determine the best pattern
+ BestPat = i * 32 + k;
+ // fill in the counter-example data
+ pModel = ABC_ALLOC( int, Aig_ManPiNum(p->pManFraig)+1 );
+ Aig_ManForEachPi( p->pManAig, pObjPi, i )
+ {
+ pModel[i] = Abc_InfoHasBit(Fra_ObjSim(p->pSml, pObjPi->Id), BestPat);
+// printf( "%d", pModel[i] );
+ }
+ pModel[Aig_ManPiNum(p->pManAig)] = pObjPo->Id;
+// printf( "\n" );
+ // set the model
+ assert( p->pManFraig->pData == NULL );
+ p->pManFraig->pData = pModel;
+ return;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the one of the output is already non-constant 0.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_SmlCheckOutput( Fra_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ // make sure the reference simulation pattern does not detect the bug
+ pObj = Aig_ManPo( p->pManAig, 0 );
+ assert( Aig_ObjFanin0(pObj)->fPhase == (unsigned)Aig_ObjFaninC0(pObj) );
+ Aig_ManForEachPo( p->pManAig, pObj, i )
+ {
+ if ( !Fra_SmlNodeIsConst( Aig_ObjFanin0(pObj) ) )
+ {
+ // create the counter-example from this pattern
+ Fra_SmlCheckOutputSavePattern( p, pObj );
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Assigns random patterns to the PI node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_SmlAssignRandom( Fra_Sml_t * p, Aig_Obj_t * pObj )
+{
+ unsigned * pSims;
+ int i;
+ assert( Aig_ObjIsPi(pObj) );
+ pSims = Fra_ObjSim( p, pObj->Id );
+ for ( i = 0; i < p->nWordsTotal; i++ )
+ pSims[i] = Fra_ObjRandomSim();
+}
+
+/**Function*************************************************************
+
+ Synopsis [Assigns constant patterns to the PI node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_SmlAssignConst( Fra_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame )
+{
+ unsigned * pSims;
+ int i;
+ assert( Aig_ObjIsPi(pObj) );
+ pSims = Fra_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame;
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = fConst1? ~(unsigned)0 : 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Assings random simulation info for the PIs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_SmlInitialize( Fra_Sml_t * p, int fInit )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ if ( fInit )
+ {
+ assert( Aig_ManRegNum(p->pAig) > 0 );
+ assert( Aig_ManRegNum(p->pAig) < Aig_ManPiNum(p->pAig) );
+ // assign random info for primary inputs
+ Aig_ManForEachPiSeq( p->pAig, pObj, i )
+ Fra_SmlAssignRandom( p, pObj );
+ // assign the initial state for the latches
+ Aig_ManForEachLoSeq( p->pAig, pObj, i )
+ Fra_SmlAssignConst( p, pObj, 0, 0 );
+ }
+ else
+ {
+ Aig_ManForEachPi( p->pAig, pObj, i )
+ Fra_SmlAssignRandom( p, pObj );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Assings distance-1 simulation info for the PIs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_SmlAssignDist1( Fra_Sml_t * p, unsigned * pPat )
+{
+ Aig_Obj_t * pObj;
+ int f, i, k, Limit, nTruePis;
+ assert( p->nFrames > 0 );
+ if ( p->nFrames == 1 )
+ {
+ // copy the PI info
+ Aig_ManForEachPi( p->pAig, pObj, i )
+ Fra_SmlAssignConst( p, pObj, Abc_InfoHasBit(pPat, i), 0 );
+ // flip one bit
+ Limit = Abc_MinInt( Aig_ManPiNum(p->pAig), p->nWordsTotal * 32 - 1 );
+ for ( i = 0; i < Limit; i++ )
+ Abc_InfoXorBit( Fra_ObjSim( p, Aig_ManPi(p->pAig,i)->Id ), i+1 );
+ }
+ else
+ {
+ int fUseDist1 = 0;
+
+ // copy the PI info for each frame
+ nTruePis = Aig_ManPiNum(p->pAig) - Aig_ManRegNum(p->pAig);
+ for ( f = 0; f < p->nFrames; f++ )
+ Aig_ManForEachPiSeq( p->pAig, pObj, i )
+ Fra_SmlAssignConst( p, pObj, Abc_InfoHasBit(pPat, nTruePis * f + i), f );
+ // copy the latch info
+ k = 0;
+ Aig_ManForEachLoSeq( p->pAig, pObj, i )
+ Fra_SmlAssignConst( p, pObj, Abc_InfoHasBit(pPat, nTruePis * p->nFrames + k++), 0 );
+// assert( p->pManFraig == NULL || nTruePis * p->nFrames + k == Aig_ManPiNum(p->pManFraig) );
+
+ // flip one bit of the last frame
+ if ( fUseDist1 ) //&& p->nFrames == 2 )
+ {
+ Limit = Abc_MinInt( nTruePis, p->nWordsFrame * 32 - 1 );
+ for ( i = 0; i < Limit; i++ )
+ Abc_InfoXorBit( Fra_ObjSim( p, Aig_ManPi(p->pAig, i)->Id ) + p->nWordsFrame*(p->nFrames-1), i+1 );
+ }
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_SmlNodeSimulate( Fra_Sml_t * p, Aig_Obj_t * pObj, int iFrame )
+{
+ unsigned * pSims, * pSims0, * pSims1;
+ int fCompl, fCompl0, fCompl1, i;
+ assert( !Aig_IsComplement(pObj) );
+ assert( Aig_ObjIsNode(pObj) );
+ assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal );
+ // get hold of the simulation information
+ pSims = Fra_ObjSim(p, pObj->Id) + p->nWordsFrame * iFrame;
+ pSims0 = Fra_ObjSim(p, Aig_ObjFanin0(pObj)->Id) + p->nWordsFrame * iFrame;
+ pSims1 = Fra_ObjSim(p, Aig_ObjFanin1(pObj)->Id) + p->nWordsFrame * iFrame;
+ // get complemented attributes of the children using their random info
+ fCompl = pObj->fPhase;
+ fCompl0 = Aig_ObjPhaseReal(Aig_ObjChild0(pObj));
+ fCompl1 = Aig_ObjPhaseReal(Aig_ObjChild1(pObj));
+ // simulate
+ if ( fCompl0 && fCompl1 )
+ {
+ if ( fCompl )
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = (pSims0[i] | pSims1[i]);
+ else
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = ~(pSims0[i] | pSims1[i]);
+ }
+ else if ( fCompl0 && !fCompl1 )
+ {
+ if ( fCompl )
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = (pSims0[i] | ~pSims1[i]);
+ else
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = (~pSims0[i] & pSims1[i]);
+ }
+ else if ( !fCompl0 && fCompl1 )
+ {
+ if ( fCompl )
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = (~pSims0[i] | pSims1[i]);
+ else
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = (pSims0[i] & ~pSims1[i]);
+ }
+ else // if ( !fCompl0 && !fCompl1 )
+ {
+ if ( fCompl )
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = ~(pSims0[i] & pSims1[i]);
+ else
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = (pSims0[i] & pSims1[i]);
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_SmlNodesCompareInFrame( Fra_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1, int iFrame0, int iFrame1 )
+{
+ unsigned * pSims0, * pSims1;
+ int i;
+ assert( !Aig_IsComplement(pObj0) );
+ assert( !Aig_IsComplement(pObj1) );
+ assert( iFrame0 == 0 || p->nWordsFrame < p->nWordsTotal );
+ assert( iFrame1 == 0 || p->nWordsFrame < p->nWordsTotal );
+ // get hold of the simulation information
+ pSims0 = Fra_ObjSim(p, pObj0->Id) + p->nWordsFrame * iFrame0;
+ pSims1 = Fra_ObjSim(p, pObj1->Id) + p->nWordsFrame * iFrame1;
+ // compare
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ if ( pSims0[i] != pSims1[i] )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_SmlNodeCopyFanin( Fra_Sml_t * p, Aig_Obj_t * pObj, int iFrame )
+{
+ unsigned * pSims, * pSims0;
+ int fCompl, fCompl0, i;
+ assert( !Aig_IsComplement(pObj) );
+ assert( Aig_ObjIsPo(pObj) );
+ assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal );
+ // get hold of the simulation information
+ pSims = Fra_ObjSim(p, pObj->Id) + p->nWordsFrame * iFrame;
+ pSims0 = Fra_ObjSim(p, Aig_ObjFanin0(pObj)->Id) + p->nWordsFrame * iFrame;
+ // get complemented attributes of the children using their random info
+ fCompl = pObj->fPhase;
+ fCompl0 = Aig_ObjPhaseReal(Aig_ObjChild0(pObj));
+ // copy information as it is
+ if ( fCompl0 )
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = ~pSims0[i];
+ else
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = pSims0[i];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_SmlNodeTransferNext( Fra_Sml_t * p, Aig_Obj_t * pOut, Aig_Obj_t * pIn, int iFrame )
+{
+ unsigned * pSims0, * pSims1;
+ int i;
+ assert( !Aig_IsComplement(pOut) );
+ assert( !Aig_IsComplement(pIn) );
+ assert( Aig_ObjIsPo(pOut) );
+ assert( Aig_ObjIsPi(pIn) );
+ assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal );
+ // get hold of the simulation information
+ pSims0 = Fra_ObjSim(p, pOut->Id) + p->nWordsFrame * iFrame;
+ pSims1 = Fra_ObjSim(p, pIn->Id) + p->nWordsFrame * (iFrame+1);
+ // copy information as it is
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims1[i] = pSims0[i];
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Check if any of the POs becomes non-constant.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fra_SmlCheckNonConstOutputs( Fra_Sml_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Aig_ManForEachPoSeq( p->pAig, pObj, i )
+ if ( !Fra_SmlNodeIsZero(p, pObj) )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates AIG manager.]
+
+ Description [Assumes that the PI simulation info is attached.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_SmlSimulateOne( Fra_Sml_t * p )
+{
+ Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+ int f, i, clk;
+clk = clock();
+ for ( f = 0; f < p->nFrames; f++ )
+ {
+ // simulate the nodes
+ Aig_ManForEachNode( p->pAig, pObj, i )
+ Fra_SmlNodeSimulate( p, pObj, f );
+ // copy simulation info into outputs
+ Aig_ManForEachPoSeq( p->pAig, pObj, i )
+ Fra_SmlNodeCopyFanin( p, pObj, f );
+ // quit if this is the last timeframe
+ if ( f == p->nFrames - 1 )
+ break;
+ // copy simulation info into outputs
+ Aig_ManForEachLiSeq( p->pAig, pObj, i )
+ Fra_SmlNodeCopyFanin( p, pObj, f );
+ // copy simulation info into the inputs
+ Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObjLo, i )
+ Fra_SmlNodeTransferNext( p, pObjLi, pObjLo, f );
+ }
+p->timeSim += clock() - clk;
+p->nSimRounds++;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Resimulates fraiging manager after finding a counter-example.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_SmlResimulate( Fra_Man_t * p )
+{
+ int nChanges, clk;
+ Fra_SmlAssignDist1( p->pSml, p->pPatWords );
+ Fra_SmlSimulateOne( p->pSml );
+// if ( p->pPars->fPatScores )
+// Fra_CleanPatScores( p );
+ if ( p->pPars->fProve && Fra_SmlCheckOutput(p) )
+ return;
+clk = clock();
+ nChanges = Fra_ClassesRefine( p->pCla );
+ nChanges += Fra_ClassesRefine1( p->pCla, 1, NULL );
+ if ( p->pCla->vImps )
+ nChanges += Fra_ImpRefineUsingCex( p, p->pCla->vImps );
+ if ( p->vOneHots )
+ nChanges += Fra_OneHotRefineUsingCex( p, p->vOneHots );
+p->timeRef += clock() - clk;
+ if ( !p->pPars->nFramesK && nChanges < 1 )
+ printf( "Error: A counter-example did not refine classes!\n" );
+// assert( nChanges >= 1 );
+//printf( "Refined classes = %5d. Changes = %4d.\n", Vec_PtrSize(p->vClasses), nChanges );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs simulation of the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_SmlSimulate( Fra_Man_t * p, int fInit )
+{
+ int fVerbose = 0;
+ int nChanges, nClasses, clk;
+ assert( !fInit || Aig_ManRegNum(p->pManAig) );
+ // start the classes
+ Fra_SmlInitialize( p->pSml, fInit );
+ Fra_SmlSimulateOne( p->pSml );
+ if ( p->pPars->fProve && Fra_SmlCheckOutput(p) )
+ return;
+ Fra_ClassesPrepare( p->pCla, p->pPars->fLatchCorr, 0 );
+// Fra_ClassesPrint( p->pCla, 0 );
+if ( fVerbose )
+printf( "Starting classes = %5d. Lits = %6d.\n", Vec_PtrSize(p->pCla->vClasses), Fra_ClassesCountLits(p->pCla) );
+
+//return;
+
+ // refine classes by walking 0/1 patterns
+ Fra_SmlSavePattern0( p, fInit );
+ Fra_SmlAssignDist1( p->pSml, p->pPatWords );
+ Fra_SmlSimulateOne( p->pSml );
+ if ( p->pPars->fProve && Fra_SmlCheckOutput(p) )
+ return;
+clk = clock();
+ nChanges = Fra_ClassesRefine( p->pCla );
+ nChanges += Fra_ClassesRefine1( p->pCla, 1, NULL );
+p->timeRef += clock() - clk;
+if ( fVerbose )
+printf( "Refined classes = %5d. Changes = %4d. Lits = %6d.\n", Vec_PtrSize(p->pCla->vClasses), nChanges, Fra_ClassesCountLits(p->pCla) );
+ Fra_SmlSavePattern1( p, fInit );
+ Fra_SmlAssignDist1( p->pSml, p->pPatWords );
+ Fra_SmlSimulateOne( p->pSml );
+ if ( p->pPars->fProve && Fra_SmlCheckOutput(p) )
+ return;
+clk = clock();
+ nChanges = Fra_ClassesRefine( p->pCla );
+ nChanges += Fra_ClassesRefine1( p->pCla, 1, NULL );
+p->timeRef += clock() - clk;
+
+if ( fVerbose )
+printf( "Refined classes = %5d. Changes = %4d. Lits = %6d.\n", Vec_PtrSize(p->pCla->vClasses), nChanges, Fra_ClassesCountLits(p->pCla) );
+ // refine classes by random simulation
+ do {
+ Fra_SmlInitialize( p->pSml, fInit );
+ Fra_SmlSimulateOne( p->pSml );
+ nClasses = Vec_PtrSize(p->pCla->vClasses);
+ if ( p->pPars->fProve && Fra_SmlCheckOutput(p) )
+ return;
+clk = clock();
+ nChanges = Fra_ClassesRefine( p->pCla );
+ nChanges += Fra_ClassesRefine1( p->pCla, 1, NULL );
+p->timeRef += clock() - clk;
+if ( fVerbose )
+printf( "Refined classes = %5d. Changes = %4d. Lits = %6d.\n", Vec_PtrSize(p->pCla->vClasses), nChanges, Fra_ClassesCountLits(p->pCla) );
+ } while ( (double)nChanges / nClasses > p->pPars->dSimSatur );
+
+// if ( p->pPars->fVerbose )
+// printf( "Consts = %6d. Classes = %6d. Literals = %6d.\n",
+// Vec_PtrSize(p->pCla->vClasses1), Vec_PtrSize(p->pCla->vClasses), Fra_ClassesCountLits(p->pCla) );
+// Fra_ClassesPrint( p->pCla, 0 );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Allocates simulation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fra_Sml_t * Fra_SmlStart( Aig_Man_t * pAig, int nPref, int nFrames, int nWordsFrame )
+{
+ Fra_Sml_t * p;
+ p = (Fra_Sml_t *)ABC_ALLOC( char, sizeof(Fra_Sml_t) + sizeof(unsigned) * Aig_ManObjNumMax(pAig) * (nPref + nFrames) * nWordsFrame );
+ memset( p, 0, sizeof(Fra_Sml_t) + sizeof(unsigned) * (nPref + nFrames) * nWordsFrame );
+ p->pAig = pAig;
+ p->nPref = nPref;
+ p->nFrames = nPref + nFrames;
+ p->nWordsFrame = nWordsFrame;
+ p->nWordsTotal = (nPref + nFrames) * nWordsFrame;
+ p->nWordsPref = nPref * nWordsFrame;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates simulation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fra_SmlStop( Fra_Sml_t * p )
+{
+ ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs simulation of the uninitialized circuit.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fra_Sml_t * Fra_SmlSimulateComb( Aig_Man_t * pAig, int nWords )
+{
+ Fra_Sml_t * p;
+ p = Fra_SmlStart( pAig, 0, 1, nWords );
+ Fra_SmlInitialize( p, 0 );
+ Fra_SmlSimulateOne( p );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs simulation of the initialized circuit.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fra_Sml_t * Fra_SmlSimulateSeq( Aig_Man_t * pAig, int nPref, int nFrames, int nWords, int fCheckMiter )
+{
+ Fra_Sml_t * p;
+ p = Fra_SmlStart( pAig, nPref, nFrames, nWords );
+ Fra_SmlInitialize( p, 1 );
+ Fra_SmlSimulateOne( p );
+ if ( fCheckMiter )
+ p->fNonConstOut = Fra_SmlCheckNonConstOutputs( p );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates sequential counter-example from the simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Cex_t * Fra_SmlGetCounterExample( Fra_Sml_t * p )
+{
+ Abc_Cex_t * pCex;
+ Aig_Obj_t * pObj;
+ unsigned * pSims;
+ int iPo, iFrame, iBit, i, k;
+
+ // make sure the simulation manager has it
+ assert( p->fNonConstOut );
+
+ // find the first output that failed
+ iPo = -1;
+ iBit = -1;
+ iFrame = -1;
+ Aig_ManForEachPoSeq( p->pAig, pObj, iPo )
+ {
+ if ( Fra_SmlNodeIsZero(p, pObj) )
+ continue;
+ pSims = Fra_ObjSim( p, pObj->Id );
+ for ( i = p->nWordsPref; i < p->nWordsTotal; i++ )
+ if ( pSims[i] )
+ {
+ iFrame = i / p->nWordsFrame;
+ iBit = 32 * (i % p->nWordsFrame) + Aig_WordFindFirstBit( pSims[i] );
+ break;
+ }
+ break;
+ }
+ assert( iPo < Aig_ManPoNum(p->pAig)-Aig_ManRegNum(p->pAig) );
+ assert( iFrame < p->nFrames );
+ assert( iBit < 32 * p->nWordsFrame );
+
+ // allocate the counter example
+ pCex = Abc_CexAlloc( Aig_ManRegNum(p->pAig), Aig_ManPiNum(p->pAig) - Aig_ManRegNum(p->pAig), iFrame + 1 );
+ pCex->iPo = iPo;
+ pCex->iFrame = iFrame;
+
+ // copy the bit data
+ Aig_ManForEachLoSeq( p->pAig, pObj, k )
+ {
+ pSims = Fra_ObjSim( p, pObj->Id );
+ if ( Abc_InfoHasBit( pSims, iBit ) )
+ Abc_InfoSetBit( pCex->pData, k );
+ }
+ for ( i = 0; i <= iFrame; i++ )
+ {
+ Aig_ManForEachPiSeq( p->pAig, pObj, k )
+ {
+ pSims = Fra_ObjSim( p, pObj->Id );
+ if ( Abc_InfoHasBit( pSims, 32 * p->nWordsFrame * i + iBit ) )
+ Abc_InfoSetBit( pCex->pData, pCex->nRegs + pCex->nPis * i + k );
+ }
+ }
+ // verify the counter example
+ if ( !Saig_ManVerifyCex( p->pAig, pCex ) )
+ {
+ printf( "Fra_SmlGetCounterExample(): Counter-example is invalid.\n" );
+ Abc_CexFree( pCex );
+ pCex = NULL;
+ }
+ return pCex;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Generates seq counter-example from the combinational one.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Cex_t * Fra_SmlCopyCounterExample( Aig_Man_t * pAig, Aig_Man_t * pFrames, int * pModel )
+{
+ Abc_Cex_t * pCex;
+ Aig_Obj_t * pObj;
+ int i, nFrames, nTruePis, nTruePos, iPo, iFrame;
+ // get the number of frames
+ assert( Aig_ManRegNum(pAig) > 0 );
+ assert( Aig_ManRegNum(pFrames) == 0 );
+ nTruePis = Aig_ManPiNum(pAig)-Aig_ManRegNum(pAig);
+ nTruePos = Aig_ManPoNum(pAig)-Aig_ManRegNum(pAig);
+ nFrames = Aig_ManPiNum(pFrames) / nTruePis;
+ assert( nTruePis * nFrames == Aig_ManPiNum(pFrames) );
+ assert( nTruePos * nFrames == Aig_ManPoNum(pFrames) );
+ // find the PO that failed
+ iPo = -1;
+ iFrame = -1;
+ Aig_ManForEachPo( pFrames, pObj, i )
+ if ( pObj->Id == pModel[Aig_ManPiNum(pFrames)] )
+ {
+ iPo = i % nTruePos;
+ iFrame = i / nTruePos;
+ break;
+ }
+ assert( iPo >= 0 );
+ // allocate the counter example
+ pCex = Abc_CexAlloc( Aig_ManRegNum(pAig), nTruePis, iFrame + 1 );
+ pCex->iPo = iPo;
+ pCex->iFrame = iFrame;
+
+ // copy the bit data
+ for ( i = 0; i < Aig_ManPiNum(pFrames); i++ )
+ {
+ if ( pModel[i] )
+ Abc_InfoSetBit( pCex->pData, pCex->nRegs + i );
+ if ( pCex->nRegs + i == pCex->nBits - 1 )
+ break;
+ }
+
+ // verify the counter example
+ if ( !Saig_ManVerifyCex( pAig, pCex ) )
+ {
+ printf( "Fra_SmlGetCounterExample(): Counter-example is invalid.\n" );
+ Abc_CexFree( pCex );
+ pCex = NULL;
+ }
+ return pCex;
+
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fra/fra_.c b/src/proof/fra/fra_.c
new file mode 100644
index 00000000..8e5785ec
--- /dev/null
+++ b/src/proof/fra/fra_.c
@@ -0,0 +1,53 @@
+/**CFile****************************************************************
+
+ FileName [fra_.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: fra_.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fra/module.make b/src/proof/fra/module.make
new file mode 100644
index 00000000..a54a98de
--- /dev/null
+++ b/src/proof/fra/module.make
@@ -0,0 +1,17 @@
+SRC += src/proof/fra/fraBmc.c \
+ src/proof/fra/fraCec.c \
+ src/proof/fra/fraClass.c \
+ src/proof/fra/fraClau.c \
+ src/proof/fra/fraClaus.c \
+ src/proof/fra/fraCnf.c \
+ src/proof/fra/fraCore.c \
+ src/proof/fra/fraHot.c \
+ src/proof/fra/fraImp.c \
+ src/proof/fra/fraInd.c \
+ src/proof/fra/fraIndVer.c \
+ src/proof/fra/fraLcr.c \
+ src/proof/fra/fraMan.c \
+ src/proof/fra/fraPart.c \
+ src/proof/fra/fraSat.c \
+ src/proof/fra/fraSec.c \
+ src/proof/fra/fraSim.c
diff --git a/src/proof/fraig/fraig.h b/src/proof/fraig/fraig.h
new file mode 100644
index 00000000..6d672716
--- /dev/null
+++ b/src/proof/fraig/fraig.h
@@ -0,0 +1,260 @@
+/**CFile****************************************************************
+
+ FileName [fraig.h]
+
+ PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+ Synopsis [External declarations of the FRAIG package.]
+
+ Author [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - October 1, 2004]
+
+ Revision [$Id: fraig.h,v 1.18 2005/07/08 01:01:30 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__sat__fraig__fraig_h
+#define ABC__sat__fraig__fraig_h
+
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// STRUCTURE DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Fraig_ManStruct_t_ Fraig_Man_t;
+typedef struct Fraig_NodeStruct_t_ Fraig_Node_t;
+typedef struct Fraig_NodeVecStruct_t_ Fraig_NodeVec_t;
+typedef struct Fraig_HashTableStruct_t_ Fraig_HashTable_t;
+typedef struct Fraig_ParamsStruct_t_ Fraig_Params_t;
+typedef struct Fraig_PatternsStruct_t_ Fraig_Patterns_t;
+typedef struct Prove_ParamsStruct_t_ Prove_Params_t;
+
+struct Fraig_ParamsStruct_t_
+{
+ int nPatsRand; // the number of words of random simulation info
+ int nPatsDyna; // the number of words of dynamic simulation info
+ int nBTLimit; // the max number of backtracks to perform
+ int nSeconds; // the timeout for the final proof
+ int fFuncRed; // performs only one level hashing
+ int fFeedBack; // enables solver feedback
+ int fDist1Pats; // enables distance-1 patterns
+ int fDoSparse; // performs equiv tests for sparse functions
+ int fChoicing; // enables recording structural choices
+ int fTryProve; // tries to solve the final miter
+ int fVerbose; // the verbosiness flag
+ int fVerboseP; // the verbosiness flag (for proof reporting)
+ int fInternal; // is set to 1 for internal fraig calls
+ int nConfLimit; // the limit on the number of conflicts
+ ABC_INT64_T nInspLimit; // the limit on the number of inspections
+};
+
+struct Prove_ParamsStruct_t_
+{
+ // general parameters
+ int fUseFraiging; // enables fraiging
+ int fUseRewriting; // enables rewriting
+ int fUseBdds; // enables BDD construction when other methods fail
+ int fVerbose; // prints verbose stats
+ // iterations
+ int nItersMax; // the number of iterations
+ // mitering
+ int nMiteringLimitStart; // starting mitering limit
+ float nMiteringLimitMulti; // multiplicative coefficient to increase the limit in each iteration
+ // rewriting
+ int nRewritingLimitStart; // the number of rewriting iterations
+ float nRewritingLimitMulti; // multiplicative coefficient to increase the limit in each iteration
+ // fraiging
+ int nFraigingLimitStart; // starting backtrack(conflict) limit
+ float nFraigingLimitMulti; // multiplicative coefficient to increase the limit in each iteration
+ // last-gasp BDD construction
+ int nBddSizeLimit; // the number of BDD nodes when construction is aborted
+ int fBddReorder; // enables dynamic BDD variable reordering
+ // last-gasp mitering
+ int nMiteringLimitLast; // final mitering limit
+ // global SAT solver limits
+ ABC_INT64_T nTotalBacktrackLimit; // global limit on the number of backtracks
+ ABC_INT64_T nTotalInspectLimit; // global limit on the number of clause inspects
+ // global resources applied
+ ABC_INT64_T nTotalBacktracksMade; // the total number of backtracks made
+ ABC_INT64_T nTotalInspectsMade; // the total number of inspects made
+};
+
+////////////////////////////////////////////////////////////////////////
+/// GLOBAL VARIABLES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// macros working with complemented attributes of the nodes
+#define Fraig_IsComplement(p) (((int)((ABC_PTRUINT_T) (p) & 01)))
+#define Fraig_Regular(p) ((Fraig_Node_t *)((ABC_PTRUINT_T)(p) & ~01))
+#define Fraig_Not(p) ((Fraig_Node_t *)((ABC_PTRUINT_T)(p) ^ 01))
+#define Fraig_NotCond(p,c) ((Fraig_Node_t *)((ABC_PTRUINT_T)(p) ^ (c)))
+
+// these are currently not used
+#define Fraig_Ref(p)
+#define Fraig_Deref(p)
+#define Fraig_RecursiveDeref(p,c)
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== fraigApi.c =============================================================*/
+extern Fraig_NodeVec_t * Fraig_ManReadVecInputs( Fraig_Man_t * p );
+extern Fraig_NodeVec_t * Fraig_ManReadVecOutputs( Fraig_Man_t * p );
+extern Fraig_NodeVec_t * Fraig_ManReadVecNodes( Fraig_Man_t * p );
+extern Fraig_Node_t ** Fraig_ManReadInputs ( Fraig_Man_t * p );
+extern Fraig_Node_t ** Fraig_ManReadOutputs( Fraig_Man_t * p );
+extern Fraig_Node_t ** Fraig_ManReadNodes( Fraig_Man_t * p );
+extern int Fraig_ManReadInputNum ( Fraig_Man_t * p );
+extern int Fraig_ManReadOutputNum( Fraig_Man_t * p );
+extern int Fraig_ManReadNodeNum( Fraig_Man_t * p );
+extern Fraig_Node_t * Fraig_ManReadConst1 ( Fraig_Man_t * p );
+extern Fraig_Node_t * Fraig_ManReadIthVar( Fraig_Man_t * p, int i );
+extern Fraig_Node_t * Fraig_ManReadIthNode( Fraig_Man_t * p, int i );
+extern char ** Fraig_ManReadInputNames( Fraig_Man_t * p );
+extern char ** Fraig_ManReadOutputNames( Fraig_Man_t * p );
+extern char * Fraig_ManReadVarsInt( Fraig_Man_t * p );
+extern char * Fraig_ManReadSat( Fraig_Man_t * p );
+extern int Fraig_ManReadFuncRed( Fraig_Man_t * p );
+extern int Fraig_ManReadFeedBack( Fraig_Man_t * p );
+extern int Fraig_ManReadDoSparse( Fraig_Man_t * p );
+extern int Fraig_ManReadChoicing( Fraig_Man_t * p );
+extern int Fraig_ManReadVerbose( Fraig_Man_t * p );
+extern int * Fraig_ManReadModel( Fraig_Man_t * p );
+extern int Fraig_ManReadPatternNumRandom( Fraig_Man_t * p );
+extern int Fraig_ManReadPatternNumDynamic( Fraig_Man_t * p );
+extern int Fraig_ManReadPatternNumDynamicFiltered( Fraig_Man_t * p );
+extern int Fraig_ManReadSatFails( Fraig_Man_t * p );
+extern int Fraig_ManReadConflicts( Fraig_Man_t * p );
+extern int Fraig_ManReadInspects( Fraig_Man_t * p );
+
+extern void Fraig_ManSetFuncRed( Fraig_Man_t * p, int fFuncRed );
+extern void Fraig_ManSetFeedBack( Fraig_Man_t * p, int fFeedBack );
+extern void Fraig_ManSetDoSparse( Fraig_Man_t * p, int fDoSparse );
+extern void Fraig_ManSetChoicing( Fraig_Man_t * p, int fChoicing );
+extern void Fraig_ManSetTryProve( Fraig_Man_t * p, int fTryProve );
+extern void Fraig_ManSetVerbose( Fraig_Man_t * p, int fVerbose );
+extern void Fraig_ManSetTimeToGraph( Fraig_Man_t * p, int Time );
+extern void Fraig_ManSetTimeToNet( Fraig_Man_t * p, int Time );
+extern void Fraig_ManSetTimeTotal( Fraig_Man_t * p, int Time );
+extern void Fraig_ManSetOutputNames( Fraig_Man_t * p, char ** ppNames );
+extern void Fraig_ManSetInputNames( Fraig_Man_t * p, char ** ppNames );
+extern void Fraig_ManSetPo( Fraig_Man_t * p, Fraig_Node_t * pNode );
+
+extern Fraig_Node_t * Fraig_NodeReadData0( Fraig_Node_t * p );
+extern Fraig_Node_t * Fraig_NodeReadData1( Fraig_Node_t * p );
+extern int Fraig_NodeReadNum( Fraig_Node_t * p );
+extern Fraig_Node_t * Fraig_NodeReadOne( Fraig_Node_t * p );
+extern Fraig_Node_t * Fraig_NodeReadTwo( Fraig_Node_t * p );
+extern Fraig_Node_t * Fraig_NodeReadNextE( Fraig_Node_t * p );
+extern Fraig_Node_t * Fraig_NodeReadRepr( Fraig_Node_t * p );
+extern int Fraig_NodeReadNumRefs( Fraig_Node_t * p );
+extern int Fraig_NodeReadNumFanouts( Fraig_Node_t * p );
+extern int Fraig_NodeReadSimInv( Fraig_Node_t * p );
+extern int Fraig_NodeReadNumOnes( Fraig_Node_t * p );
+extern unsigned * Fraig_NodeReadPatternsRandom( Fraig_Node_t * p );
+extern unsigned * Fraig_NodeReadPatternsDynamic( Fraig_Node_t * p );
+
+extern void Fraig_NodeSetData0( Fraig_Node_t * p, Fraig_Node_t * pData );
+extern void Fraig_NodeSetData1( Fraig_Node_t * p, Fraig_Node_t * pData );
+
+extern int Fraig_NodeIsConst( Fraig_Node_t * p );
+extern int Fraig_NodeIsVar( Fraig_Node_t * p );
+extern int Fraig_NodeIsAnd( Fraig_Node_t * p );
+extern int Fraig_NodeComparePhase( Fraig_Node_t * p1, Fraig_Node_t * p2 );
+
+extern Fraig_Node_t * Fraig_NodeOr( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 );
+extern Fraig_Node_t * Fraig_NodeAnd( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 );
+extern Fraig_Node_t * Fraig_NodeOr( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 );
+extern Fraig_Node_t * Fraig_NodeExor( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 );
+extern Fraig_Node_t * Fraig_NodeMux( Fraig_Man_t * p, Fraig_Node_t * pNode, Fraig_Node_t * pNodeT, Fraig_Node_t * pNodeE );
+extern void Fraig_NodeSetChoice( Fraig_Man_t * pMan, Fraig_Node_t * pNodeOld, Fraig_Node_t * pNodeNew );
+
+/*=== fraigMan.c =============================================================*/
+extern void Prove_ParamsSetDefault( Prove_Params_t * pParams );
+extern void Fraig_ParamsSetDefault( Fraig_Params_t * pParams );
+extern void Fraig_ParamsSetDefaultFull( Fraig_Params_t * pParams );
+extern Fraig_Man_t * Fraig_ManCreate( Fraig_Params_t * pParams );
+extern void Fraig_ManFree( Fraig_Man_t * pMan );
+extern void Fraig_ManPrintStats( Fraig_Man_t * p );
+extern Fraig_NodeVec_t * Fraig_ManGetSimInfo( Fraig_Man_t * p );
+extern int Fraig_ManCheckClauseUsingSimInfo( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 );
+extern void Fraig_ManAddClause( Fraig_Man_t * p, Fraig_Node_t ** ppNodes, int nNodes );
+
+/*=== fraigDfs.c =============================================================*/
+extern Fraig_NodeVec_t * Fraig_Dfs( Fraig_Man_t * pMan, int fEquiv );
+extern Fraig_NodeVec_t * Fraig_DfsOne( Fraig_Man_t * pMan, Fraig_Node_t * pNode, int fEquiv );
+extern Fraig_NodeVec_t * Fraig_DfsNodes( Fraig_Man_t * pMan, Fraig_Node_t ** ppNodes, int nNodes, int fEquiv );
+extern Fraig_NodeVec_t * Fraig_DfsReverse( Fraig_Man_t * pMan );
+extern int Fraig_CountNodes( Fraig_Man_t * pMan, int fEquiv );
+extern int Fraig_CheckTfi( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew );
+extern int Fraig_CountLevels( Fraig_Man_t * pMan );
+
+/*=== fraigSat.c =============================================================*/
+extern int Fraig_NodesAreEqual( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit, int nTimeLimit );
+extern int Fraig_NodeIsEquivalent( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit, int nTimeLimit );
+extern void Fraig_ManProveMiter( Fraig_Man_t * p );
+extern int Fraig_ManCheckMiter( Fraig_Man_t * p );
+extern int Fraig_ManCheckClauseUsingSat( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit );
+
+/*=== fraigVec.c ===============================================================*/
+extern Fraig_NodeVec_t * Fraig_NodeVecAlloc( int nCap );
+extern void Fraig_NodeVecFree( Fraig_NodeVec_t * p );
+extern Fraig_NodeVec_t * Fraig_NodeVecDup( Fraig_NodeVec_t * p );
+extern Fraig_Node_t ** Fraig_NodeVecReadArray( Fraig_NodeVec_t * p );
+extern int Fraig_NodeVecReadSize( Fraig_NodeVec_t * p );
+extern void Fraig_NodeVecGrow( Fraig_NodeVec_t * p, int nCapMin );
+extern void Fraig_NodeVecShrink( Fraig_NodeVec_t * p, int nSizeNew );
+extern void Fraig_NodeVecClear( Fraig_NodeVec_t * p );
+extern void Fraig_NodeVecPush( Fraig_NodeVec_t * p, Fraig_Node_t * Entry );
+extern int Fraig_NodeVecPushUnique( Fraig_NodeVec_t * p, Fraig_Node_t * Entry );
+extern void Fraig_NodeVecPushOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode );
+extern int Fraig_NodeVecPushUniqueOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode );
+extern void Fraig_NodeVecPushOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode );
+extern int Fraig_NodeVecPushUniqueOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode );
+extern Fraig_Node_t * Fraig_NodeVecPop( Fraig_NodeVec_t * p );
+extern void Fraig_NodeVecRemove( Fraig_NodeVec_t * p, Fraig_Node_t * Entry );
+extern void Fraig_NodeVecWriteEntry( Fraig_NodeVec_t * p, int i, Fraig_Node_t * Entry );
+extern Fraig_Node_t * Fraig_NodeVecReadEntry( Fraig_NodeVec_t * p, int i );
+extern void Fraig_NodeVecSortByLevel( Fraig_NodeVec_t * p, int fIncreasing );
+extern void Fraig_NodeVecSortByNumber( Fraig_NodeVec_t * p );
+
+/*=== fraigUtil.c ===============================================================*/
+extern void Fraig_ManMarkRealFanouts( Fraig_Man_t * p );
+extern int Fraig_ManCheckConsistency( Fraig_Man_t * p );
+extern int Fraig_GetMaxLevel( Fraig_Man_t * pMan );
+extern void Fraig_ManReportChoices( Fraig_Man_t * pMan );
+extern void Fraig_MappingSetChoiceLevels( Fraig_Man_t * pMan, int fMaximum );
+extern Fraig_NodeVec_t * Fraig_CollectSupergate( Fraig_Node_t * pNode, int fStopAtMux );
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
diff --git a/src/proof/fraig/fraigApi.c b/src/proof/fraig/fraigApi.c
new file mode 100644
index 00000000..6e0ab959
--- /dev/null
+++ b/src/proof/fraig/fraigApi.c
@@ -0,0 +1,302 @@
+/**CFile****************************************************************
+
+ FileName [fraigApi.c]
+
+ PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+ Synopsis [Access APIs for the FRAIG manager and node.]
+
+ Author [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - October 1, 2004]
+
+ Revision [$Id: fraigApi.c,v 1.2 2005/07/08 01:01:30 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fraigInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Access functions to read the data members of the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_NodeVec_t * Fraig_ManReadVecInputs( Fraig_Man_t * p ) { return p->vInputs; }
+Fraig_NodeVec_t * Fraig_ManReadVecOutputs( Fraig_Man_t * p ) { return p->vOutputs; }
+Fraig_NodeVec_t * Fraig_ManReadVecNodes( Fraig_Man_t * p ) { return p->vNodes; }
+Fraig_Node_t ** Fraig_ManReadInputs ( Fraig_Man_t * p ) { return p->vInputs->pArray; }
+Fraig_Node_t ** Fraig_ManReadOutputs( Fraig_Man_t * p ) { return p->vOutputs->pArray; }
+Fraig_Node_t ** Fraig_ManReadNodes( Fraig_Man_t * p ) { return p->vNodes->pArray; }
+int Fraig_ManReadInputNum ( Fraig_Man_t * p ) { return p->vInputs->nSize; }
+int Fraig_ManReadOutputNum( Fraig_Man_t * p ) { return p->vOutputs->nSize; }
+int Fraig_ManReadNodeNum( Fraig_Man_t * p ) { return p->vNodes->nSize; }
+Fraig_Node_t * Fraig_ManReadConst1 ( Fraig_Man_t * p ) { return p->pConst1; }
+Fraig_Node_t * Fraig_ManReadIthNode( Fraig_Man_t * p, int i ) { assert ( i < p->vNodes->nSize ); return p->vNodes->pArray[i]; }
+char ** Fraig_ManReadInputNames( Fraig_Man_t * p ) { return p->ppInputNames; }
+char ** Fraig_ManReadOutputNames( Fraig_Man_t * p ) { return p->ppOutputNames; }
+char * Fraig_ManReadVarsInt( Fraig_Man_t * p ) { return (char *)p->vVarsInt; }
+char * Fraig_ManReadSat( Fraig_Man_t * p ) { return (char *)p->pSat; }
+int Fraig_ManReadFuncRed( Fraig_Man_t * p ) { return p->fFuncRed; }
+int Fraig_ManReadFeedBack( Fraig_Man_t * p ) { return p->fFeedBack; }
+int Fraig_ManReadDoSparse( Fraig_Man_t * p ) { return p->fDoSparse; }
+int Fraig_ManReadChoicing( Fraig_Man_t * p ) { return p->fChoicing; }
+int Fraig_ManReadVerbose( Fraig_Man_t * p ) { return p->fVerbose; }
+int * Fraig_ManReadModel( Fraig_Man_t * p ) { return p->pModel; }
+// returns the number of patterns used for random simulation (this number is fixed for the FRAIG run)
+int Fraig_ManReadPatternNumRandom( Fraig_Man_t * p ) { return p->nWordsRand * 32; }
+// returns the number of dynamic patterns accumulated at runtime (include SAT solver counter-examples and distance-1 patterns derived from them)
+int Fraig_ManReadPatternNumDynamic( Fraig_Man_t * p ) { return p->iWordStart * 32; }
+// returns the number of dynamic patterns proved useful to distinquish some FRAIG nodes (this number is more than 0 after the first garbage collection of patterns)
+int Fraig_ManReadPatternNumDynamicFiltered( Fraig_Man_t * p ) { return p->iPatsPerm; }
+// returns the number of times FRAIG package timed out
+int Fraig_ManReadSatFails( Fraig_Man_t * p ) { return p->nSatFailsReal; }
+// returns the number of conflicts in the SAT solver
+int Fraig_ManReadConflicts( Fraig_Man_t * p ) { return p->pSat? Msat_SolverReadBackTracks(p->pSat) : 0; }
+// returns the number of inspections in the SAT solver
+int Fraig_ManReadInspects( Fraig_Man_t * p ) { return p->pSat? Msat_SolverReadInspects(p->pSat) : 0; }
+
+/**Function*************************************************************
+
+ Synopsis [Access functions to set the data members of the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_ManSetFuncRed( Fraig_Man_t * p, int fFuncRed ) { p->fFuncRed = fFuncRed; }
+void Fraig_ManSetFeedBack( Fraig_Man_t * p, int fFeedBack ) { p->fFeedBack = fFeedBack; }
+void Fraig_ManSetDoSparse( Fraig_Man_t * p, int fDoSparse ) { p->fDoSparse = fDoSparse; }
+void Fraig_ManSetChoicing( Fraig_Man_t * p, int fChoicing ) { p->fChoicing = fChoicing; }
+void Fraig_ManSetTryProve( Fraig_Man_t * p, int fTryProve ) { p->fTryProve = fTryProve; }
+void Fraig_ManSetVerbose( Fraig_Man_t * p, int fVerbose ) { p->fVerbose = fVerbose; }
+void Fraig_ManSetTimeToGraph( Fraig_Man_t * p, int Time ) { p->timeToAig = Time; }
+void Fraig_ManSetTimeToNet( Fraig_Man_t * p, int Time ) { p->timeToNet = Time; }
+void Fraig_ManSetTimeTotal( Fraig_Man_t * p, int Time ) { p->timeTotal = Time; }
+void Fraig_ManSetOutputNames( Fraig_Man_t * p, char ** ppNames ) { p->ppOutputNames = ppNames; }
+void Fraig_ManSetInputNames( Fraig_Man_t * p, char ** ppNames ) { p->ppInputNames = ppNames; }
+
+/**Function*************************************************************
+
+ Synopsis [Access functions to read the data members of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_NodeReadData0( Fraig_Node_t * p ) { return p->pData0; }
+Fraig_Node_t * Fraig_NodeReadData1( Fraig_Node_t * p ) { return p->pData1; }
+int Fraig_NodeReadNum( Fraig_Node_t * p ) { return p->Num; }
+Fraig_Node_t * Fraig_NodeReadOne( Fraig_Node_t * p ) { assert (!Fraig_IsComplement(p)); return p->p1; }
+Fraig_Node_t * Fraig_NodeReadTwo( Fraig_Node_t * p ) { assert (!Fraig_IsComplement(p)); return p->p2; }
+Fraig_Node_t * Fraig_NodeReadNextE( Fraig_Node_t * p ) { return p->pNextE; }
+Fraig_Node_t * Fraig_NodeReadRepr( Fraig_Node_t * p ) { return p->pRepr; }
+int Fraig_NodeReadNumRefs( Fraig_Node_t * p ) { return p->nRefs; }
+int Fraig_NodeReadNumFanouts( Fraig_Node_t * p ) { return p->nFanouts; }
+int Fraig_NodeReadSimInv( Fraig_Node_t * p ) { return p->fInv; }
+int Fraig_NodeReadNumOnes( Fraig_Node_t * p ) { return p->nOnes; }
+// returns the pointer to the random simulation patterns (their number is returned by Fraig_ManReadPatternNumRandom)
+// memory pointed to by this and the following procedure is maintained by the FRAIG package and exists as long as the package runs
+unsigned * Fraig_NodeReadPatternsRandom( Fraig_Node_t * p ) { return p->puSimR; }
+// returns the pointer to the dynamic simulation patterns (their number is returned by Fraig_ManReadPatternNumDynamic or Fraig_ManReadPatternNumDynamicFiltered)
+// if the number of patterns is not evenly divisible by 32, the patterns beyond the given number contain garbage
+unsigned * Fraig_NodeReadPatternsDynamic( Fraig_Node_t * p ) { return p->puSimD; }
+
+/**Function*************************************************************
+
+ Synopsis [Access functions to set the data members of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_NodeSetData0( Fraig_Node_t * p, Fraig_Node_t * pData ) { p->pData0 = pData; }
+void Fraig_NodeSetData1( Fraig_Node_t * p, Fraig_Node_t * pData ) { p->pData1 = pData; }
+
+/**Function*************************************************************
+
+ Synopsis [Checks the type of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_NodeIsConst( Fraig_Node_t * p ) { return (Fraig_Regular(p))->Num == 0; }
+int Fraig_NodeIsVar( Fraig_Node_t * p ) { return (Fraig_Regular(p))->NumPi >= 0; }
+int Fraig_NodeIsAnd( Fraig_Node_t * p ) { return (Fraig_Regular(p))->NumPi < 0 && (Fraig_Regular(p))->Num > 0; }
+int Fraig_NodeComparePhase( Fraig_Node_t * p1, Fraig_Node_t * p2 ) { assert( !Fraig_IsComplement(p1) ); assert( !Fraig_IsComplement(p2) ); return p1->fInv ^ p2->fInv; }
+
+/**Function*************************************************************
+
+ Synopsis [Returns a new primary input node.]
+
+ Description [If the node with this number does not exist,
+ create a new PI node with this number.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_ManReadIthVar( Fraig_Man_t * p, int i )
+{
+ int k;
+ if ( i < 0 )
+ {
+ printf( "Requesting a PI with a negative number\n" );
+ return NULL;
+ }
+ // create the PIs to fill in the interval
+ if ( i >= p->vInputs->nSize )
+ for ( k = p->vInputs->nSize; k <= i; k++ )
+ Fraig_NodeCreatePi( p );
+ return p->vInputs->pArray[i];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates a new PO node.]
+
+ Description [This procedure may take a complemented node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_ManSetPo( Fraig_Man_t * p, Fraig_Node_t * pNode )
+{
+ // internal node may be a PO two times
+ Fraig_Regular(pNode)->fNodePo = 1;
+ Fraig_NodeVecPush( p->vOutputs, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Perfoms the AND operation with functional hashing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_NodeAnd( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 )
+{
+ return Fraig_NodeAndCanon( p, p1, p2 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Perfoms the OR operation with functional hashing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_NodeOr( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 )
+{
+ return Fraig_Not( Fraig_NodeAndCanon( p, Fraig_Not(p1), Fraig_Not(p2) ) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Perfoms the EXOR operation with functional hashing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_NodeExor( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 )
+{
+ return Fraig_NodeMux( p, p1, Fraig_Not(p2), p2 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Perfoms the MUX operation with functional hashing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_NodeMux( Fraig_Man_t * p, Fraig_Node_t * pC, Fraig_Node_t * pT, Fraig_Node_t * pE )
+{
+ Fraig_Node_t * pAnd1, * pAnd2, * pRes;
+ pAnd1 = Fraig_NodeAndCanon( p, pC, pT ); Fraig_Ref( pAnd1 );
+ pAnd2 = Fraig_NodeAndCanon( p, Fraig_Not(pC), pE ); Fraig_Ref( pAnd2 );
+ pRes = Fraig_NodeOr( p, pAnd1, pAnd2 );
+ Fraig_RecursiveDeref( p, pAnd1 );
+ Fraig_RecursiveDeref( p, pAnd2 );
+ Fraig_Deref( pRes );
+ return pRes;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Sets the node to be equivalent to the given one.]
+
+ Description [This procedure is a work-around for the equivalence check.
+ Does not verify the equivalence. Use at the user's risk.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_NodeSetChoice( Fraig_Man_t * pMan, Fraig_Node_t * pNodeOld, Fraig_Node_t * pNodeNew )
+{
+// assert( pMan->fChoicing );
+ pNodeNew->pNextE = pNodeOld->pNextE;
+ pNodeOld->pNextE = pNodeNew;
+ pNodeNew->pRepr = pNodeOld;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fraig/fraigCanon.c b/src/proof/fraig/fraigCanon.c
new file mode 100644
index 00000000..47539db2
--- /dev/null
+++ b/src/proof/fraig/fraigCanon.c
@@ -0,0 +1,223 @@
+/**CFile****************************************************************
+
+ FileName [fraigCanon.c]
+
+ PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+ Synopsis [AND-node creation and elementary AND-operation.]
+
+ Author [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - October 1, 2004]
+
+ Revision [$Id: fraigCanon.c,v 1.4 2005/07/08 01:01:31 alanmi Exp $]
+
+***********************************************************************/
+
+#include <limits.h>
+#include "fraigInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [The internal AND operation for the two FRAIG nodes.]
+
+ Description [This procedure is the core of the FRAIG package, because
+ it performs the two-step canonicization of FRAIG nodes. The first step
+ involves the lookup in the structural hash table (which hashes two ANDs
+ into a node that has them as fanins, if such a node exists). If the node
+ is not found in the structural hash table, an attempt is made to find a
+ functionally equivalent node in another hash table (which hashes the
+ simulation info into the nodes, which has this simulation info). Some
+ tricks used on the way are described in the comments to the code and
+ in the paper "FRAIGs: Functionally reduced AND-INV graphs".]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_NodeAndCanon( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2 )
+{
+ Fraig_Node_t * pNodeNew, * pNodeOld, * pNodeRepr;
+ int fUseSatCheck;
+// int RetValue;
+
+ // check for trivial cases
+ if ( p1 == p2 )
+ return p1;
+ if ( p1 == Fraig_Not(p2) )
+ return Fraig_Not(pMan->pConst1);
+ if ( Fraig_NodeIsConst(p1) )
+ {
+ if ( p1 == pMan->pConst1 )
+ return p2;
+ return Fraig_Not(pMan->pConst1);
+ }
+ if ( Fraig_NodeIsConst(p2) )
+ {
+ if ( p2 == pMan->pConst1 )
+ return p1;
+ return Fraig_Not(pMan->pConst1);
+ }
+/*
+ // check for less trivial cases
+ if ( Fraig_IsComplement(p1) )
+ {
+ if ( RetValue = Fraig_NodeIsInSupergate( Fraig_Regular(p1), p2 ) )
+ {
+ if ( RetValue == -1 )
+ pMan->nImplies0++;
+ else
+ pMan->nImplies1++;
+
+ if ( RetValue == -1 )
+ return p2;
+ }
+ }
+ else
+ {
+ if ( RetValue = Fraig_NodeIsInSupergate( p1, p2 ) )
+ {
+ if ( RetValue == 1 )
+ pMan->nSimplifies1++;
+ else
+ pMan->nSimplifies0++;
+
+ if ( RetValue == 1 )
+ return p1;
+ return Fraig_Not(pMan->pConst1);
+ }
+ }
+
+ if ( Fraig_IsComplement(p2) )
+ {
+ if ( RetValue = Fraig_NodeIsInSupergate( Fraig_Regular(p2), p1 ) )
+ {
+ if ( RetValue == -1 )
+ pMan->nImplies0++;
+ else
+ pMan->nImplies1++;
+
+ if ( RetValue == -1 )
+ return p1;
+ }
+ }
+ else
+ {
+ if ( RetValue = Fraig_NodeIsInSupergate( p2, p1 ) )
+ {
+ if ( RetValue == 1 )
+ pMan->nSimplifies1++;
+ else
+ pMan->nSimplifies0++;
+
+ if ( RetValue == 1 )
+ return p2;
+ return Fraig_Not(pMan->pConst1);
+ }
+ }
+*/
+ // perform level-one structural hashing
+ if ( Fraig_HashTableLookupS( pMan, p1, p2, &pNodeNew ) ) // the node with these children is found
+ {
+ // if the existent node is part of the cone of unused logic
+ // (that is logic feeding the node which is equivalent to the given node)
+ // return the canonical representative of this node
+ // determine the phase of the given node, with respect to its canonical form
+ pNodeRepr = Fraig_Regular(pNodeNew)->pRepr;
+ if ( pMan->fFuncRed && pNodeRepr )
+ return Fraig_NotCond( pNodeRepr, Fraig_IsComplement(pNodeNew) ^ Fraig_NodeComparePhase(Fraig_Regular(pNodeNew), pNodeRepr) );
+ // otherwise, the node is itself a canonical representative, return it
+ return pNodeNew;
+ }
+ // the same node is not found, but the new one is created
+
+ // if one level hashing is requested (without functionality hashing), return
+ if ( !pMan->fFuncRed )
+ return pNodeNew;
+
+ // check if the new node is unique using the simulation info
+ if ( pNodeNew->nOnes == 0 || pNodeNew->nOnes == (unsigned)pMan->nWordsRand * 32 )
+ {
+ pMan->nSatZeros++;
+ if ( !pMan->fDoSparse ) // if we do not do sparse functions, skip
+ return pNodeNew;
+ // check the sparse function simulation hash table
+ pNodeOld = Fraig_HashTableLookupF0( pMan, pNodeNew );
+ if ( pNodeOld == NULL ) // the node is unique (it is added to the table)
+ return pNodeNew;
+ }
+ else
+ {
+ // check the simulation hash table
+ pNodeOld = Fraig_HashTableLookupF( pMan, pNodeNew );
+ if ( pNodeOld == NULL ) // the node is unique
+ return pNodeNew;
+ }
+ assert( pNodeOld->pRepr == 0 );
+ // there is another node which looks the same according to simulation
+
+ // use SAT to resolve the ambiguity
+ fUseSatCheck = (pMan->nInspLimit == 0 || Fraig_ManReadInspects(pMan) < pMan->nInspLimit);
+ if ( fUseSatCheck && Fraig_NodeIsEquivalent( pMan, pNodeOld, pNodeNew, pMan->nBTLimit, 1000000 ) )
+ {
+ // set the node to be equivalent with this node
+ // to prevent loops, only set if the old node is not in the TFI of the new node
+ // the loop may happen in the following case: suppose
+ // NodeC = AND(NodeA, NodeB) and at the same time NodeA => NodeB
+ // in this case, NodeA and NodeC are functionally equivalent
+ // however, NodeA is a fanin of node NodeC (this leads to the loop)
+ // add the node to the list of equivalent nodes or dereference it
+ if ( pMan->fChoicing && !Fraig_CheckTfi( pMan, pNodeOld, pNodeNew ) )
+ {
+ // if the old node is not in the TFI of the new node and choicing
+ // is enabled, add the new node to the list of equivalent ones
+ pNodeNew->pNextE = pNodeOld->pNextE;
+ pNodeOld->pNextE = pNodeNew;
+ }
+ // set the canonical representative of this node
+ pNodeNew->pRepr = pNodeOld;
+ // return the equivalent node
+ return Fraig_NotCond( pNodeOld, Fraig_NodeComparePhase(pNodeOld, pNodeNew) );
+ }
+
+ // now we add another member to this simulation class
+ if ( pNodeNew->nOnes == 0 || pNodeNew->nOnes == (unsigned)pMan->nWordsRand * 32 )
+ {
+ Fraig_Node_t * pNodeTemp;
+ assert( pMan->fDoSparse );
+ pNodeTemp = Fraig_HashTableLookupF0( pMan, pNodeNew );
+// assert( pNodeTemp == NULL );
+// Fraig_HashTableInsertF0( pMan, pNodeNew );
+ }
+ else
+ {
+ pNodeNew->pNextD = pNodeOld->pNextD;
+ pNodeOld->pNextD = pNodeNew;
+ }
+ // return the new node
+ assert( pNodeNew->pRepr == 0 );
+ return pNodeNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fraig/fraigChoice.c b/src/proof/fraig/fraigChoice.c
new file mode 100644
index 00000000..21d4fe10
--- /dev/null
+++ b/src/proof/fraig/fraigChoice.c
@@ -0,0 +1,246 @@
+/**CFile****************************************************************
+
+ FileName [fraigTrans.c]
+
+ PackageName [MVSIS 1.3: Multi-valued logic synthesis system.]
+
+ Synopsis [Adds the additive and distributive choices to the AIG.]
+
+ Author [MVSIS Group]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - February 1, 2003.]
+
+ Revision [$Id: fraigTrans.c,v 1.1 2005/02/28 05:34:34 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fraigInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Adds choice nodes based on associativity.]
+
+ Description [Make nLimit big AND gates and add all decompositions
+ to the Fraig.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_ManAddChoices( Fraig_Man_t * pMan, int fVerbose, int nLimit )
+{
+// ProgressBar * pProgress;
+ char Buffer[100];
+ int clkTotal = clock();
+ int i, nNodesBefore, nNodesAfter, nInputs, nMaxNodes;
+ int /*nMaxLevel,*/ nDistributive;
+ Fraig_Node_t *pNode, *pRepr;
+ Fraig_Node_t *pX, *pA, *pB, *pC, /* *pD,*/ *pN, /* *pQ, *pR,*/ *pT;
+ int fShortCut = 0;
+
+ nDistributive = 0;
+
+// Fraig_ManSetApprox( pMan, 1 );
+
+ // NO functional reduction
+ if (fShortCut) Fraig_ManSetFuncRed( pMan, 0 );
+
+ // First we mark critical functions i.e. compute those
+ // nodes which lie on the critical path. Note that this
+ // doesn't update the required times on any choice nodes
+ // which are not the representatives
+/*
+ nMaxLevel = Fraig_GetMaxLevel( pMan );
+ for ( i = 0; i < pMan->nOutputs; i++ )
+ {
+ Fraig_SetNodeRequired( pMan, pMan->pOutputs[i], nMaxLevel );
+ }
+*/
+ nNodesBefore = Fraig_ManReadNodeNum( pMan );
+ nInputs = Fraig_ManReadInputNum( pMan );
+ nMaxNodes = nInputs + nLimit * ( nNodesBefore - nInputs );
+
+ printf ("Limit = %d, Before = %d\n", nMaxNodes, nNodesBefore );
+
+ if (0)
+ {
+ char buffer[128];
+ sprintf (buffer, "test" );
+// Fraig_MappingShow( pMan, buffer );
+ }
+
+// pProgress = Extra_ProgressBarStart( stdout, nMaxNodes );
+Fraig_ManCheckConsistency( pMan );
+
+ for ( i = nInputs+1; (i < Fraig_ManReadNodeNum( pMan ))
+ && (nMaxNodes > Fraig_ManReadNodeNum( pMan )); ++i )
+ {
+// if ( i == nNodesBefore )
+// break;
+
+ pNode = Fraig_ManReadIthNode( pMan, i );
+ assert ( pNode );
+
+ pRepr = pNode->pRepr ? pNode->pRepr : pNode;
+ //printf ("Slack: %d\n", Fraig_NodeReadSlack( pRepr ));
+
+ // All the new associative choices we add will have huge slack
+ // since we do not redo timing, and timing doesnt handle choices
+ // well anyway. However every newly added node is a choice of an
+ // existing critical node, so they are considered critical.
+// if ( (Fraig_NodeReadSlack( pRepr ) > 3) && (i < nNodesBefore) )
+// continue;
+
+// if ( pNode->pRepr )
+// continue;
+
+ // Try ((ab)c), x = ab -> (a(bc)) and (b(ac))
+ pX = Fraig_NodeReadOne(pNode);
+ pC = Fraig_NodeReadTwo(pNode);
+ if (Fraig_NodeIsAnd(pX) && !Fraig_IsComplement(pX))
+ {
+ pA = Fraig_NodeReadOne(Fraig_Regular(pX));
+ pB = Fraig_NodeReadTwo(Fraig_Regular(pX));
+
+// pA = Fraig_NodeGetRepr( pA );
+// pB = Fraig_NodeGetRepr( pB );
+// pC = Fraig_NodeGetRepr( pC );
+
+ if (fShortCut)
+ {
+ pT = Fraig_NodeAnd(pMan, pB, pC);
+ if ( !pT->pRepr )
+ {
+ pN = Fraig_NodeAnd(pMan, pA, pT);
+// Fraig_NodeAddChoice( pMan, pNode, pN );
+ }
+ }
+ else
+ pN = Fraig_NodeAnd(pMan, pA, Fraig_NodeAnd(pMan, pB, pC));
+ // assert ( Fraig_NodesEqual(pN, pNode) );
+
+
+ if (fShortCut)
+ {
+ pT = Fraig_NodeAnd(pMan, pA, pC);
+ if ( !pT->pRepr )
+ {
+ pN = Fraig_NodeAnd(pMan, pB, pT);
+// Fraig_NodeAddChoice( pMan, pNode, pN );
+ }
+ }
+ else
+ pN = Fraig_NodeAnd(pMan, pB, Fraig_NodeAnd(pMan, pA, pC));
+ // assert ( Fraig_NodesEqual(pN, pNode) );
+ }
+
+
+ // Try (a(bc)), x = bc -> ((ab)c) and ((ac)b)
+ pA = Fraig_NodeReadOne(pNode);
+ pX = Fraig_NodeReadTwo(pNode);
+ if (Fraig_NodeIsAnd(pX) && !Fraig_IsComplement(pX))
+ {
+ pB = Fraig_NodeReadOne(Fraig_Regular(pX));
+ pC = Fraig_NodeReadTwo(Fraig_Regular(pX));
+
+// pA = Fraig_NodeGetRepr( pA );
+// pB = Fraig_NodeGetRepr( pB );
+// pC = Fraig_NodeGetRepr( pC );
+
+ if (fShortCut)
+ {
+ pT = Fraig_NodeAnd(pMan, pA, pB);
+ if ( !pT->pRepr )
+ {
+ pN = Fraig_NodeAnd(pMan, pC, pT);
+// Fraig_NodeAddChoice( pMan, pNode, pN );
+ }
+ }
+ else
+ pN = Fraig_NodeAnd(pMan, Fraig_NodeAnd(pMan, pA, pB), pC);
+ // assert ( Fraig_NodesEqual(pN, pNode) );
+
+ if (fShortCut)
+ {
+ pT = Fraig_NodeAnd(pMan, pA, pC);
+ if ( !pT->pRepr )
+ {
+ pN = Fraig_NodeAnd(pMan, pB, pT);
+// Fraig_NodeAddChoice( pMan, pNode, pN );
+ }
+ }
+ else
+ pN = Fraig_NodeAnd(pMan, Fraig_NodeAnd(pMan, pA, pC), pB);
+ // assert ( Fraig_NodesEqual(pN, pNode) );
+ }
+
+
+/*
+ // Try distributive transform
+ pQ = Fraig_NodeReadOne(pNode);
+ pR = Fraig_NodeReadTwo(pNode);
+ if ( (Fraig_IsComplement(pQ) && Fraig_NodeIsAnd(pQ))
+ && (Fraig_IsComplement(pR) && Fraig_NodeIsAnd(pR)) )
+ {
+ pA = Fraig_NodeReadOne(Fraig_Regular(pQ));
+ pB = Fraig_NodeReadTwo(Fraig_Regular(pQ));
+ pC = Fraig_NodeReadOne(Fraig_Regular(pR));
+ pD = Fraig_NodeReadTwo(Fraig_Regular(pR));
+
+ // Now detect the !(xy + xz) pattern, store
+ // x in pA, y in pB and z in pC and set pD = 0 to indicate
+ // pattern was found
+ assert (pD != 0);
+ if (pA == pC) { pC = pD; pD = 0; }
+ if (pA == pD) { pD = 0; }
+ if (pB == pC) { pB = pA; pA = pC; pC = pD; pD = 0; }
+ if (pB == pD) { pB = pA; pA = pD; pD = 0; }
+ if (pD == 0)
+ {
+ nDistributive++;
+ pN = Fraig_Not(Fraig_NodeAnd(pMan, pA,
+ Fraig_NodeOr(pMan, pB, pC)));
+ if (fShortCut) Fraig_NodeAddChoice( pMan, pNode, pN );
+ // assert ( Fraig_NodesEqual(pN, pNode) );
+ }
+ }
+*/
+ if ( i % 1000 == 0 )
+ {
+ sprintf( Buffer, "Adding choice %6d...", i - nNodesBefore );
+// Extra_ProgressBarUpdate( pProgress, i, Buffer );
+ }
+ }
+
+// Extra_ProgressBarStop( pProgress );
+
+Fraig_ManCheckConsistency( pMan );
+
+ nNodesAfter = Fraig_ManReadNodeNum( pMan );
+ printf ( "Nodes before = %6d. Nodes with associative choices = %6d. Increase = %4.2f %%.\n",
+ nNodesBefore, nNodesAfter, ((float)(nNodesAfter - nNodesBefore)) * 100.0/(nNodesBefore - nInputs) );
+ printf ( "Distributive = %d\n", nDistributive );
+
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fraig/fraigFanout.c b/src/proof/fraig/fraigFanout.c
new file mode 100644
index 00000000..0e6c86f8
--- /dev/null
+++ b/src/proof/fraig/fraigFanout.c
@@ -0,0 +1,180 @@
+/**CFile****************************************************************
+
+ FileName [fraigFanout.c]
+
+ PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+ Synopsis [Procedures to manipulate fanouts of the FRAIG nodes.]
+
+ Author [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - October 1, 2004]
+
+ Revision [$Id: fraigFanout.c,v 1.5 2005/07/08 01:01:31 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fraigInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+#ifdef FRAIG_ENABLE_FANOUTS
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Add the fanout to the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_NodeAddFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanout )
+{
+ Fraig_Node_t * pPivot;
+
+ // pFanins is a fanin of pFanout
+ assert( !Fraig_IsComplement(pFanin) );
+ assert( !Fraig_IsComplement(pFanout) );
+ assert( Fraig_Regular(pFanout->p1) == pFanin || Fraig_Regular(pFanout->p2) == pFanin );
+
+ pPivot = pFanin->pFanPivot;
+ if ( pPivot == NULL )
+ {
+ pFanin->pFanPivot = pFanout;
+ return;
+ }
+
+ if ( Fraig_Regular(pPivot->p1) == pFanin )
+ {
+ if ( Fraig_Regular(pFanout->p1) == pFanin )
+ {
+ pFanout->pFanFanin1 = pPivot->pFanFanin1;
+ pPivot->pFanFanin1 = pFanout;
+ }
+ else // if ( Fraig_Regular(pFanout->p2) == pFanin )
+ {
+ pFanout->pFanFanin2 = pPivot->pFanFanin1;
+ pPivot->pFanFanin1 = pFanout;
+ }
+ }
+ else // if ( Fraig_Regular(pPivot->p2) == pFanin )
+ {
+ assert( Fraig_Regular(pPivot->p2) == pFanin );
+ if ( Fraig_Regular(pFanout->p1) == pFanin )
+ {
+ pFanout->pFanFanin1 = pPivot->pFanFanin2;
+ pPivot->pFanFanin2 = pFanout;
+ }
+ else // if ( Fraig_Regular(pFanout->p2) == pFanin )
+ {
+ pFanout->pFanFanin2 = pPivot->pFanFanin2;
+ pPivot->pFanFanin2 = pFanout;
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Add the fanout to the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_NodeRemoveFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanoutToRemove )
+{
+ Fraig_Node_t * pFanout, * pFanout2, ** ppFanList;
+ // start the linked list of fanouts
+ ppFanList = &pFanin->pFanPivot;
+ // go through the fanouts
+ Fraig_NodeForEachFanoutSafe( pFanin, pFanout, pFanout2 )
+ {
+ // skip the fanout-to-remove
+ if ( pFanout == pFanoutToRemove )
+ continue;
+ // add useful fanouts to the list
+ *ppFanList = pFanout;
+ ppFanList = Fraig_NodeReadNextFanoutPlace( pFanin, pFanout );
+ }
+ *ppFanList = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transfers fanout to a different node.]
+
+ Description [Assumes that the other node currently has no fanouts.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_NodeTransferFanout( Fraig_Node_t * pNodeFrom, Fraig_Node_t * pNodeTo )
+{
+ Fraig_Node_t * pFanout;
+ assert( pNodeTo->pFanPivot == NULL );
+ assert( pNodeTo->pFanFanin1 == NULL );
+ assert( pNodeTo->pFanFanin2 == NULL );
+ // go through the fanouts and update their fanins
+ Fraig_NodeForEachFanout( pNodeFrom, pFanout )
+ {
+ if ( Fraig_Regular(pFanout->p1) == pNodeFrom )
+ pFanout->p1 = Fraig_NotCond( pNodeTo, Fraig_IsComplement(pFanout->p1) );
+ else if ( Fraig_Regular(pFanout->p2) == pNodeFrom )
+ pFanout->p2 = Fraig_NotCond( pNodeTo, Fraig_IsComplement(pFanout->p2) );
+ }
+ // move the pointers
+ pNodeTo->pFanPivot = pNodeFrom->pFanPivot;
+ pNodeTo->pFanFanin1 = pNodeFrom->pFanFanin1;
+ pNodeTo->pFanFanin2 = pNodeFrom->pFanFanin2;
+ pNodeFrom->pFanPivot = NULL;
+ pNodeFrom->pFanFanin1 = NULL;
+ pNodeFrom->pFanFanin2 = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of fanouts of a node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_NodeGetFanoutNum( Fraig_Node_t * pNode )
+{
+ Fraig_Node_t * pFanout;
+ int Counter = 0;
+ Fraig_NodeForEachFanout( pNode, pFanout )
+ Counter++;
+ return Counter;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+#endif
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fraig/fraigFeed.c b/src/proof/fraig/fraigFeed.c
new file mode 100644
index 00000000..47f946e1
--- /dev/null
+++ b/src/proof/fraig/fraigFeed.c
@@ -0,0 +1,913 @@
+/**CFile****************************************************************
+
+ FileName [fraigFeed.c]
+
+ PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+ Synopsis [Procedures to support the solver feedback.]
+
+ Author [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - October 1, 2004]
+
+ Revision [$Id: fraigFeed.c,v 1.8 2005/07/08 01:01:31 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fraigInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int Fraig_FeedBackPrepare( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars );
+static int Fraig_FeedBackInsert( Fraig_Man_t * p, int nVarsPi );
+static void Fraig_FeedBackVerify( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew );
+
+static void Fraig_FeedBackCovering( Fraig_Man_t * p, Msat_IntVec_t * vPats );
+static Fraig_NodeVec_t * Fraig_FeedBackCoveringStart( Fraig_Man_t * pMan );
+static int Fraig_GetSmallestColumn( int * pHits, int nHits );
+static int Fraig_GetHittingPattern( unsigned * pSims, int nWords );
+static void Fraig_CancelCoveredColumns( Fraig_NodeVec_t * vColumns, int * pHits, int iPat );
+static void Fraig_FeedBackCheckTable( Fraig_Man_t * p );
+static void Fraig_FeedBackCheckTableF0( Fraig_Man_t * p );
+static void Fraig_ReallocateSimulationInfo( Fraig_Man_t * p );
+
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Initializes the feedback information.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_FeedBackInit( Fraig_Man_t * p )
+{
+ p->vCones = Fraig_NodeVecAlloc( 500 );
+ p->vPatsReal = Msat_IntVecAlloc( 1000 );
+ p->pSimsReal = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims );
+ memset( p->pSimsReal, 0, sizeof(unsigned) * p->nWordsDyna );
+ p->pSimsTemp = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims );
+ p->pSimsDiff = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Processes the feedback from teh solver.]
+
+ Description [Array pModel gives the value of each variable in the SAT
+ solver. Array vVars is the array of integer numbers of variables
+ involves in this conflict.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_FeedBack( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars, Fraig_Node_t * pOld, Fraig_Node_t * pNew )
+{
+ int nVarsPi, nWords;
+ int i, clk = clock();
+
+ // get the number of PI vars in the feedback (also sets the PI values)
+ nVarsPi = Fraig_FeedBackPrepare( p, pModel, vVars );
+
+ // set the PI values
+ nWords = Fraig_FeedBackInsert( p, nVarsPi );
+ assert( p->iWordStart + nWords <= p->nWordsDyna );
+
+ // resimulates the words from p->iWordStart to iWordStop
+ for ( i = 1; i < p->vNodes->nSize; i++ )
+ if ( Fraig_NodeIsAnd(p->vNodes->pArray[i]) )
+ Fraig_NodeSimulate( p->vNodes->pArray[i], p->iWordStart, p->iWordStart + nWords, 0 );
+
+ if ( p->fDoSparse )
+ Fraig_TableRehashF0( p, 0 );
+
+ if ( !p->fChoicing )
+ Fraig_FeedBackVerify( p, pOld, pNew );
+
+ // if there is no room left, compress the patterns
+ if ( p->iWordStart + nWords == p->nWordsDyna )
+ p->iWordStart = Fraig_FeedBackCompress( p );
+ else // otherwise, update the starting word
+ p->iWordStart += nWords;
+
+p->timeFeed += clock() - clk;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Get the number and values of the PI variables.]
+
+ Description [Returns the number of PI variables involved in this feedback.
+ Fills in the internal presence and value data for the primary inputs.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_FeedBackPrepare( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars )
+{
+ Fraig_Node_t * pNode;
+ int i, nVars, nVarsPis, * pVars;
+
+ // clean the presence flag for all PIs
+ for ( i = 0; i < p->vInputs->nSize; i++ )
+ {
+ pNode = p->vInputs->pArray[i];
+ pNode->fFeedUse = 0;
+ }
+
+ // get the variables involved in the feedback
+ nVars = Msat_IntVecReadSize(vVars);
+ pVars = Msat_IntVecReadArray(vVars);
+
+ // set the values for the present variables
+ nVarsPis = 0;
+ for ( i = 0; i < nVars; i++ )
+ {
+ pNode = p->vNodes->pArray[ pVars[i] ];
+ if ( !Fraig_NodeIsVar(pNode) )
+ continue;
+ // set its value
+ pNode->fFeedUse = 1;
+ pNode->fFeedVal = !MSAT_LITSIGN(pModel[pVars[i]]);
+ nVarsPis++;
+ }
+ return nVarsPis;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts the new simulation patterns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_FeedBackInsert( Fraig_Man_t * p, int nVarsPi )
+{
+ Fraig_Node_t * pNode;
+ int nWords, iPatFlip, nPatFlipLimit, i, w;
+ int fUseNoPats = 0;
+ int fUse2Pats = 0;
+
+ // get the number of words
+ if ( fUse2Pats )
+ nWords = FRAIG_NUM_WORDS( 2 * nVarsPi + 1 );
+ else if ( fUseNoPats )
+ nWords = 1;
+ else
+ nWords = FRAIG_NUM_WORDS( nVarsPi + 1 );
+ // update the number of words if they do not fit into the simulation info
+ if ( nWords > p->nWordsDyna - p->iWordStart )
+ nWords = p->nWordsDyna - p->iWordStart;
+ // determine the bound on the flipping bit
+ nPatFlipLimit = nWords * 32 - 2;
+
+ // mark the real pattern
+ Msat_IntVecPush( p->vPatsReal, p->iWordStart * 32 );
+ // record the real pattern
+ Fraig_BitStringSetBit( p->pSimsReal, p->iWordStart * 32 );
+
+ // set the values at the PIs
+ iPatFlip = 1;
+ for ( i = 0; i < p->vInputs->nSize; i++ )
+ {
+ pNode = p->vInputs->pArray[i];
+ for ( w = p->iWordStart; w < p->iWordStart + nWords; w++ )
+ if ( !pNode->fFeedUse )
+ pNode->puSimD[w] = FRAIG_RANDOM_UNSIGNED;
+ else if ( pNode->fFeedVal )
+ pNode->puSimD[w] = FRAIG_FULL;
+ else // if ( !pNode->fFeedVal )
+ pNode->puSimD[w] = 0;
+
+ if ( fUse2Pats )
+ {
+ // flip two patterns
+ if ( pNode->fFeedUse && 2 * iPatFlip < nPatFlipLimit )
+ {
+ Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, 2 * iPatFlip - 1 );
+ Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, 2 * iPatFlip );
+ Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, 2 * iPatFlip + 1 );
+ iPatFlip++;
+ }
+ }
+ else if ( fUseNoPats )
+ {
+ }
+ else
+ {
+ // flip the diagonal
+ if ( pNode->fFeedUse && iPatFlip < nPatFlipLimit )
+ {
+ Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, iPatFlip );
+ iPatFlip++;
+ // Extra_PrintBinary( stdout, &pNode->puSimD, 45 ); printf( "\n" );
+ }
+ }
+ // clean the use mask
+ pNode->fFeedUse = 0;
+
+ // add the info to the D hash value of the PIs
+ for ( w = p->iWordStart; w < p->iWordStart + nWords; w++ )
+ pNode->uHashD ^= pNode->puSimD[w] * s_FraigPrimes[w];
+
+ }
+ return nWords;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Checks that the SAT solver pattern indeed distinquishes the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_FeedBackVerify( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew )
+{
+ int fValue1, fValue2, iPat;
+ iPat = Msat_IntVecReadEntry( p->vPatsReal, Msat_IntVecReadSize(p->vPatsReal)-1 );
+ fValue1 = (Fraig_BitStringHasBit( pOld->puSimD, iPat ));
+ fValue2 = (Fraig_BitStringHasBit( pNew->puSimD, iPat ));
+/*
+Fraig_PrintNode( p, pOld );
+printf( "\n" );
+Fraig_PrintNode( p, pNew );
+printf( "\n" );
+*/
+// assert( fValue1 != fValue2 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compress the simulation patterns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_FeedBackCompress( Fraig_Man_t * p )
+{
+ unsigned * pSims;
+ unsigned uHash;
+ int i, w, t, nPats, * pPats;
+ int fPerformChecks = (p->nBTLimit == -1);
+
+ // solve the covering problem
+ if ( fPerformChecks )
+ {
+ Fraig_FeedBackCheckTable( p );
+ if ( p->fDoSparse )
+ Fraig_FeedBackCheckTableF0( p );
+ }
+
+ // solve the covering problem
+ Fraig_FeedBackCovering( p, p->vPatsReal );
+
+
+ // get the number of additional patterns
+ nPats = Msat_IntVecReadSize( p->vPatsReal );
+ pPats = Msat_IntVecReadArray( p->vPatsReal );
+ // get the new starting word
+ p->iWordStart = FRAIG_NUM_WORDS( p->iPatsPerm + nPats );
+
+ // set the simulation info for the PIs
+ for ( i = 0; i < p->vInputs->nSize; i++ )
+ {
+ // get hold of the simulation info for this PI
+ pSims = p->vInputs->pArray[i]->puSimD;
+ // clean the storage for the new patterns
+ for ( w = p->iWordPerm; w < p->iWordStart; w++ )
+ p->pSimsTemp[w] = 0;
+ // set the patterns
+ for ( t = 0; t < nPats; t++ )
+ if ( Fraig_BitStringHasBit( pSims, pPats[t] ) )
+ {
+ // check if this pattern falls into temporary storage
+ if ( p->iPatsPerm + t < p->iWordPerm * 32 )
+ Fraig_BitStringSetBit( pSims, p->iPatsPerm + t );
+ else
+ Fraig_BitStringSetBit( p->pSimsTemp, p->iPatsPerm + t );
+ }
+ // copy the pattern
+ for ( w = p->iWordPerm; w < p->iWordStart; w++ )
+ pSims[w] = p->pSimsTemp[w];
+ // recompute the hashing info
+ uHash = 0;
+ for ( w = 0; w < p->iWordStart; w++ )
+ uHash ^= pSims[w] * s_FraigPrimes[w];
+ p->vInputs->pArray[i]->uHashD = uHash;
+ }
+
+ // update info about the permanently stored patterns
+ p->iWordPerm = p->iWordStart;
+ p->iPatsPerm += nPats;
+ assert( p->iWordPerm == FRAIG_NUM_WORDS( p->iPatsPerm ) );
+
+ // resimulate and recompute the hash values
+ for ( i = 1; i < p->vNodes->nSize; i++ )
+ if ( Fraig_NodeIsAnd(p->vNodes->pArray[i]) )
+ {
+ p->vNodes->pArray[i]->uHashD = 0;
+ Fraig_NodeSimulate( p->vNodes->pArray[i], 0, p->iWordPerm, 0 );
+ }
+
+ // double-check that the nodes are still distinguished
+ if ( fPerformChecks )
+ Fraig_FeedBackCheckTable( p );
+
+ // rehash the values in the F0 table
+ if ( p->fDoSparse )
+ {
+ Fraig_TableRehashF0( p, 0 );
+ if ( fPerformChecks )
+ Fraig_FeedBackCheckTableF0( p );
+ }
+
+ // check if we need to resize the simulation info
+ // if less than FRAIG_WORDS_STORE words are left, reallocate simulation info
+ if ( p->iWordPerm + FRAIG_WORDS_STORE > p->nWordsDyna )
+ Fraig_ReallocateSimulationInfo( p );
+
+ // set the real patterns
+ Msat_IntVecClear( p->vPatsReal );
+ memset( p->pSimsReal, 0, sizeof(unsigned)*p->nWordsDyna );
+ for ( w = 0; w < p->iWordPerm; w++ )
+ p->pSimsReal[w] = FRAIG_FULL;
+ if ( p->iPatsPerm % 32 > 0 )
+ p->pSimsReal[p->iWordPerm-1] = FRAIG_MASK( p->iPatsPerm % 32 );
+// printf( "The number of permanent words = %d.\n", p->iWordPerm );
+ return p->iWordStart;
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Checks the correctness of the functional simulation table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_FeedBackCovering( Fraig_Man_t * p, Msat_IntVec_t * vPats )
+{
+ Fraig_NodeVec_t * vColumns;
+ unsigned * pSims;
+ int * pHits, iPat, iCol, i;
+ int nOnesTotal, nSolStarting;
+ int fVeryVerbose = 0;
+
+ // collect the pairs to be distinguished
+ vColumns = Fraig_FeedBackCoveringStart( p );
+ // collect the number of 1s in each simulation vector
+ nOnesTotal = 0;
+ pHits = ABC_ALLOC( int, vColumns->nSize );
+ for ( i = 0; i < vColumns->nSize; i++ )
+ {
+ pSims = (unsigned *)vColumns->pArray[i];
+ pHits[i] = Fraig_BitStringCountOnes( pSims, p->iWordStart );
+ nOnesTotal += pHits[i];
+// assert( pHits[i] > 0 );
+ }
+
+ // go through the patterns
+ nSolStarting = Msat_IntVecReadSize(vPats);
+ while ( (iCol = Fraig_GetSmallestColumn( pHits, vColumns->nSize )) != -1 )
+ {
+ // find the pattern, which hits this column
+ iPat = Fraig_GetHittingPattern( (unsigned *)vColumns->pArray[iCol], p->iWordStart );
+ // cancel the columns covered by this pattern
+ Fraig_CancelCoveredColumns( vColumns, pHits, iPat );
+ // save the pattern
+ Msat_IntVecPush( vPats, iPat );
+ }
+
+ // free the set of columns
+ for ( i = 0; i < vColumns->nSize; i++ )
+ Fraig_MemFixedEntryRecycle( p->mmSims, (char *)vColumns->pArray[i] );
+
+ // print stats related to the covering problem
+ if ( p->fVerbose && fVeryVerbose )
+ {
+ printf( "%3d\\%3d\\%3d ", p->nWordsRand, p->nWordsDyna, p->iWordPerm );
+ printf( "Col (pairs) = %5d. ", vColumns->nSize );
+ printf( "Row (pats) = %5d. ", p->iWordStart * 32 );
+ printf( "Dns = %6.2f %%. ", vColumns->nSize==0? 0.0 : 100.0 * nOnesTotal / vColumns->nSize / p->iWordStart / 32 );
+ printf( "Sol = %3d (%3d). ", Msat_IntVecReadSize(vPats), nSolStarting );
+ printf( "\n" );
+ }
+ Fraig_NodeVecFree( vColumns );
+ ABC_FREE( pHits );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Checks the correctness of the functional simulation table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_NodeVec_t * Fraig_FeedBackCoveringStart( Fraig_Man_t * p )
+{
+ Fraig_NodeVec_t * vColumns;
+ Fraig_HashTable_t * pT = p->pTableF;
+ Fraig_Node_t * pEntF, * pEntD;
+ unsigned * pSims;
+ unsigned * pUnsigned1, * pUnsigned2;
+ int i, k, m, w;//, nOnes;
+
+ // start the set of columns
+ vColumns = Fraig_NodeVecAlloc( 100 );
+
+ // go through the pairs of nodes to be distinguished
+ for ( i = 0; i < pT->nBins; i++ )
+ Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF )
+ {
+ p->vCones->nSize = 0;
+ Fraig_TableBinForEachEntryD( pEntF, pEntD )
+ Fraig_NodeVecPush( p->vCones, pEntD );
+ if ( p->vCones->nSize == 1 )
+ continue;
+ //////////////////////////////// bug fix by alanmi, September 14, 2006
+ if ( p->vCones->nSize > 20 )
+ continue;
+ ////////////////////////////////
+
+ for ( k = 0; k < p->vCones->nSize; k++ )
+ for ( m = k+1; m < p->vCones->nSize; m++ )
+ {
+ if ( !Fraig_CompareSimInfoUnderMask( p->vCones->pArray[k], p->vCones->pArray[m], p->iWordStart, 0, p->pSimsReal ) )
+ continue;
+
+ // primary simulation patterns (counter-examples) cannot distinguish this pair
+ // get memory to store the feasible simulation patterns
+ pSims = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims );
+ // find the pattern that distinguish this column, exept the primary ones
+ pUnsigned1 = p->vCones->pArray[k]->puSimD;
+ pUnsigned2 = p->vCones->pArray[m]->puSimD;
+ for ( w = 0; w < p->iWordStart; w++ )
+ pSims[w] = (pUnsigned1[w] ^ pUnsigned2[w]) & ~p->pSimsReal[w];
+ // store the pattern
+ Fraig_NodeVecPush( vColumns, (Fraig_Node_t *)pSims );
+// nOnes = Fraig_BitStringCountOnes(pSims, p->iWordStart);
+// assert( nOnes > 0 );
+ }
+ }
+
+ // if the flag is not set, do not consider sparse nodes in p->pTableF0
+ if ( !p->fDoSparse )
+ return vColumns;
+
+ // recalculate their hash values based on p->pSimsReal
+ pT = p->pTableF0;
+ for ( i = 0; i < pT->nBins; i++ )
+ Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF )
+ {
+ pSims = pEntF->puSimD;
+ pEntF->uHashD = 0;
+ for ( w = 0; w < p->iWordStart; w++ )
+ pEntF->uHashD ^= (pSims[w] & p->pSimsReal[w]) * s_FraigPrimes[w];
+ }
+
+ // rehash the table using these values
+ Fraig_TableRehashF0( p, 1 );
+
+ // collect the classes of equivalent node pairs
+ for ( i = 0; i < pT->nBins; i++ )
+ Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF )
+ {
+ p->vCones->nSize = 0;
+ Fraig_TableBinForEachEntryD( pEntF, pEntD )
+ Fraig_NodeVecPush( p->vCones, pEntD );
+ if ( p->vCones->nSize == 1 )
+ continue;
+
+ // primary simulation patterns (counter-examples) cannot distinguish all these pairs
+ for ( k = 0; k < p->vCones->nSize; k++ )
+ for ( m = k+1; m < p->vCones->nSize; m++ )
+ {
+ // get memory to store the feasible simulation patterns
+ pSims = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims );
+ // find the patterns that are not distinquished
+ pUnsigned1 = p->vCones->pArray[k]->puSimD;
+ pUnsigned2 = p->vCones->pArray[m]->puSimD;
+ for ( w = 0; w < p->iWordStart; w++ )
+ pSims[w] = (pUnsigned1[w] ^ pUnsigned2[w]) & ~p->pSimsReal[w];
+ // store the pattern
+ Fraig_NodeVecPush( vColumns, (Fraig_Node_t *)pSims );
+// nOnes = Fraig_BitStringCountOnes(pSims, p->iWordStart);
+// assert( nOnes > 0 );
+ }
+ }
+ return vColumns;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Selects the column, which has the smallest number of hits.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_GetSmallestColumn( int * pHits, int nHits )
+{
+ int i, iColMin = -1, nHitsMin = 1000000;
+ for ( i = 0; i < nHits; i++ )
+ {
+ // skip covered columns
+ if ( pHits[i] == 0 )
+ continue;
+ // take the column if it can only be covered by one pattern
+ if ( pHits[i] == 1 )
+ return i;
+ // find the column, which requires the smallest number of patterns
+ if ( nHitsMin > pHits[i] )
+ {
+ nHitsMin = pHits[i];
+ iColMin = i;
+ }
+ }
+ return iColMin;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Select the pattern, which hits this column.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_GetHittingPattern( unsigned * pSims, int nWords )
+{
+ int i, b;
+ for ( i = 0; i < nWords; i++ )
+ {
+ if ( pSims[i] == 0 )
+ continue;
+ for ( b = 0; b < 32; b++ )
+ if ( pSims[i] & (1 << b) )
+ return i * 32 + b;
+ }
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Cancel covered patterns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_CancelCoveredColumns( Fraig_NodeVec_t * vColumns, int * pHits, int iPat )
+{
+ unsigned * pSims;
+ int i;
+ for ( i = 0; i < vColumns->nSize; i++ )
+ {
+ pSims = (unsigned *)vColumns->pArray[i];
+ if ( Fraig_BitStringHasBit( pSims, iPat ) )
+ pHits[i] = 0;
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Checks the correctness of the functional simulation table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_FeedBackCheckTable( Fraig_Man_t * p )
+{
+ Fraig_HashTable_t * pT = p->pTableF;
+ Fraig_Node_t * pEntF, * pEntD;
+ int i, k, m, nPairs;
+
+ nPairs = 0;
+ for ( i = 0; i < pT->nBins; i++ )
+ Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF )
+ {
+ p->vCones->nSize = 0;
+ Fraig_TableBinForEachEntryD( pEntF, pEntD )
+ Fraig_NodeVecPush( p->vCones, pEntD );
+ if ( p->vCones->nSize == 1 )
+ continue;
+ for ( k = 0; k < p->vCones->nSize; k++ )
+ for ( m = k+1; m < p->vCones->nSize; m++ )
+ {
+ if ( Fraig_CompareSimInfo( p->vCones->pArray[k], p->vCones->pArray[m], p->iWordStart, 0 ) )
+ printf( "Nodes %d and %d have the same D simulation info.\n",
+ p->vCones->pArray[k]->Num, p->vCones->pArray[m]->Num );
+ nPairs++;
+ }
+ }
+// printf( "\nThe total of %d node pairs have been verified.\n", nPairs );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks the correctness of the functional simulation table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_FeedBackCheckTableF0( Fraig_Man_t * p )
+{
+ Fraig_HashTable_t * pT = p->pTableF0;
+ Fraig_Node_t * pEntF;
+ int i, k, m, nPairs;
+
+ nPairs = 0;
+ for ( i = 0; i < pT->nBins; i++ )
+ {
+ p->vCones->nSize = 0;
+ Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF )
+ Fraig_NodeVecPush( p->vCones, pEntF );
+ if ( p->vCones->nSize == 1 )
+ continue;
+ for ( k = 0; k < p->vCones->nSize; k++ )
+ for ( m = k+1; m < p->vCones->nSize; m++ )
+ {
+ if ( Fraig_CompareSimInfo( p->vCones->pArray[k], p->vCones->pArray[m], p->iWordStart, 0 ) )
+ printf( "Nodes %d and %d have the same D simulation info.\n",
+ p->vCones->pArray[k]->Num, p->vCones->pArray[m]->Num );
+ nPairs++;
+ }
+ }
+// printf( "\nThe total of %d node pairs have been verified.\n", nPairs );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Doubles the size of simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_ReallocateSimulationInfo( Fraig_Man_t * p )
+{
+ Fraig_MemFixed_t * mmSimsNew; // new memory manager for simulation info
+ Fraig_Node_t * pNode;
+ unsigned * pSimsNew;
+ unsigned uSignOld;
+ int i;
+
+ // allocate a new memory manager
+ p->nWordsDyna *= 2;
+ mmSimsNew = Fraig_MemFixedStart( sizeof(unsigned) * (p->nWordsRand + p->nWordsDyna) );
+
+ // set the new data for the constant node
+ pNode = p->pConst1;
+ pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew );
+ pNode->puSimD = pNode->puSimR + p->nWordsRand;
+ memset( pNode->puSimR, 0, sizeof(unsigned) * p->nWordsRand );
+ memset( pNode->puSimD, 0, sizeof(unsigned) * p->nWordsDyna );
+
+ // copy the simulation info of the PIs
+ for ( i = 0; i < p->vInputs->nSize; i++ )
+ {
+ pNode = p->vInputs->pArray[i];
+ // copy the simulation info
+ pSimsNew = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew );
+ memmove( pSimsNew, pNode->puSimR, sizeof(unsigned) * (p->nWordsRand + p->iWordStart) );
+ // attach the new info
+ pNode->puSimR = pSimsNew;
+ pNode->puSimD = pNode->puSimR + p->nWordsRand;
+ // signatures remain without changes
+ }
+
+ // replace the manager to free up some memory
+ Fraig_MemFixedStop( p->mmSims, 0 );
+ p->mmSims = mmSimsNew;
+
+ // resimulate the internal nodes (this should lead to the same signatures)
+ for ( i = 1; i < p->vNodes->nSize; i++ )
+ {
+ pNode = p->vNodes->pArray[i];
+ if ( !Fraig_NodeIsAnd(pNode) )
+ continue;
+ // allocate memory for the simulation info
+ pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew );
+ pNode->puSimD = pNode->puSimR + p->nWordsRand;
+ // derive random simulation info
+ uSignOld = pNode->uHashR;
+ pNode->uHashR = 0;
+ Fraig_NodeSimulate( pNode, 0, p->nWordsRand, 1 );
+ assert( uSignOld == pNode->uHashR );
+ // derive dynamic simulation info
+ uSignOld = pNode->uHashD;
+ pNode->uHashD = 0;
+ Fraig_NodeSimulate( pNode, 0, p->iWordStart, 0 );
+ assert( uSignOld == pNode->uHashD );
+ }
+
+ // realloc temporary storage
+ p->pSimsReal = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew );
+ memset( p->pSimsReal, 0, sizeof(unsigned) * p->nWordsDyna );
+ p->pSimsTemp = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew );
+ p->pSimsDiff = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Generated trivial counter example.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int * Fraig_ManAllocCounterExample( Fraig_Man_t * p )
+{
+ int * pModel;
+ pModel = ABC_ALLOC( int, p->vInputs->nSize );
+ memset( pModel, 0, sizeof(int) * p->vInputs->nSize );
+ return pModel;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Saves the counter example.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_ManSimulateBitNode_rec( Fraig_Man_t * p, Fraig_Node_t * pNode )
+{
+ int Value0, Value1;
+ if ( Fraig_NodeIsTravIdCurrent( p, pNode ) )
+ return pNode->fMark3;
+ Fraig_NodeSetTravIdCurrent( p, pNode );
+ Value0 = Fraig_ManSimulateBitNode_rec( p, Fraig_Regular(pNode->p1) );
+ Value1 = Fraig_ManSimulateBitNode_rec( p, Fraig_Regular(pNode->p2) );
+ Value0 ^= Fraig_IsComplement(pNode->p1);
+ Value1 ^= Fraig_IsComplement(pNode->p2);
+ pNode->fMark3 = Value0 & Value1;
+ return pNode->fMark3;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one bit.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_ManSimulateBitNode( Fraig_Man_t * p, Fraig_Node_t * pNode, int * pModel )
+{
+ int fCompl, RetValue, i;
+ // set the PI values
+ Fraig_ManIncrementTravId( p );
+ for ( i = 0; i < p->vInputs->nSize; i++ )
+ {
+ Fraig_NodeSetTravIdCurrent( p, p->vInputs->pArray[i] );
+ p->vInputs->pArray[i]->fMark3 = pModel[i];
+ }
+ // perform the traversal
+ fCompl = Fraig_IsComplement(pNode);
+ RetValue = Fraig_ManSimulateBitNode_rec( p, Fraig_Regular(pNode) );
+ return fCompl ^ RetValue;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Saves the counter example.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int * Fraig_ManSaveCounterExample( Fraig_Man_t * p, Fraig_Node_t * pNode )
+{
+ int * pModel;
+ int iPattern;
+ int i, fCompl;
+
+ // the node can be complemented
+ fCompl = Fraig_IsComplement(pNode);
+ // because we compare with constant 0, p->pConst1 should also be complemented
+ fCompl = !fCompl;
+
+ // derive the model
+ pModel = Fraig_ManAllocCounterExample( p );
+ iPattern = Fraig_FindFirstDiff( p->pConst1, Fraig_Regular(pNode), fCompl, p->nWordsRand, 1 );
+ if ( iPattern >= 0 )
+ {
+ for ( i = 0; i < p->vInputs->nSize; i++ )
+ if ( Fraig_BitStringHasBit( p->vInputs->pArray[i]->puSimR, iPattern ) )
+ pModel[i] = 1;
+/*
+printf( "SAT solver's pattern:\n" );
+for ( i = 0; i < p->vInputs->nSize; i++ )
+ printf( "%d", pModel[i] );
+printf( "\n" );
+*/
+ assert( Fraig_ManSimulateBitNode( p, pNode, pModel ) );
+ return pModel;
+ }
+ iPattern = Fraig_FindFirstDiff( p->pConst1, Fraig_Regular(pNode), fCompl, p->iWordStart, 0 );
+ if ( iPattern >= 0 )
+ {
+ for ( i = 0; i < p->vInputs->nSize; i++ )
+ if ( Fraig_BitStringHasBit( p->vInputs->pArray[i]->puSimD, iPattern ) )
+ pModel[i] = 1;
+/*
+printf( "SAT solver's pattern:\n" );
+for ( i = 0; i < p->vInputs->nSize; i++ )
+ printf( "%d", pModel[i] );
+printf( "\n" );
+*/
+ assert( Fraig_ManSimulateBitNode( p, pNode, pModel ) );
+ return pModel;
+ }
+ ABC_FREE( pModel );
+ return NULL;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fraig/fraigInt.h b/src/proof/fraig/fraigInt.h
new file mode 100644
index 00000000..f6a5d74f
--- /dev/null
+++ b/src/proof/fraig/fraigInt.h
@@ -0,0 +1,433 @@
+/**CFile****************************************************************
+
+ FileName [fraigInt.h]
+
+ PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+ Synopsis [Internal declarations of the FRAIG package.]
+
+ Author [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - October 1, 2004]
+
+ Revision [$Id: fraigInt.h,v 1.15 2005/07/08 01:01:31 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__sat__fraig__fraigInt_h
+#define ABC__sat__fraig__fraigInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <time.h>
+
+#include "src/misc/util/abc_global.h"
+#include "fraig.h"
+#include "src/sat/msat/msat.h"
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+/*
+ The AIG node policy:
+ - Each node has its main number (pNode->Num)
+ This is the number of this node in the array of all nodes and its SAT variable number
+ - The PI nodes are stored along with other nodes
+ Additionally, PI nodes have a PI number, by which they are stored in the PI node array
+ - The constant node is has number 0 and is also stored in the array
+*/
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// enable this macro to support the fanouts
+#define FRAIG_ENABLE_FANOUTS
+#define FRAIG_PATTERNS_RANDOM 2048 // should not be less than 128 and more than 32768 (2^15)
+#define FRAIG_PATTERNS_DYNAMIC 2048 // should not be less than 256 and more than 32768 (2^15)
+#define FRAIG_MAX_PRIMES 1024 // the maximum number of primes used for hashing
+
+// this parameter determines when simulation info is extended
+// it will be extended when the free storage in the dynamic simulation
+// info is less or equal to this number of words (FRAIG_WORDS_STORE)
+// this is done because if the free storage for dynamic simulation info
+// is not sufficient, computation becomes inefficient
+#define FRAIG_WORDS_STORE 5
+
+// the bit masks
+#define FRAIG_MASK(n) ((~((unsigned)0)) >> (32-(n)))
+#define FRAIG_FULL (~((unsigned)0))
+#define FRAIG_NUM_WORDS(n) (((n)>>5) + (((n)&31) > 0))
+
+// generating random unsigned (#define RAND_MAX 0x7fff)
+#define FRAIG_RANDOM_UNSIGNED ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand()))
+
+// macros to get hold of the bits in a bit string
+#define Fraig_BitStringSetBit(p,i) ((p)[(i)>>5] |= (1<<((i) & 31)))
+#define Fraig_BitStringXorBit(p,i) ((p)[(i)>>5] ^= (1<<((i) & 31)))
+#define Fraig_BitStringHasBit(p,i) (((p)[(i)>>5] & (1<<((i) & 31))) > 0)
+
+// macros to get hold of the bits in the support info
+//#define Fraig_NodeSetVarStr(p,i) (Fraig_Regular(p)->pSuppStr[((i)%FRAIG_SUPP_SIGN)>>5] |= (1<<(((i)%FRAIG_SUPP_SIGN) & 31)))
+//#define Fraig_NodeHasVarStr(p,i) ((Fraig_Regular(p)->pSuppStr[((i)%FRAIG_SUPP_SIGN)>>5] & (1<<(((i)%FRAIG_SUPP_SIGN) & 31))) > 0)
+#define Fraig_NodeSetVarStr(p,i) Fraig_BitStringSetBit(Fraig_Regular(p)->pSuppStr,i)
+#define Fraig_NodeHasVarStr(p,i) Fraig_BitStringHasBit(Fraig_Regular(p)->pSuppStr,i)
+
+// copied from "extra.h" for stand-aloneness
+#define Fraig_PrintTime(a,t) printf( "%s = ", (a) ); printf( "%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC) )
+
+#define Fraig_HashKey2(a,b,TSIZE) (((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b) * 12582917) % TSIZE)
+//#define Fraig_HashKey2(a,b,TSIZE) (( ((unsigned)(a)->Num * 19) ^ ((unsigned)(b)->Num * 1999) ) % TSIZE)
+//#define Fraig_HashKey2(a,b,TSIZE) ( ((unsigned)((a)->Num + (b)->Num) * ((a)->Num + (b)->Num + 1) / 2) % TSIZE)
+// the other two hash functions give bad distribution of hash chain lengths (not clear why)
+
+////////////////////////////////////////////////////////////////////////
+/// STRUCTURE DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Fraig_MemFixed_t_ Fraig_MemFixed_t;
+
+// the mapping manager
+struct Fraig_ManStruct_t_
+{
+ // the AIG nodes
+ Fraig_NodeVec_t * vInputs; // the array of primary inputs
+ Fraig_NodeVec_t * vNodes; // the array of all nodes, including primary inputs
+ Fraig_NodeVec_t * vOutputs; // the array of primary outputs (some internal nodes)
+ Fraig_Node_t * pConst1; // the pointer to the constant node (vNodes->pArray[0])
+
+ // info about the original circuit
+ char ** ppInputNames; // the primary input names
+ char ** ppOutputNames; // the primary output names
+
+ // various hash-tables
+ Fraig_HashTable_t * pTableS; // hashing by structure
+ Fraig_HashTable_t * pTableF; // hashing by simulation info
+ Fraig_HashTable_t * pTableF0; // hashing by simulation info (sparse functions)
+
+ // parameters
+ int nWordsRand; // the number of words of random simulation info
+ int nWordsDyna; // the number of words of dynamic simulation info
+ int nBTLimit; // the max number of backtracks to perform
+ int nSeconds; // the runtime limit for the miter proof
+ int fFuncRed; // performs only one level hashing
+ int fFeedBack; // enables solver feedback
+ int fDist1Pats; // enables solver feedback
+ int fDoSparse; // performs equiv tests for sparse functions
+ int fChoicing; // enables recording structural choices
+ int fTryProve; // tries to solve the final miter
+ int fVerbose; // the verbosiness flag
+ int fVerboseP; // the verbosiness flag
+ ABC_INT64_T nInspLimit; // the inspection limit
+
+ int nTravIds; // the traversal counter
+ int nTravIds2; // the traversal counter
+
+ // info related to the solver feedback
+ int iWordStart; // the first word to use for simulation
+ int iWordPerm; // the number of words stored permanently
+ int iPatsPerm; // the number of patterns stored permanently
+ Fraig_NodeVec_t * vCones; // the temporary array of internal variables
+ Msat_IntVec_t * vPatsReal; // the array of real pattern numbers
+ unsigned * pSimsReal; // used for simulation patterns
+ unsigned * pSimsDiff; // used for simulation patterns
+ unsigned * pSimsTemp; // used for simulation patterns
+
+ // the support information
+ int nSuppWords;
+ unsigned ** pSuppS;
+ unsigned ** pSuppF;
+
+ // the memory managers
+ Fraig_MemFixed_t * mmNodes; // the memory manager for nodes
+ Fraig_MemFixed_t * mmSims; // the memory manager for simulation info
+
+ // solving the SAT problem
+ Msat_Solver_t * pSat; // the SAT solver
+ Msat_IntVec_t * vProj; // the temporary array of projection vars
+ int nSatNums; // the counter of SAT variables
+ int * pModel; // the assignment, which satisfies the miter
+ // these arrays belong to the solver
+ Msat_IntVec_t * vVarsInt; // the temporary array of variables
+ Msat_ClauseVec_t * vAdjacents; // the temporary storage for connectivity
+ Msat_IntVec_t * vVarsUsed; // the array marking vars appearing in the cone
+
+ // various statistic variables
+ int nSatCalls; // the number of times equivalence checking was called
+ int nSatProof; // the number of times a proof was found
+ int nSatCounter; // the number of times a counter example was found
+ int nSatFails; // the number of times the SAT solver failed to complete due to resource limit or prediction
+ int nSatFailsReal; // the number of times the SAT solver failed to complete due to resource limit
+
+ int nSatCallsImp; // the number of times equivalence checking was called
+ int nSatProofImp; // the number of times a proof was found
+ int nSatCounterImp;// the number of times a counter example was found
+ int nSatFailsImp; // the number of times the SAT solver failed to complete
+
+ int nSatZeros; // the number of times the simulation vector is zero
+ int nSatSupps; // the number of times the support info was useful
+ int nRefErrors; // the number of ref counting errors
+ int nImplies; // the number of implication cases
+ int nSatImpls; // the number of implication SAT calls
+ int nVarsClauses; // the number of variables with clauses
+ int nSimplifies0;
+ int nSimplifies1;
+ int nImplies0;
+ int nImplies1;
+
+ // runtime statistics
+ int timeToAig; // time to transfer to the mapping structure
+ int timeSims; // time to compute k-feasible cuts
+ int timeTrav; // time to traverse the network
+ int timeFeed; // time for solver feedback (recording and resimulating)
+ int timeImply; // time to analyze implications
+ int timeSat; // time to compute the truth table for each cut
+ int timeToNet; // time to transfer back to the network
+ int timeTotal; // the total mapping time
+ int time1; // time to perform one task
+ int time2; // time to perform another task
+ int time3; // time to perform another task
+ int time4; // time to perform another task
+};
+
+// the mapping node
+struct Fraig_NodeStruct_t_
+{
+ // various numbers associated with the node
+ int Num; // the unique number (SAT var number) of this node
+ int NumPi; // if the node is a PI, this is its variable number
+ int Level; // the level of the node
+ int nRefs; // the number of references of the node
+ int TravId; // the traversal ID (use to avoid cleaning marks)
+ int TravId2; // the traversal ID (use to avoid cleaning marks)
+
+ // general information about the node
+ unsigned fInv : 1; // the mark to show that simulation info is complemented
+ unsigned fNodePo : 1; // the mark used for primary outputs
+ unsigned fClauses : 1; // the clauses for this node are loaded
+ unsigned fMark0 : 1; // the mark used for traversals
+ unsigned fMark1 : 1; // the mark used for traversals
+ unsigned fMark2 : 1; // the mark used for traversals
+ unsigned fMark3 : 1; // the mark used for traversals
+ unsigned fFeedUse : 1; // the presence of the variable in the feedback
+ unsigned fFeedVal : 1; // the value of the variable in the feedback
+ unsigned fFailTfo : 1; // the node is in the TFO of the failed SAT run
+ unsigned nFanouts : 2; // the indicator of fanouts (none, one, or many)
+ unsigned nOnes : 20; // the number of 1's in the random sim info
+
+ // the children of the node
+ Fraig_Node_t * p1; // the first child
+ Fraig_Node_t * p2; // the second child
+ Fraig_NodeVec_t * vFanins; // the fanins of the supergate rooted at this node
+// Fraig_NodeVec_t * vFanouts; // the fanouts of the supergate rooted at this node
+
+ // various linked lists
+ Fraig_Node_t * pNextS; // the next node in the structural hash table
+ Fraig_Node_t * pNextF; // the next node in the functional (simulation) hash table
+ Fraig_Node_t * pNextD; // the next node in the list of nodes based on dynamic simulation
+ Fraig_Node_t * pNextE; // the next structural choice (functionally-equivalent node)
+ Fraig_Node_t * pRepr; // the canonical functional representative of the node
+
+ // simulation data
+ unsigned uHashR; // the hash value for random information
+ unsigned uHashD; // the hash value for dynamic information
+ unsigned * puSimR; // the simulation information (random)
+ unsigned * puSimD; // the simulation information (dynamic)
+
+ // misc information
+ Fraig_Node_t * pData0; // temporary storage for the corresponding network node
+ Fraig_Node_t * pData1; // temporary storage for the corresponding network node
+
+#ifdef FRAIG_ENABLE_FANOUTS
+ // representation of node's fanouts
+ Fraig_Node_t * pFanPivot; // the first fanout of this node
+ Fraig_Node_t * pFanFanin1; // the next fanout of p1
+ Fraig_Node_t * pFanFanin2; // the next fanout of p2
+#endif
+};
+
+// the vector of nodes
+struct Fraig_NodeVecStruct_t_
+{
+ int nCap; // the number of allocated entries
+ int nSize; // the number of entries in the array
+ Fraig_Node_t ** pArray; // the array of nodes
+};
+
+// the hash table
+struct Fraig_HashTableStruct_t_
+{
+ Fraig_Node_t ** pBins; // the table bins
+ int nBins; // the size of the table
+ int nEntries; // the total number of entries in the table
+};
+
+// getting hold of the next fanout of the node
+#define Fraig_NodeReadNextFanout( pNode, pFanout ) \
+ ( ( pFanout == NULL )? NULL : \
+ ((Fraig_Regular((pFanout)->p1) == (pNode))? \
+ (pFanout)->pFanFanin1 : (pFanout)->pFanFanin2) )
+// getting hold of the place where the next fanout will be attached
+#define Fraig_NodeReadNextFanoutPlace( pNode, pFanout ) \
+ ( (Fraig_Regular((pFanout)->p1) == (pNode))? \
+ &(pFanout)->pFanFanin1 : &(pFanout)->pFanFanin2 )
+// iterator through the fanouts of the node
+#define Fraig_NodeForEachFanout( pNode, pFanout ) \
+ for ( pFanout = (pNode)->pFanPivot; pFanout; \
+ pFanout = Fraig_NodeReadNextFanout(pNode, pFanout) )
+// safe iterator through the fanouts of the node
+#define Fraig_NodeForEachFanoutSafe( pNode, pFanout, pFanout2 ) \
+ for ( pFanout = (pNode)->pFanPivot, \
+ pFanout2 = Fraig_NodeReadNextFanout(pNode, pFanout); \
+ pFanout; \
+ pFanout = pFanout2, \
+ pFanout2 = Fraig_NodeReadNextFanout(pNode, pFanout) )
+
+// iterators through the entries in the linked lists of nodes
+// the list of nodes in the structural hash table
+#define Fraig_TableBinForEachEntryS( pBin, pEnt ) \
+ for ( pEnt = pBin; \
+ pEnt; \
+ pEnt = pEnt->pNextS )
+#define Fraig_TableBinForEachEntrySafeS( pBin, pEnt, pEnt2 ) \
+ for ( pEnt = pBin, \
+ pEnt2 = pEnt? pEnt->pNextS: NULL; \
+ pEnt; \
+ pEnt = pEnt2, \
+ pEnt2 = pEnt? pEnt->pNextS: NULL )
+// the list of nodes in the functional (simulation) hash table
+#define Fraig_TableBinForEachEntryF( pBin, pEnt ) \
+ for ( pEnt = pBin; \
+ pEnt; \
+ pEnt = pEnt->pNextF )
+#define Fraig_TableBinForEachEntrySafeF( pBin, pEnt, pEnt2 ) \
+ for ( pEnt = pBin, \
+ pEnt2 = pEnt? pEnt->pNextF: NULL; \
+ pEnt; \
+ pEnt = pEnt2, \
+ pEnt2 = pEnt? pEnt->pNextF: NULL )
+// the list of nodes with the same simulation and different functionality
+#define Fraig_TableBinForEachEntryD( pBin, pEnt ) \
+ for ( pEnt = pBin; \
+ pEnt; \
+ pEnt = pEnt->pNextD )
+#define Fraig_TableBinForEachEntrySafeD( pBin, pEnt, pEnt2 ) \
+ for ( pEnt = pBin, \
+ pEnt2 = pEnt? pEnt->pNextD: NULL; \
+ pEnt; \
+ pEnt = pEnt2, \
+ pEnt2 = pEnt? pEnt->pNextD: NULL )
+// the list of nodes with the same functionality
+#define Fraig_TableBinForEachEntryE( pBin, pEnt ) \
+ for ( pEnt = pBin; \
+ pEnt; \
+ pEnt = pEnt->pNextE )
+#define Fraig_TableBinForEachEntrySafeE( pBin, pEnt, pEnt2 ) \
+ for ( pEnt = pBin, \
+ pEnt2 = pEnt? pEnt->pNextE: NULL; \
+ pEnt; \
+ pEnt = pEnt2, \
+ pEnt2 = pEnt? pEnt->pNextE: NULL )
+
+////////////////////////////////////////////////////////////////////////
+/// GLOBAL VARIABLES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== fraigCanon.c =============================================================*/
+extern Fraig_Node_t * Fraig_NodeAndCanon( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2 );
+/*=== fraigFanout.c =============================================================*/
+extern void Fraig_NodeAddFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanout );
+extern void Fraig_NodeRemoveFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanoutToRemove );
+extern int Fraig_NodeGetFanoutNum( Fraig_Node_t * pNode );
+/*=== fraigFeed.c =============================================================*/
+extern void Fraig_FeedBackInit( Fraig_Man_t * p );
+extern void Fraig_FeedBack( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars, Fraig_Node_t * pOld, Fraig_Node_t * pNew );
+extern void Fraig_FeedBackTest( Fraig_Man_t * p );
+extern int Fraig_FeedBackCompress( Fraig_Man_t * p );
+extern int * Fraig_ManAllocCounterExample( Fraig_Man_t * p );
+extern int * Fraig_ManSaveCounterExample( Fraig_Man_t * p, Fraig_Node_t * pNode );
+/*=== fraigMan.c =============================================================*/
+extern void Fraig_ManCreateSolver( Fraig_Man_t * p );
+/*=== fraigMem.c =============================================================*/
+extern Fraig_MemFixed_t * Fraig_MemFixedStart( int nEntrySize );
+extern void Fraig_MemFixedStop( Fraig_MemFixed_t * p, int fVerbose );
+extern char * Fraig_MemFixedEntryFetch( Fraig_MemFixed_t * p );
+extern void Fraig_MemFixedEntryRecycle( Fraig_MemFixed_t * p, char * pEntry );
+extern void Fraig_MemFixedRestart( Fraig_MemFixed_t * p );
+extern int Fraig_MemFixedReadMemUsage( Fraig_MemFixed_t * p );
+/*=== fraigNode.c =============================================================*/
+extern Fraig_Node_t * Fraig_NodeCreateConst( Fraig_Man_t * p );
+extern Fraig_Node_t * Fraig_NodeCreatePi( Fraig_Man_t * p );
+extern Fraig_Node_t * Fraig_NodeCreate( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 );
+extern void Fraig_NodeSimulate( Fraig_Node_t * pNode, int iWordStart, int iWordStop, int fUseRand );
+/*=== fraigPrime.c =============================================================*/
+extern int s_FraigPrimes[FRAIG_MAX_PRIMES];
+/*=== fraigSat.c ===============================================================*/
+extern int Fraig_NodeIsImplication( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit );
+/*=== fraigTable.c =============================================================*/
+extern Fraig_HashTable_t * Fraig_HashTableCreate( int nSize );
+extern void Fraig_HashTableFree( Fraig_HashTable_t * p );
+extern int Fraig_HashTableLookupS( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2, Fraig_Node_t ** ppNodeRes );
+extern Fraig_Node_t * Fraig_HashTableLookupF( Fraig_Man_t * pMan, Fraig_Node_t * pNode );
+extern Fraig_Node_t * Fraig_HashTableLookupF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode );
+extern void Fraig_HashTableInsertF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode );
+extern int Fraig_CompareSimInfo( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand );
+extern int Fraig_CompareSimInfoUnderMask( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask );
+extern int Fraig_FindFirstDiff( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int fCompl, int iWordLast, int fUseRand );
+extern void Fraig_CollectXors( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask );
+extern void Fraig_TablePrintStatsS( Fraig_Man_t * pMan );
+extern void Fraig_TablePrintStatsF( Fraig_Man_t * pMan );
+extern void Fraig_TablePrintStatsF0( Fraig_Man_t * pMan );
+extern int Fraig_TableRehashF0( Fraig_Man_t * pMan, int fLinkEquiv );
+/*=== fraigUtil.c ===============================================================*/
+extern int Fraig_NodeCountPis( Msat_IntVec_t * vVars, int nVarsPi );
+extern int Fraig_NodeCountSuppVars( Fraig_Man_t * p, Fraig_Node_t * pNode, int fSuppStr );
+extern int Fraig_NodesCompareSupps( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew );
+extern int Fraig_NodeAndSimpleCase_rec( Fraig_Node_t * pOld, Fraig_Node_t * pNew );
+extern int Fraig_NodeIsExorType( Fraig_Node_t * pNode );
+extern void Fraig_ManSelectBestChoice( Fraig_Man_t * p );
+extern int Fraig_BitStringCountOnes( unsigned * pString, int nWords );
+extern void Fraig_PrintBinary( FILE * pFile, unsigned * pSign, int nBits );
+extern int Fraig_NodeIsExorType( Fraig_Node_t * pNode );
+extern int Fraig_NodeIsExor( Fraig_Node_t * pNode );
+extern int Fraig_NodeIsMuxType( Fraig_Node_t * pNode );
+extern Fraig_Node_t * Fraig_NodeRecognizeMux( Fraig_Node_t * pNode, Fraig_Node_t ** ppNodeT, Fraig_Node_t ** ppNodeE );
+extern int Fraig_ManCountExors( Fraig_Man_t * pMan );
+extern int Fraig_ManCountMuxes( Fraig_Man_t * pMan );
+extern int Fraig_NodeSimsContained( Fraig_Man_t * pMan, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 );
+extern int Fraig_NodeIsInSupergate( Fraig_Node_t * pOld, Fraig_Node_t * pNew );
+extern Fraig_NodeVec_t * Fraig_CollectSupergate( Fraig_Node_t * pNode, int fStopAtMux );
+extern int Fraig_CountPis( Fraig_Man_t * p, Msat_IntVec_t * vVarNums );
+extern void Fraig_ManIncrementTravId( Fraig_Man_t * pMan );
+extern void Fraig_NodeSetTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode );
+extern int Fraig_NodeIsTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode );
+extern int Fraig_NodeIsTravIdPrevious( Fraig_Man_t * pMan, Fraig_Node_t * pNode );
+/*=== fraigVec.c ===============================================================*/
+extern void Fraig_NodeVecSortByRefCount( Fraig_NodeVec_t * p );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
diff --git a/src/proof/fraig/fraigMan.c b/src/proof/fraig/fraigMan.c
new file mode 100644
index 00000000..ba08d793
--- /dev/null
+++ b/src/proof/fraig/fraigMan.c
@@ -0,0 +1,545 @@
+/**CFile****************************************************************
+
+ FileName [fraigMan.c]
+
+ PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+ Synopsis [Implementation of the FRAIG manager.]
+
+ Author [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - October 1, 2004]
+
+ Revision [$Id: fraigMan.c,v 1.11 2005/07/08 01:01:31 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fraigInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+int timeSelect;
+int timeAssign;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Sets the default parameters of the package.]
+
+ Description [This set of parameters is tuned for equivalence checking.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Prove_ParamsSetDefault( Prove_Params_t * pParams )
+{
+ // clean the parameter structure
+ memset( pParams, 0, sizeof(Prove_Params_t) );
+ // general parameters
+ pParams->fUseFraiging = 1; // enables fraiging
+ pParams->fUseRewriting = 1; // enables rewriting
+ pParams->fUseBdds = 0; // enables BDD construction when other methods fail
+ pParams->fVerbose = 0; // prints verbose stats
+ // iterations
+ pParams->nItersMax = 6; // the number of iterations
+ // mitering
+ pParams->nMiteringLimitStart = 5000; // starting mitering limit
+ pParams->nMiteringLimitMulti = 2.0; // multiplicative coefficient to increase the limit in each iteration
+ // rewriting (currently not used)
+ pParams->nRewritingLimitStart = 3; // the number of rewriting iterations
+ pParams->nRewritingLimitMulti = 1.0; // multiplicative coefficient to increase the limit in each iteration
+ // fraiging
+ pParams->nFraigingLimitStart = 2; // starting backtrack(conflict) limit
+ pParams->nFraigingLimitMulti = 8.0; // multiplicative coefficient to increase the limit in each iteration
+ // last-gasp BDD construction
+ pParams->nBddSizeLimit = 1000000; // the number of BDD nodes when construction is aborted
+ pParams->fBddReorder = 1; // enables dynamic BDD variable reordering
+ // last-gasp mitering
+// pParams->nMiteringLimitLast = 1000000; // final mitering limit
+ pParams->nMiteringLimitLast = 0; // final mitering limit
+ // global SAT solver limits
+ pParams->nTotalBacktrackLimit = 0; // global limit on the number of backtracks
+ pParams->nTotalInspectLimit = 0; // global limit on the number of clause inspects
+// pParams->nTotalInspectLimit = 100000000; // global limit on the number of clause inspects
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints out the current values of CEC engine parameters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Prove_ParamsPrint( Prove_Params_t * pParams )
+{
+ printf( "CEC enging parameters:\n" );
+ printf( "Fraiging enabled: %s\n", pParams->fUseFraiging? "yes":"no" );
+ printf( "Rewriting enabled: %s\n", pParams->fUseRewriting? "yes":"no" );
+ printf( "BDD construction enabled: %s\n", pParams->fUseBdds? "yes":"no" );
+ printf( "Verbose output enabled: %s\n", pParams->fVerbose? "yes":"no" );
+ printf( "Solver iterations: %d\n", pParams->nItersMax );
+ printf( "Starting mitering limit: %d\n", pParams->nMiteringLimitStart );
+ printf( "Multiplicative coeficient for mitering: %.2f\n", pParams->nMiteringLimitMulti );
+ printf( "Starting number of rewriting iterations: %d\n", pParams->nRewritingLimitStart );
+ printf( "Multiplicative coeficient for rewriting: %.2f\n", pParams->nRewritingLimitMulti );
+ printf( "Starting number of conflicts in fraiging: %.2f\n", pParams->nFraigingLimitMulti );
+ printf( "Multiplicative coeficient for fraiging: %.2f\n", pParams->nRewritingLimitMulti );
+ printf( "BDD size limit for bailing out: %d\n", pParams->nBddSizeLimit );
+ printf( "BDD reordering enabled: %s\n", pParams->fBddReorder? "yes":"no" );
+ printf( "Last-gasp mitering limit: %d\n", pParams->nMiteringLimitLast );
+ printf( "Total conflict limit: %lld\n", pParams->nTotalBacktrackLimit );
+ printf( "Total inspection limit: %lld\n", pParams->nTotalInspectLimit );
+ printf( "Parameter dump complete.\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the default parameters of the package.]
+
+ Description [This set of parameters is tuned for equivalence checking.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_ParamsSetDefault( Fraig_Params_t * pParams )
+{
+ memset( pParams, 0, sizeof(Fraig_Params_t) );
+ pParams->nPatsRand = FRAIG_PATTERNS_RANDOM; // the number of words of random simulation info
+ pParams->nPatsDyna = FRAIG_PATTERNS_DYNAMIC; // the number of words of dynamic simulation info
+ pParams->nBTLimit = 99; // the max number of backtracks to perform
+ pParams->nSeconds = 20; // the max number of seconds to solve the miter
+ pParams->fFuncRed = 1; // performs only one level hashing
+ pParams->fFeedBack = 1; // enables solver feedback
+ pParams->fDist1Pats = 1; // enables distance-1 patterns
+ pParams->fDoSparse = 0; // performs equiv tests for sparse functions
+ pParams->fChoicing = 0; // enables recording structural choices
+ pParams->fTryProve = 1; // tries to solve the final miter
+ pParams->fVerbose = 0; // the verbosiness flag
+ pParams->fVerboseP = 0; // the verbose flag for reporting the proof
+ pParams->fInternal = 0; // the flag indicates the internal run
+ pParams->nConfLimit = 0; // the limit on the number of conflicts
+ pParams->nInspLimit = 0; // the limit on the number of inspections
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the default parameters of the package.]
+
+ Description [This set of parameters is tuned for complete FRAIGing.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_ParamsSetDefaultFull( Fraig_Params_t * pParams )
+{
+ memset( pParams, 0, sizeof(Fraig_Params_t) );
+ pParams->nPatsRand = FRAIG_PATTERNS_RANDOM; // the number of words of random simulation info
+ pParams->nPatsDyna = FRAIG_PATTERNS_DYNAMIC; // the number of words of dynamic simulation info
+ pParams->nBTLimit = -1; // the max number of backtracks to perform
+ pParams->nSeconds = 20; // the max number of seconds to solve the miter
+ pParams->fFuncRed = 1; // performs only one level hashing
+ pParams->fFeedBack = 1; // enables solver feedback
+ pParams->fDist1Pats = 1; // enables distance-1 patterns
+ pParams->fDoSparse = 1; // performs equiv tests for sparse functions
+ pParams->fChoicing = 0; // enables recording structural choices
+ pParams->fTryProve = 0; // tries to solve the final miter
+ pParams->fVerbose = 0; // the verbosiness flag
+ pParams->fVerboseP = 0; // the verbose flag for reporting the proof
+ pParams->fInternal = 0; // the flag indicates the internal run
+ pParams->nConfLimit = 0; // the limit on the number of conflicts
+ pParams->nInspLimit = 0; // the limit on the number of inspections
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the new FRAIG manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_Man_t * Fraig_ManCreate( Fraig_Params_t * pParams )
+{
+ Fraig_Params_t Params;
+ Fraig_Man_t * p;
+
+ // set the random seed for simulation
+// srand( 0xFEEDDEAF );
+ srand( 0xDEADCAFE );
+
+ // set parameters for equivalence checking
+ if ( pParams == NULL )
+ Fraig_ParamsSetDefault( pParams = &Params );
+ // adjust the amount of simulation info
+ if ( pParams->nPatsRand < 128 )
+ pParams->nPatsRand = 128;
+ if ( pParams->nPatsRand > 32768 )
+ pParams->nPatsRand = 32768;
+ if ( pParams->nPatsDyna < 128 )
+ pParams->nPatsDyna = 128;
+ if ( pParams->nPatsDyna > 32768 )
+ pParams->nPatsDyna = 32768;
+ // if reduction is not performed, allocate minimum simulation info
+ if ( !pParams->fFuncRed )
+ pParams->nPatsRand = pParams->nPatsDyna = 128;
+
+ // start the manager
+ p = ABC_ALLOC( Fraig_Man_t, 1 );
+ memset( p, 0, sizeof(Fraig_Man_t) );
+
+ // set the default parameters
+ p->nWordsRand = FRAIG_NUM_WORDS( pParams->nPatsRand ); // the number of words of random simulation info
+ p->nWordsDyna = FRAIG_NUM_WORDS( pParams->nPatsDyna ); // the number of patterns for dynamic simulation info
+ p->nBTLimit = pParams->nBTLimit; // -1 means infinite backtrack limit
+ p->nSeconds = pParams->nSeconds; // the timeout for the final miter
+ p->fFuncRed = pParams->fFuncRed; // enables functional reduction (otherwise, only one-level hashing is performed)
+ p->fFeedBack = pParams->fFeedBack; // enables solver feedback (the use of counter-examples in simulation)
+ p->fDist1Pats = pParams->fDist1Pats; // enables solver feedback (the use of counter-examples in simulation)
+ p->fDoSparse = pParams->fDoSparse; // performs equivalence checking for sparse functions (whose sim-info is 0)
+ p->fChoicing = pParams->fChoicing; // disable accumulation of structural choices (keeps only the first choice)
+ p->fTryProve = pParams->fTryProve; // disable accumulation of structural choices (keeps only the first choice)
+ p->fVerbose = pParams->fVerbose; // disable verbose output
+ p->fVerboseP = pParams->fVerboseP; // disable verbose output
+ p->nInspLimit = pParams->nInspLimit; // the limit on the number of inspections
+
+ // start memory managers
+ p->mmNodes = Fraig_MemFixedStart( sizeof(Fraig_Node_t) );
+ p->mmSims = Fraig_MemFixedStart( sizeof(unsigned) * (p->nWordsRand + p->nWordsDyna) );
+ // allocate node arrays
+ p->vInputs = Fraig_NodeVecAlloc( 1000 ); // the array of primary inputs
+ p->vOutputs = Fraig_NodeVecAlloc( 1000 ); // the array of primary outputs
+ p->vNodes = Fraig_NodeVecAlloc( 1000 ); // the array of internal nodes
+ // start the tables
+ p->pTableS = Fraig_HashTableCreate( 1000 ); // hashing by structure
+ p->pTableF = Fraig_HashTableCreate( 1000 ); // hashing by function
+ p->pTableF0 = Fraig_HashTableCreate( 1000 ); // hashing by function (for sparse functions)
+ // create the constant node
+ p->pConst1 = Fraig_NodeCreateConst( p );
+ // initialize SAT solver feedback data structures
+ Fraig_FeedBackInit( p );
+ // initialize other variables
+ p->vProj = Msat_IntVecAlloc( 10 );
+ p->nTravIds = 1;
+ p->nTravIds2 = 1;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates the mapping manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_ManFree( Fraig_Man_t * p )
+{
+ int i;
+ if ( p->fVerbose )
+ {
+ if ( p->fChoicing ) Fraig_ManReportChoices( p );
+ Fraig_ManPrintStats( p );
+// Fraig_TablePrintStatsS( p );
+// Fraig_TablePrintStatsF( p );
+// Fraig_TablePrintStatsF0( p );
+ }
+
+ for ( i = 0; i < p->vNodes->nSize; i++ )
+ if ( p->vNodes->pArray[i]->vFanins )
+ {
+ Fraig_NodeVecFree( p->vNodes->pArray[i]->vFanins );
+ p->vNodes->pArray[i]->vFanins = NULL;
+ }
+
+ if ( p->vInputs ) Fraig_NodeVecFree( p->vInputs );
+ if ( p->vNodes ) Fraig_NodeVecFree( p->vNodes );
+ if ( p->vOutputs ) Fraig_NodeVecFree( p->vOutputs );
+
+ if ( p->pTableS ) Fraig_HashTableFree( p->pTableS );
+ if ( p->pTableF ) Fraig_HashTableFree( p->pTableF );
+ if ( p->pTableF0 ) Fraig_HashTableFree( p->pTableF0 );
+
+ if ( p->pSat ) Msat_SolverFree( p->pSat );
+ if ( p->vProj ) Msat_IntVecFree( p->vProj );
+ if ( p->vCones ) Fraig_NodeVecFree( p->vCones );
+ if ( p->vPatsReal ) Msat_IntVecFree( p->vPatsReal );
+ if ( p->pModel ) ABC_FREE( p->pModel );
+
+ Fraig_MemFixedStop( p->mmNodes, 0 );
+ Fraig_MemFixedStop( p->mmSims, 0 );
+
+ if ( p->pSuppS )
+ {
+ ABC_FREE( p->pSuppS[0] );
+ ABC_FREE( p->pSuppS );
+ }
+ if ( p->pSuppF )
+ {
+ ABC_FREE( p->pSuppF[0] );
+ ABC_FREE( p->pSuppF );
+ }
+
+ ABC_FREE( p->ppOutputNames );
+ ABC_FREE( p->ppInputNames );
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the SAT solver to run on the two nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_ManCreateSolver( Fraig_Man_t * p )
+{
+ extern int timeSelect;
+ extern int timeAssign;
+ assert( p->pSat == NULL );
+ // allocate data for SAT solving
+ p->pSat = Msat_SolverAlloc( 500, 1, 1, 1, 1, 0 );
+ p->vVarsInt = Msat_SolverReadConeVars( p->pSat );
+ p->vAdjacents = Msat_SolverReadAdjacents( p->pSat );
+ p->vVarsUsed = Msat_SolverReadVarsUsed( p->pSat );
+ timeSelect = 0;
+ timeAssign = 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates the mapping manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_ManPrintStats( Fraig_Man_t * p )
+{
+ double nMemory;
+ nMemory = ((double)(p->vInputs->nSize + p->vNodes->nSize) *
+ (sizeof(Fraig_Node_t) + sizeof(unsigned)*(p->nWordsRand + p->nWordsDyna) /*+ p->nSuppWords*sizeof(unsigned)*/))/(1<<20);
+ printf( "Words: Random = %d. Dynamic = %d. Used = %d. Memory = %0.2f Mb.\n",
+ p->nWordsRand, p->nWordsDyna, p->iWordPerm, nMemory );
+ printf( "Proof = %d. Counter-example = %d. Fail = %d. FailReal = %d. Zero = %d.\n",
+ p->nSatProof, p->nSatCounter, p->nSatFails, p->nSatFailsReal, p->nSatZeros );
+ printf( "Nodes: Final = %d. Total = %d. Mux = %d. (Exor = %d.) ClaVars = %d.\n",
+ Fraig_CountNodes(p,0), p->vNodes->nSize, Fraig_ManCountMuxes(p), Fraig_ManCountExors(p), p->nVarsClauses );
+ if ( p->pSat ) Msat_SolverPrintStats( p->pSat );
+ Fraig_PrintTime( "AIG simulation ", p->timeSims );
+ Fraig_PrintTime( "AIG traversal ", p->timeTrav );
+ Fraig_PrintTime( "Solver feedback ", p->timeFeed );
+ Fraig_PrintTime( "SAT solving ", p->timeSat );
+ Fraig_PrintTime( "Network update ", p->timeToNet );
+ Fraig_PrintTime( "TOTAL RUNTIME ", p->timeTotal );
+ if ( p->time1 > 0 ) { Fraig_PrintTime( "time1", p->time1 ); }
+ if ( p->time2 > 0 ) { Fraig_PrintTime( "time2", p->time2 ); }
+ if ( p->time3 > 0 ) { Fraig_PrintTime( "time3", p->time3 ); }
+ if ( p->time4 > 0 ) { Fraig_PrintTime( "time4", p->time4 ); }
+// ABC_PRT( "Selection ", timeSelect );
+// ABC_PRT( "Assignment", timeAssign );
+ fflush( stdout );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocates simulation information for all nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_NodeVec_t * Fraig_UtilInfoAlloc( int nSize, int nWords, int fClean )
+{
+ Fraig_NodeVec_t * vInfo;
+ unsigned * pUnsigned;
+ int i;
+ assert( nSize > 0 && nWords > 0 );
+ vInfo = Fraig_NodeVecAlloc( nSize );
+ pUnsigned = ABC_ALLOC( unsigned, nSize * nWords );
+ vInfo->pArray[0] = (Fraig_Node_t *)pUnsigned;
+ if ( fClean )
+ memset( pUnsigned, 0, sizeof(unsigned) * nSize * nWords );
+ for ( i = 1; i < nSize; i++ )
+ vInfo->pArray[i] = (Fraig_Node_t *)(((unsigned *)vInfo->pArray[i-1]) + nWords);
+ vInfo->nSize = nSize;
+ return vInfo;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns simulation info of all nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_NodeVec_t * Fraig_ManGetSimInfo( Fraig_Man_t * p )
+{
+ Fraig_NodeVec_t * vInfo;
+ Fraig_Node_t * pNode;
+ unsigned * pUnsigned;
+ int nRandom, nDynamic;
+ int i, k, nWords;
+
+ nRandom = Fraig_ManReadPatternNumRandom( p );
+ nDynamic = Fraig_ManReadPatternNumDynamic( p );
+ nWords = nRandom / 32 + nDynamic / 32;
+
+ vInfo = Fraig_UtilInfoAlloc( p->vNodes->nSize, nWords, 0 );
+ for ( i = 0; i < p->vNodes->nSize; i++ )
+ {
+ pNode = p->vNodes->pArray[i];
+ assert( i == pNode->Num );
+ pUnsigned = (unsigned *)vInfo->pArray[i];
+ for ( k = 0; k < nRandom / 32; k++ )
+ pUnsigned[k] = pNode->puSimR[k];
+ for ( k = 0; k < nDynamic / 32; k++ )
+ pUnsigned[nRandom / 32 + k] = pNode->puSimD[k];
+ }
+ return vInfo;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if A v B is always true based on the siminfo.]
+
+ Description [A v B is always true iff A' * B' is always false.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_ManCheckClauseUsingSimInfo( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 )
+{
+ int fCompl1, fCompl2, i;
+
+ fCompl1 = 1 ^ Fraig_IsComplement(pNode1) ^ Fraig_Regular(pNode1)->fInv;
+ fCompl2 = 1 ^ Fraig_IsComplement(pNode2) ^ Fraig_Regular(pNode2)->fInv;
+
+ pNode1 = Fraig_Regular(pNode1);
+ pNode2 = Fraig_Regular(pNode2);
+ assert( pNode1 != pNode2 );
+
+ // check the simulation info
+ if ( fCompl1 && fCompl2 )
+ {
+ for ( i = 0; i < p->nWordsRand; i++ )
+ if ( ~pNode1->puSimR[i] & ~pNode2->puSimR[i] )
+ return 0;
+ for ( i = 0; i < p->iWordStart; i++ )
+ if ( ~pNode1->puSimD[i] & ~pNode2->puSimD[i] )
+ return 0;
+ return 1;
+ }
+ if ( !fCompl1 && fCompl2 )
+ {
+ for ( i = 0; i < p->nWordsRand; i++ )
+ if ( pNode1->puSimR[i] & ~pNode2->puSimR[i] )
+ return 0;
+ for ( i = 0; i < p->iWordStart; i++ )
+ if ( pNode1->puSimD[i] & ~pNode2->puSimD[i] )
+ return 0;
+ return 1;
+ }
+ if ( fCompl1 && !fCompl2 )
+ {
+ for ( i = 0; i < p->nWordsRand; i++ )
+ if ( ~pNode1->puSimR[i] & pNode2->puSimR[i] )
+ return 0;
+ for ( i = 0; i < p->iWordStart; i++ )
+ if ( ~pNode1->puSimD[i] & pNode2->puSimD[i] )
+ return 0;
+ return 1;
+ }
+// if ( fCompl1 && fCompl2 )
+ {
+ for ( i = 0; i < p->nWordsRand; i++ )
+ if ( pNode1->puSimR[i] & pNode2->puSimR[i] )
+ return 0;
+ for ( i = 0; i < p->iWordStart; i++ )
+ if ( pNode1->puSimD[i] & pNode2->puSimD[i] )
+ return 0;
+ return 1;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds clauses to the solver.]
+
+ Description [This procedure is used to add external clauses to the solver.
+ The clauses are given by sets of nodes. Each node stands for one literal.
+ If the node is complemented, the literal is negated.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_ManAddClause( Fraig_Man_t * p, Fraig_Node_t ** ppNodes, int nNodes )
+{
+ Fraig_Node_t * pNode;
+ int i, fComp, RetValue;
+ if ( p->pSat == NULL )
+ Fraig_ManCreateSolver( p );
+ // create four clauses
+ Msat_IntVecClear( p->vProj );
+ for ( i = 0; i < nNodes; i++ )
+ {
+ pNode = Fraig_Regular(ppNodes[i]);
+ fComp = Fraig_IsComplement(ppNodes[i]);
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, fComp) );
+// printf( "%d(%d) ", pNode->Num, fComp );
+ }
+// printf( "\n" );
+ RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+ assert( RetValue );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fraig/fraigMem.c b/src/proof/fraig/fraigMem.c
new file mode 100644
index 00000000..ef52765e
--- /dev/null
+++ b/src/proof/fraig/fraigMem.c
@@ -0,0 +1,251 @@
+/**CFile****************************************************************
+
+ FileName [fraigMem.c]
+
+ PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+ Synopsis [Fixed-size-entry memory manager for the FRAIG package.]
+
+ Author [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - October 1, 2004]
+
+ Revision [$Id: fraigMem.c,v 1.4 2005/07/08 01:01:31 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fraigInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+struct Fraig_MemFixed_t_
+{
+ // information about individual entries
+ int nEntrySize; // the size of one entry
+ int nEntriesAlloc; // the total number of entries allocated
+ int nEntriesUsed; // the number of entries in use
+ int nEntriesMax; // the max number of entries in use
+ char * pEntriesFree; // the linked list of free entries
+
+ // this is where the memory is stored
+ int nChunkSize; // the size of one chunk
+ int nChunksAlloc; // the maximum number of memory chunks
+ int nChunks; // the current number of memory chunks
+ char ** pChunks; // the allocated memory
+
+ // statistics
+ int nMemoryUsed; // memory used in the allocated entries
+ int nMemoryAlloc; // memory allocated
+};
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Starts the internal memory manager.]
+
+ Description [Can only work with entry size at least 4 byte long.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_MemFixed_t * Fraig_MemFixedStart( int nEntrySize )
+{
+ Fraig_MemFixed_t * p;
+
+ p = ABC_ALLOC( Fraig_MemFixed_t, 1 );
+ memset( p, 0, sizeof(Fraig_MemFixed_t) );
+
+ p->nEntrySize = nEntrySize;
+ p->nEntriesAlloc = 0;
+ p->nEntriesUsed = 0;
+ p->pEntriesFree = NULL;
+
+ if ( nEntrySize * (1 << 10) < (1<<16) )
+ p->nChunkSize = (1 << 10);
+ else
+ p->nChunkSize = (1<<16) / nEntrySize;
+ if ( p->nChunkSize < 8 )
+ p->nChunkSize = 8;
+
+ p->nChunksAlloc = 64;
+ p->nChunks = 0;
+ p->pChunks = ABC_ALLOC( char *, p->nChunksAlloc );
+
+ p->nMemoryUsed = 0;
+ p->nMemoryAlloc = 0;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the internal memory manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_MemFixedStop( Fraig_MemFixed_t * p, int fVerbose )
+{
+ int i;
+ if ( p == NULL )
+ return;
+ if ( fVerbose )
+ {
+ printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n",
+ p->nEntrySize, p->nChunkSize, p->nChunks );
+ printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n",
+ p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc );
+ }
+ for ( i = 0; i < p->nChunks; i++ )
+ ABC_FREE( p->pChunks[i] );
+ ABC_FREE( p->pChunks );
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Extracts one entry from the memory manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Fraig_MemFixedEntryFetch( Fraig_MemFixed_t * p )
+{
+ char * pTemp;
+ int i;
+
+ // check if there are still free entries
+ if ( p->nEntriesUsed == p->nEntriesAlloc )
+ { // need to allocate more entries
+ assert( p->pEntriesFree == NULL );
+ if ( p->nChunks == p->nChunksAlloc )
+ {
+ p->nChunksAlloc *= 2;
+ p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc );
+ }
+ p->pEntriesFree = ABC_ALLOC( char, p->nEntrySize * p->nChunkSize );
+ p->nMemoryAlloc += p->nEntrySize * p->nChunkSize;
+ // transform these entries into a linked list
+ pTemp = p->pEntriesFree;
+ for ( i = 1; i < p->nChunkSize; i++ )
+ {
+ *((char **)pTemp) = pTemp + p->nEntrySize;
+ pTemp += p->nEntrySize;
+ }
+ // set the last link
+ *((char **)pTemp) = NULL;
+ // add the chunk to the chunk storage
+ p->pChunks[ p->nChunks++ ] = p->pEntriesFree;
+ // add to the number of entries allocated
+ p->nEntriesAlloc += p->nChunkSize;
+ }
+ // incrememt the counter of used entries
+ p->nEntriesUsed++;
+ if ( p->nEntriesMax < p->nEntriesUsed )
+ p->nEntriesMax = p->nEntriesUsed;
+ // return the first entry in the free entry list
+ pTemp = p->pEntriesFree;
+ p->pEntriesFree = *((char **)pTemp);
+ return pTemp;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns one entry into the memory manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_MemFixedEntryRecycle( Fraig_MemFixed_t * p, char * pEntry )
+{
+ // decrement the counter of used entries
+ p->nEntriesUsed--;
+ // add the entry to the linked list of free entries
+ *((char **)pEntry) = p->pEntriesFree;
+ p->pEntriesFree = pEntry;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees all associated memory and resets the manager.]
+
+ Description [Relocates all the memory except the first chunk.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_MemFixedRestart( Fraig_MemFixed_t * p )
+{
+ int i;
+ char * pTemp;
+
+ // deallocate all chunks except the first one
+ for ( i = 1; i < p->nChunks; i++ )
+ ABC_FREE( p->pChunks[i] );
+ p->nChunks = 1;
+ // transform these entries into a linked list
+ pTemp = p->pChunks[0];
+ for ( i = 1; i < p->nChunkSize; i++ )
+ {
+ *((char **)pTemp) = pTemp + p->nEntrySize;
+ pTemp += p->nEntrySize;
+ }
+ // set the last link
+ *((char **)pTemp) = NULL;
+ // set the free entry list
+ p->pEntriesFree = p->pChunks[0];
+ // set the correct statistics
+ p->nMemoryAlloc = p->nEntrySize * p->nChunkSize;
+ p->nMemoryUsed = 0;
+ p->nEntriesAlloc = p->nChunkSize;
+ p->nEntriesUsed = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reports the memory usage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_MemFixedReadMemUsage( Fraig_MemFixed_t * p )
+{
+ return p->nMemoryAlloc;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fraig/fraigNode.c b/src/proof/fraig/fraigNode.c
new file mode 100644
index 00000000..609d5f65
--- /dev/null
+++ b/src/proof/fraig/fraigNode.c
@@ -0,0 +1,318 @@
+/**CFile****************************************************************
+
+ FileName [fraigNode.c]
+
+ PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+ Synopsis [Implementation of the FRAIG node.]
+
+ Author [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - October 1, 2004]
+
+ Revision [$Id: fraigNode.c,v 1.3 2005/07/08 01:01:32 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fraigInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// returns the complemented attribute of the node
+#define Fraig_NodeIsSimComplement(p) (Fraig_IsComplement(p)? !(Fraig_Regular(p)->fInv) : (p)->fInv)
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Creates the constant 1 node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_NodeCreateConst( Fraig_Man_t * p )
+{
+ Fraig_Node_t * pNode;
+
+ // create the node
+ pNode = (Fraig_Node_t *)Fraig_MemFixedEntryFetch( p->mmNodes );
+ memset( pNode, 0, sizeof(Fraig_Node_t) );
+
+ // assign the number and add to the array of nodes
+ pNode->Num = p->vNodes->nSize;
+ Fraig_NodeVecPush( p->vNodes, pNode );
+ pNode->NumPi = -1; // this is not a PI, so its number is -1
+ pNode->Level = 0; // just like a PI, it has 0 level
+ pNode->nRefs = 1; // it is a persistent node, which comes referenced
+ pNode->fInv = 1; // the simulation info is complemented
+
+ // create the simulation info
+ pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims );
+ pNode->puSimD = pNode->puSimR + p->nWordsRand;
+ memset( pNode->puSimR, 0, sizeof(unsigned) * p->nWordsRand );
+ memset( pNode->puSimD, 0, sizeof(unsigned) * p->nWordsDyna );
+
+ // count the number of ones in the simulation vector
+ pNode->nOnes = p->nWordsRand * sizeof(unsigned) * 8;
+
+ // insert it into the hash table
+ Fraig_HashTableLookupF0( p, pNode );
+ return pNode;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates a primary input node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_NodeCreatePi( Fraig_Man_t * p )
+{
+ Fraig_Node_t * pNode, * pNodeRes;
+ int i, clk;
+
+ // create the node
+ pNode = (Fraig_Node_t *)Fraig_MemFixedEntryFetch( p->mmNodes );
+ memset( pNode, 0, sizeof(Fraig_Node_t) );
+ pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims );
+ pNode->puSimD = pNode->puSimR + p->nWordsRand;
+ memset( pNode->puSimD, 0, sizeof(unsigned) * p->nWordsDyna );
+
+ // assign the number and add to the array of nodes
+ pNode->Num = p->vNodes->nSize;
+ Fraig_NodeVecPush( p->vNodes, pNode );
+
+ // assign the PI number and add to the array of primary inputs
+ pNode->NumPi = p->vInputs->nSize;
+ Fraig_NodeVecPush( p->vInputs, pNode );
+
+ pNode->Level = 0; // PI has 0 level
+ pNode->nRefs = 1; // it is a persistent node, which comes referenced
+ pNode->fInv = 0; // the simulation info of the PI is not complemented
+
+ // derive the simulation info for the new node
+clk = clock();
+ // set the random simulation info for the primary input
+ pNode->uHashR = 0;
+ for ( i = 0; i < p->nWordsRand; i++ )
+ {
+ // generate the simulation info
+ pNode->puSimR[i] = FRAIG_RANDOM_UNSIGNED;
+ // for reasons that take very long to explain, it makes sense to have (0000000...)
+ // pattern in the set (this helps if we need to return the counter-examples)
+ if ( i == 0 )
+ pNode->puSimR[i] <<= 1;
+ // compute the hash key
+ pNode->uHashR ^= pNode->puSimR[i] * s_FraigPrimes[i];
+ }
+ // count the number of ones in the simulation vector
+ pNode->nOnes = Fraig_BitStringCountOnes( pNode->puSimR, p->nWordsRand );
+
+ // set the systematic simulation info for the primary input
+ pNode->uHashD = 0;
+ for ( i = 0; i < p->iWordStart; i++ )
+ {
+ // generate the simulation info
+ pNode->puSimD[i] = FRAIG_RANDOM_UNSIGNED;
+ // compute the hash key
+ pNode->uHashD ^= pNode->puSimD[i] * s_FraigPrimes[i];
+ }
+p->timeSims += clock() - clk;
+
+ // insert it into the hash table
+ pNodeRes = Fraig_HashTableLookupF( p, pNode );
+ assert( pNodeRes == NULL );
+ // add to the runtime of simulation
+ return pNode;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates a new node.]
+
+ Description [This procedure should be called to create the constant
+ node and the PI nodes first.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_NodeCreate( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 )
+{
+ Fraig_Node_t * pNode;
+ int clk;
+
+ // create the node
+ pNode = (Fraig_Node_t *)Fraig_MemFixedEntryFetch( p->mmNodes );
+ memset( pNode, 0, sizeof(Fraig_Node_t) );
+
+ // assign the children
+ pNode->p1 = p1; Fraig_Ref(p1); Fraig_Regular(p1)->nRefs++;
+ pNode->p2 = p2; Fraig_Ref(p2); Fraig_Regular(p2)->nRefs++;
+
+ // assign the number and add to the array of nodes
+ pNode->Num = p->vNodes->nSize;
+ Fraig_NodeVecPush( p->vNodes, pNode );
+
+ // assign the PI number
+ pNode->NumPi = -1;
+
+ // compute the level of this node
+ pNode->Level = 1 + Abc_MaxInt(Fraig_Regular(p1)->Level, Fraig_Regular(p2)->Level);
+ pNode->fInv = Fraig_NodeIsSimComplement(p1) & Fraig_NodeIsSimComplement(p2);
+ pNode->fFailTfo = Fraig_Regular(p1)->fFailTfo | Fraig_Regular(p2)->fFailTfo;
+
+ // derive the simulation info
+clk = clock();
+ // allocate memory for the simulation info
+ pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims );
+ pNode->puSimD = pNode->puSimR + p->nWordsRand;
+ // derive random simulation info
+ pNode->uHashR = 0;
+ Fraig_NodeSimulate( pNode, 0, p->nWordsRand, 1 );
+ // derive dynamic simulation info
+ pNode->uHashD = 0;
+ Fraig_NodeSimulate( pNode, 0, p->iWordStart, 0 );
+ // count the number of ones in the random simulation info
+ pNode->nOnes = Fraig_BitStringCountOnes( pNode->puSimR, p->nWordsRand );
+ if ( pNode->fInv )
+ pNode->nOnes = p->nWordsRand * 32 - pNode->nOnes;
+ // add to the runtime of simulation
+p->timeSims += clock() - clk;
+
+#ifdef FRAIG_ENABLE_FANOUTS
+ // create the fanout info
+ Fraig_NodeAddFaninFanout( Fraig_Regular(p1), pNode );
+ Fraig_NodeAddFaninFanout( Fraig_Regular(p2), pNode );
+#endif
+ return pNode;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Simulates the node.]
+
+ Description [Simulates the random or dynamic simulation info through
+ the node. Uses phases of the children to determine their real simulation
+ info. Uses phase of the node to determine the way its simulation info
+ is stored. The resulting info is guaranteed to be 0 for the first pattern.]
+
+ SideEffects [This procedure modified the hash value of the simulation info.]
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_NodeSimulate( Fraig_Node_t * pNode, int iWordStart, int iWordStop, int fUseRand )
+{
+ unsigned * pSims, * pSims1, * pSims2;
+ unsigned uHash;
+ int fCompl, fCompl1, fCompl2, i;
+
+ assert( !Fraig_IsComplement(pNode) );
+
+ // get hold of the simulation information
+ pSims = fUseRand? pNode->puSimR : pNode->puSimD;
+ pSims1 = fUseRand? Fraig_Regular(pNode->p1)->puSimR : Fraig_Regular(pNode->p1)->puSimD;
+ pSims2 = fUseRand? Fraig_Regular(pNode->p2)->puSimR : Fraig_Regular(pNode->p2)->puSimD;
+
+ // get complemented attributes of the children using their random info
+ fCompl = pNode->fInv;
+ fCompl1 = Fraig_NodeIsSimComplement(pNode->p1);
+ fCompl2 = Fraig_NodeIsSimComplement(pNode->p2);
+
+ // simulate
+ uHash = 0;
+ if ( fCompl1 && fCompl2 )
+ {
+ if ( fCompl )
+ for ( i = iWordStart; i < iWordStop; i++ )
+ {
+ pSims[i] = (pSims1[i] | pSims2[i]);
+ uHash ^= pSims[i] * s_FraigPrimes[i];
+ }
+ else
+ for ( i = iWordStart; i < iWordStop; i++ )
+ {
+ pSims[i] = ~(pSims1[i] | pSims2[i]);
+ uHash ^= pSims[i] * s_FraigPrimes[i];
+ }
+ }
+ else if ( fCompl1 && !fCompl2 )
+ {
+ if ( fCompl )
+ for ( i = iWordStart; i < iWordStop; i++ )
+ {
+ pSims[i] = (pSims1[i] | ~pSims2[i]);
+ uHash ^= pSims[i] * s_FraigPrimes[i];
+ }
+ else
+ for ( i = iWordStart; i < iWordStop; i++ )
+ {
+ pSims[i] = (~pSims1[i] & pSims2[i]);
+ uHash ^= pSims[i] * s_FraigPrimes[i];
+ }
+ }
+ else if ( !fCompl1 && fCompl2 )
+ {
+ if ( fCompl )
+ for ( i = iWordStart; i < iWordStop; i++ )
+ {
+ pSims[i] = (~pSims1[i] | pSims2[i]);
+ uHash ^= pSims[i] * s_FraigPrimes[i];
+ }
+ else
+ for ( i = iWordStart; i < iWordStop; i++ )
+ {
+ pSims[i] = (pSims1[i] & ~pSims2[i]);
+ uHash ^= pSims[i] * s_FraigPrimes[i];
+ }
+ }
+ else // if ( !fCompl1 && !fCompl2 )
+ {
+ if ( fCompl )
+ for ( i = iWordStart; i < iWordStop; i++ )
+ {
+ pSims[i] = ~(pSims1[i] & pSims2[i]);
+ uHash ^= pSims[i] * s_FraigPrimes[i];
+ }
+ else
+ for ( i = iWordStart; i < iWordStop; i++ )
+ {
+ pSims[i] = (pSims1[i] & pSims2[i]);
+ uHash ^= pSims[i] * s_FraigPrimes[i];
+ }
+ }
+
+ if ( fUseRand )
+ pNode->uHashR ^= uHash;
+ else
+ pNode->uHashD ^= uHash;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fraig/fraigPrime.c b/src/proof/fraig/fraigPrime.c
new file mode 100644
index 00000000..4878738d
--- /dev/null
+++ b/src/proof/fraig/fraigPrime.c
@@ -0,0 +1,113 @@
+/**CFile****************************************************************
+
+ FileName [fraigPrime.c]
+
+ PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+ Synopsis [The table of the first 1000 primes.]
+
+ Author [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - October 1, 2004]
+
+ Revision [$Id: fraigPrime.c,v 1.4 2005/07/08 01:01:32 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fraigInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// The 1,024 smallest prime numbers used to compute the hash value
+// http://www.math.utah.edu/~alfeld/math/primelist.html
+int s_FraigPrimes[FRAIG_MAX_PRIMES] = { 2, 3, 5,
+7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
+101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191,
+193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283,
+293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401,
+409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509,
+521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631,
+641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751,
+757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877,
+881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997,
+1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091,
+1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193,
+1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291,
+1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423,
+1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493,
+1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601,
+1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699,
+1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811,
+1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931,
+1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029,
+2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137,
+2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267,
+2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357,
+2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459,
+2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593,
+2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693,
+2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791,
+2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903,
+2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023,
+3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167,
+3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271,
+3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373,
+3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511,
+3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607,
+3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709,
+3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833,
+3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931,
+3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057,
+4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177,
+4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283,
+4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423,
+4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547,
+4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657,
+4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789,
+4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931,
+4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011,
+5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147,
+5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279,
+5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413,
+5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507,
+5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647,
+5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743,
+5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857,
+5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007,
+6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121,
+6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247,
+6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343,
+6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473,
+6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607,
+6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733,
+6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857,
+6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971,
+6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103,
+7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229,
+7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369,
+7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517,
+7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603,
+7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723,
+7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873,
+7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009,
+8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123,
+8147, 8161 };
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fraig/fraigSat.c b/src/proof/fraig/fraigSat.c
new file mode 100644
index 00000000..6ccd1b86
--- /dev/null
+++ b/src/proof/fraig/fraigSat.c
@@ -0,0 +1,1459 @@
+/**CFile****************************************************************
+
+ FileName [fraigSat.c]
+
+ PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+ Synopsis [Proving functional equivalence using SAT.]
+
+ Author [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - October 1, 2004]
+
+ Revision [$Id: fraigSat.c,v 1.10 2005/07/08 01:01:32 alanmi Exp $]
+
+***********************************************************************/
+
+#include <math.h>
+#include "fraigInt.h"
+#include "src/sat/msat/msatInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Fraig_OrderVariables( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew );
+static void Fraig_SetupAdjacent( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars );
+static void Fraig_SetupAdjacentMark( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars );
+static void Fraig_PrepareCones( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew );
+static void Fraig_PrepareCones_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode );
+
+static void Fraig_SupergateAddClauses( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper );
+static void Fraig_SupergateAddClausesExor( Fraig_Man_t * pMan, Fraig_Node_t * pNode );
+static void Fraig_SupergateAddClausesMux( Fraig_Man_t * pMan, Fraig_Node_t * pNode );
+//static void Fraig_DetectFanoutFreeCone( Fraig_Man_t * pMan, Fraig_Node_t * pNode );
+static void Fraig_DetectFanoutFreeConeMux( Fraig_Man_t * pMan, Fraig_Node_t * pNode );
+static void Fraig_SetActivity( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew );
+
+// The lesson learned seems to be that variable should be in reverse topological order
+// from the output of the miter. The ordering of adjacency lists is very important.
+// The best way seems to be fanins followed by fanouts. Slight changes to this order
+// leads to big degradation in quality.
+
+static int nMuxes;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Checks equivalence of two nodes.]
+
+ Description [Returns 1 iff the nodes are equivalent.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_NodesAreEqual( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit, int nTimeLimit )
+{
+ if ( pNode1 == pNode2 )
+ return 1;
+ if ( pNode1 == Fraig_Not(pNode2) )
+ return 0;
+ return Fraig_NodeIsEquivalent( p, Fraig_Regular(pNode1), Fraig_Regular(pNode2), nBTLimit, nTimeLimit );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Tries to prove the final miter.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_ManProveMiter( Fraig_Man_t * p )
+{
+ Fraig_Node_t * pNode;
+ int i, clk;
+
+ if ( !p->fTryProve )
+ return;
+
+ clk = clock();
+ // consider all outputs of the multi-output miter
+ for ( i = 0; i < p->vOutputs->nSize; i++ )
+ {
+ pNode = Fraig_Regular(p->vOutputs->pArray[i]);
+ // skip already constant nodes
+ if ( pNode == p->pConst1 )
+ continue;
+ // skip nodes that are different according to simulation
+ if ( !Fraig_CompareSimInfo( pNode, p->pConst1, p->nWordsRand, 1 ) )
+ continue;
+ if ( Fraig_NodeIsEquivalent( p, p->pConst1, pNode, -1, p->nSeconds ) )
+ {
+ if ( Fraig_IsComplement(p->vOutputs->pArray[i]) ^ Fraig_NodeComparePhase(p->pConst1, pNode) )
+ p->vOutputs->pArray[i] = Fraig_Not(p->pConst1);
+ else
+ p->vOutputs->pArray[i] = p->pConst1;
+ }
+ }
+ if ( p->fVerboseP )
+ {
+// ABC_PRT( "Final miter proof time", clock() - clk );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the miter is unsat; 0 if sat; -1 if undecided.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_ManCheckMiter( Fraig_Man_t * p )
+{
+ Fraig_Node_t * pNode;
+ int i;
+ ABC_FREE( p->pModel );
+ for ( i = 0; i < p->vOutputs->nSize; i++ )
+ {
+ // get the output node (it can be complemented!)
+ pNode = p->vOutputs->pArray[i];
+ // if the miter is constant 0, the problem is UNSAT
+ if ( pNode == Fraig_Not(p->pConst1) )
+ continue;
+ // consider the special case when the miter is constant 1
+ if ( pNode == p->pConst1 )
+ {
+ // in this case, any counter example will do to distinquish it from constant 0
+ // here we pick the counter example composed of all zeros
+ p->pModel = Fraig_ManAllocCounterExample( p );
+ return 0;
+ }
+ // save the counter example
+ p->pModel = Fraig_ManSaveCounterExample( p, pNode );
+ // if the model is not found, return undecided
+ if ( p->pModel == NULL )
+ return -1;
+ else
+ return 0;
+ }
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if pOld is in the TFI of pNew.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_MarkTfi_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
+{
+ // skip the visited node
+ if ( pNode->TravId == pMan->nTravIds )
+ return 0;
+ pNode->TravId = pMan->nTravIds;
+ // skip the PI node
+ if ( pNode->NumPi >= 0 )
+ return 1;
+ // check the children
+ return Fraig_MarkTfi_rec( pMan, Fraig_Regular(pNode->p1) ) +
+ Fraig_MarkTfi_rec( pMan, Fraig_Regular(pNode->p2) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if pOld is in the TFI of pNew.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_MarkTfi2_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
+{
+ // skip the visited node
+ if ( pNode->TravId == pMan->nTravIds )
+ return 0;
+ // skip the boundary node
+ if ( pNode->TravId == pMan->nTravIds-1 )
+ {
+ pNode->TravId = pMan->nTravIds;
+ return 1;
+ }
+ pNode->TravId = pMan->nTravIds;
+ // skip the PI node
+ if ( pNode->NumPi >= 0 )
+ return 1;
+ // check the children
+ return Fraig_MarkTfi2_rec( pMan, Fraig_Regular(pNode->p1) ) +
+ Fraig_MarkTfi2_rec( pMan, Fraig_Regular(pNode->p2) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if pOld is in the TFI of pNew.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_MarkTfi3_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
+{
+ // skip the visited node
+ if ( pNode->TravId == pMan->nTravIds )
+ return 1;
+ // skip the boundary node
+ if ( pNode->TravId == pMan->nTravIds-1 )
+ {
+ pNode->TravId = pMan->nTravIds;
+ return 1;
+ }
+ pNode->TravId = pMan->nTravIds;
+ // skip the PI node
+ if ( pNode->NumPi >= 0 )
+ return 0;
+ // check the children
+ return Fraig_MarkTfi3_rec( pMan, Fraig_Regular(pNode->p1) ) *
+ Fraig_MarkTfi3_rec( pMan, Fraig_Regular(pNode->p2) );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_VarsStudy( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew )
+{
+ int NumPis, NumCut, fContain;
+
+ // mark the TFI of pNew
+ p->nTravIds++;
+ NumPis = Fraig_MarkTfi_rec( p, pNew );
+ printf( "(%d)(%d,%d):", NumPis, pOld->Level, pNew->Level );
+
+ // check if the old is in the TFI
+ if ( pOld->TravId == p->nTravIds )
+ {
+ printf( "* " );
+ return;
+ }
+
+ // count the boundary of nodes in pOld
+ p->nTravIds++;
+ NumCut = Fraig_MarkTfi2_rec( p, pOld );
+ printf( "%d", NumCut );
+
+ // check if the new is contained in the old's support
+ p->nTravIds++;
+ fContain = Fraig_MarkTfi3_rec( p, pNew );
+ printf( "%c ", fContain? '+':'-' );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Checks whether two nodes are functinally equivalent.]
+
+ Description [The flag (fComp) tells whether the nodes to be checked
+ are in the opposite polarity. The second flag (fSkipZeros) tells whether
+ the checking should be performed if the simulation vectors are zeros.
+ Returns 1 if the nodes are equivalent; 0 othewise.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_NodeIsEquivalent( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit, int nTimeLimit )
+{
+ int RetValue, RetValue1, i, fComp, clk;
+ int fVerbose = 0;
+ int fSwitch = 0;
+
+ // make sure the nodes are not complemented
+ assert( !Fraig_IsComplement(pNew) );
+ assert( !Fraig_IsComplement(pOld) );
+ assert( pNew != pOld );
+
+ // if at least one of the nodes is a failed node, perform adjustments:
+ // if the backtrack limit is small, simply skip this node
+ // if the backtrack limit is > 10, take the quare root of the limit
+ if ( nBTLimit > 0 && (pOld->fFailTfo || pNew->fFailTfo) )
+ {
+ p->nSatFails++;
+// return 0;
+// if ( nBTLimit > 10 )
+// nBTLimit /= 10;
+ if ( nBTLimit <= 10 )
+ return 0;
+ nBTLimit = (int)sqrt((double)nBTLimit);
+// fSwitch = 1;
+ }
+
+ p->nSatCalls++;
+
+ // make sure the solver is allocated and has enough variables
+ if ( p->pSat == NULL )
+ Fraig_ManCreateSolver( p );
+ // make sure the SAT solver has enough variables
+ for ( i = Msat_SolverReadVarNum(p->pSat); i < p->vNodes->nSize; i++ )
+ Msat_SolverAddVar( p->pSat, p->vNodes->pArray[i]->Level );
+
+
+
+/*
+ {
+ Fraig_Node_t * ppNodes[2] = { pOld, pNew };
+ extern void Fraig_MappingShowNodes( Fraig_Man_t * pMan, Fraig_Node_t ** ppRoots, int nRoots, char * pFileName );
+ Fraig_MappingShowNodes( p, ppNodes, 2, "temp_aig" );
+ }
+*/
+
+ nMuxes = 0;
+
+
+ // get the logic cone
+clk = clock();
+// Fraig_VarsStudy( p, pOld, pNew );
+ Fraig_OrderVariables( p, pOld, pNew );
+// Fraig_PrepareCones( p, pOld, pNew );
+p->timeTrav += clock() - clk;
+
+// printf( "The number of MUXes detected = %d (%5.2f %% of logic). ", nMuxes, 300.0*nMuxes/(p->vNodes->nSize - p->vInputs->nSize) );
+// ABC_PRT( "Time", clock() - clk );
+
+if ( fVerbose )
+ printf( "%d(%d) - ", Fraig_CountPis(p,p->vVarsInt), Msat_IntVecReadSize(p->vVarsInt) );
+
+
+ // prepare variable activity
+ Fraig_SetActivity( p, pOld, pNew );
+
+ // get the complemented attribute
+ fComp = Fraig_NodeComparePhase( pOld, pNew );
+//Msat_SolverPrintClauses( p->pSat );
+
+ ////////////////////////////////////////////
+ // prepare the solver to run incrementally on these variables
+//clk = clock();
+ Msat_SolverPrepare( p->pSat, p->vVarsInt );
+//p->time3 += clock() - clk;
+
+
+ // solve under assumptions
+ // A = 1; B = 0 OR A = 1; B = 1
+ Msat_IntVecClear( p->vProj );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 0) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, !fComp) );
+
+//Msat_SolverWriteDimacs( p->pSat, "temp_fraig.cnf" );
+
+ // run the solver
+clk = clock();
+ RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, nTimeLimit );
+p->timeSat += clock() - clk;
+
+ if ( RetValue1 == MSAT_FALSE )
+ {
+//p->time1 += clock() - clk;
+
+if ( fVerbose )
+{
+// printf( "unsat %d ", Msat_SolverReadBackTracks(p->pSat) );
+//ABC_PRT( "time", clock() - clk );
+}
+
+ // add the clause
+ Msat_IntVecClear( p->vProj );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 1) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, fComp) );
+ RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+ assert( RetValue );
+ // continue solving the other implication
+ }
+ else if ( RetValue1 == MSAT_TRUE )
+ {
+//p->time2 += clock() - clk;
+
+if ( fVerbose )
+{
+// printf( "sat %d ", Msat_SolverReadBackTracks(p->pSat) );
+//ABC_PRT( "time", clock() - clk );
+}
+
+ // record the counter example
+ Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew );
+
+// if ( pOld->fFailTfo || pNew->fFailTfo )
+// printf( "*" );
+// printf( "s(%d)", pNew->Level );
+ if ( fSwitch )
+ printf( "s(%d)", pNew->Level );
+ p->nSatCounter++;
+ return 0;
+ }
+ else // if ( RetValue1 == MSAT_UNKNOWN )
+ {
+p->time3 += clock() - clk;
+
+// if ( pOld->fFailTfo || pNew->fFailTfo )
+// printf( "*" );
+// printf( "T(%d)", pNew->Level );
+
+ // mark the node as the failed node
+ if ( pOld != p->pConst1 )
+ pOld->fFailTfo = 1;
+ pNew->fFailTfo = 1;
+// p->nSatFails++;
+ if ( fSwitch )
+ printf( "T(%d)", pNew->Level );
+ p->nSatFailsReal++;
+ return 0;
+ }
+
+ // if the old node was constant 0, we already know the answer
+ if ( pOld == p->pConst1 )
+ return 1;
+
+ ////////////////////////////////////////////
+ // prepare the solver to run incrementally
+//clk = clock();
+ Msat_SolverPrepare( p->pSat, p->vVarsInt );
+//p->time3 += clock() - clk;
+ // solve under assumptions
+ // A = 0; B = 1 OR A = 0; B = 0
+ Msat_IntVecClear( p->vProj );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 1) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, fComp) );
+ // run the solver
+clk = clock();
+ RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, nTimeLimit );
+p->timeSat += clock() - clk;
+
+ if ( RetValue1 == MSAT_FALSE )
+ {
+//p->time1 += clock() - clk;
+
+if ( fVerbose )
+{
+// printf( "unsat %d ", Msat_SolverReadBackTracks(p->pSat) );
+//ABC_PRT( "time", clock() - clk );
+}
+
+ // add the clause
+ Msat_IntVecClear( p->vProj );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 0) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, !fComp) );
+ RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+ assert( RetValue );
+ // continue solving the other implication
+ }
+ else if ( RetValue1 == MSAT_TRUE )
+ {
+//p->time2 += clock() - clk;
+
+if ( fVerbose )
+{
+// printf( "sat %d ", Msat_SolverReadBackTracks(p->pSat) );
+//ABC_PRT( "time", clock() - clk );
+}
+
+ // record the counter example
+ Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew );
+ p->nSatCounter++;
+
+// if ( pOld->fFailTfo || pNew->fFailTfo )
+// printf( "*" );
+// printf( "s(%d)", pNew->Level );
+ if ( fSwitch )
+ printf( "s(%d)", pNew->Level );
+ return 0;
+ }
+ else // if ( RetValue1 == MSAT_UNKNOWN )
+ {
+p->time3 += clock() - clk;
+
+// if ( pOld->fFailTfo || pNew->fFailTfo )
+// printf( "*" );
+// printf( "T(%d)", pNew->Level );
+ if ( fSwitch )
+ printf( "T(%d)", pNew->Level );
+
+ // mark the node as the failed node
+ pOld->fFailTfo = 1;
+ pNew->fFailTfo = 1;
+// p->nSatFails++;
+ p->nSatFailsReal++;
+ return 0;
+ }
+
+ // return SAT proof
+ p->nSatProof++;
+
+// if ( pOld->fFailTfo || pNew->fFailTfo )
+// printf( "*" );
+// printf( "u(%d)", pNew->Level );
+
+ if ( fSwitch )
+ printf( "u(%d)", pNew->Level );
+
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Checks whether pOld => pNew.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_NodeIsImplication( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit )
+{
+ int RetValue, RetValue1, i, fComp, clk;
+ int fVerbose = 0;
+
+ // make sure the nodes are not complemented
+ assert( !Fraig_IsComplement(pNew) );
+ assert( !Fraig_IsComplement(pOld) );
+ assert( pNew != pOld );
+
+ p->nSatCallsImp++;
+
+ // make sure the solver is allocated and has enough variables
+ if ( p->pSat == NULL )
+ Fraig_ManCreateSolver( p );
+ // make sure the SAT solver has enough variables
+ for ( i = Msat_SolverReadVarNum(p->pSat); i < p->vNodes->nSize; i++ )
+ Msat_SolverAddVar( p->pSat, p->vNodes->pArray[i]->Level );
+
+ // get the logic cone
+clk = clock();
+ Fraig_OrderVariables( p, pOld, pNew );
+// Fraig_PrepareCones( p, pOld, pNew );
+p->timeTrav += clock() - clk;
+
+if ( fVerbose )
+ printf( "%d(%d) - ", Fraig_CountPis(p,p->vVarsInt), Msat_IntVecReadSize(p->vVarsInt) );
+
+
+ // get the complemented attribute
+ fComp = Fraig_NodeComparePhase( pOld, pNew );
+//Msat_SolverPrintClauses( p->pSat );
+
+ ////////////////////////////////////////////
+ // prepare the solver to run incrementally on these variables
+//clk = clock();
+ Msat_SolverPrepare( p->pSat, p->vVarsInt );
+//p->time3 += clock() - clk;
+
+ // solve under assumptions
+ // A = 1; B = 0 OR A = 1; B = 1
+ Msat_IntVecClear( p->vProj );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 0) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, !fComp) );
+ // run the solver
+clk = clock();
+ RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, 1000000 );
+p->timeSat += clock() - clk;
+
+ if ( RetValue1 == MSAT_FALSE )
+ {
+//p->time1 += clock() - clk;
+
+if ( fVerbose )
+{
+// printf( "unsat %d ", Msat_SolverReadBackTracks(p->pSat) );
+//ABC_PRT( "time", clock() - clk );
+}
+
+ // add the clause
+ Msat_IntVecClear( p->vProj );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 1) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, fComp) );
+ RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+ assert( RetValue );
+// p->nSatProofImp++;
+ return 1;
+ }
+ else if ( RetValue1 == MSAT_TRUE )
+ {
+//p->time2 += clock() - clk;
+
+if ( fVerbose )
+{
+// printf( "sat %d ", Msat_SolverReadBackTracks(p->pSat) );
+//ABC_PRT( "time", clock() - clk );
+}
+ // record the counter example
+ Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew );
+ p->nSatCounterImp++;
+ return 0;
+ }
+ else // if ( RetValue1 == MSAT_UNKNOWN )
+ {
+p->time3 += clock() - clk;
+ p->nSatFailsImp++;
+ return 0;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the SAT solver to run on the two nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_ManCheckClauseUsingSat( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit )
+{
+ Fraig_Node_t * pNode1R, * pNode2R;
+ int RetValue, RetValue1, i, clk;
+ int fVerbose = 0;
+
+ pNode1R = Fraig_Regular(pNode1);
+ pNode2R = Fraig_Regular(pNode2);
+ assert( pNode1R != pNode2R );
+
+ // make sure the solver is allocated and has enough variables
+ if ( p->pSat == NULL )
+ Fraig_ManCreateSolver( p );
+ // make sure the SAT solver has enough variables
+ for ( i = Msat_SolverReadVarNum(p->pSat); i < p->vNodes->nSize; i++ )
+ Msat_SolverAddVar( p->pSat, p->vNodes->pArray[i]->Level );
+
+ // get the logic cone
+clk = clock();
+ Fraig_OrderVariables( p, pNode1R, pNode2R );
+// Fraig_PrepareCones( p, pNode1R, pNode2R );
+p->timeTrav += clock() - clk;
+
+ ////////////////////////////////////////////
+ // prepare the solver to run incrementally on these variables
+//clk = clock();
+ Msat_SolverPrepare( p->pSat, p->vVarsInt );
+//p->time3 += clock() - clk;
+
+ // solve under assumptions
+ // A = 1; B = 0 OR A = 1; B = 1
+ Msat_IntVecClear( p->vProj );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1R->Num, !Fraig_IsComplement(pNode1)) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2R->Num, !Fraig_IsComplement(pNode2)) );
+ // run the solver
+clk = clock();
+ RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, 1000000 );
+p->timeSat += clock() - clk;
+
+ if ( RetValue1 == MSAT_FALSE )
+ {
+//p->time1 += clock() - clk;
+
+if ( fVerbose )
+{
+// printf( "unsat %d ", Msat_SolverReadBackTracks(p->pSat) );
+//ABC_PRT( "time", clock() - clk );
+}
+
+ // add the clause
+ Msat_IntVecClear( p->vProj );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1R->Num, Fraig_IsComplement(pNode1)) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2R->Num, Fraig_IsComplement(pNode2)) );
+ RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+ assert( RetValue );
+// p->nSatProofImp++;
+ return 1;
+ }
+ else if ( RetValue1 == MSAT_TRUE )
+ {
+//p->time2 += clock() - clk;
+
+if ( fVerbose )
+{
+// printf( "sat %d ", Msat_SolverReadBackTracks(p->pSat) );
+//ABC_PRT( "time", clock() - clk );
+}
+ // record the counter example
+// Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pNode1R, pNode2R );
+ p->nSatCounterImp++;
+ return 0;
+ }
+ else // if ( RetValue1 == MSAT_UNKNOWN )
+ {
+p->time3 += clock() - clk;
+ p->nSatFailsImp++;
+ return 0;
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the SAT solver to run on the two nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_PrepareCones( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew )
+{
+// Msat_IntVec_t * vAdjs;
+// int * pVars, nVars, i, k;
+ int nVarsAlloc;
+
+ assert( pOld != pNew );
+ assert( !Fraig_IsComplement(pOld) );
+ assert( !Fraig_IsComplement(pNew) );
+ // clean the variables
+ nVarsAlloc = Msat_IntVecReadSize(pMan->vVarsUsed);
+ Msat_IntVecFill( pMan->vVarsUsed, nVarsAlloc, 0 );
+ Msat_IntVecClear( pMan->vVarsInt );
+
+ pMan->nTravIds++;
+ Fraig_PrepareCones_rec( pMan, pNew );
+ Fraig_PrepareCones_rec( pMan, pOld );
+
+
+/*
+ nVars = Msat_IntVecReadSize( pMan->vVarsInt );
+ pVars = Msat_IntVecReadArray( pMan->vVarsInt );
+ for ( i = 0; i < nVars; i++ )
+ {
+ // process its connections
+ vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] );
+ printf( "%d=%d { ", pVars[i], Msat_IntVecReadSize(vAdjs) );
+ for ( k = 0; k < Msat_IntVecReadSize(vAdjs); k++ )
+ printf( "%d ", Msat_IntVecReadEntry(vAdjs,k) );
+ printf( "}\n" );
+
+ }
+ i = 0;
+*/
+}
+
+/**Function*************************************************************
+
+ Synopsis [Traverses the cone, collects the numbers and adds the clauses.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_PrepareCones_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
+{
+ Fraig_Node_t * pFanin;
+ Msat_IntVec_t * vAdjs;
+ int fUseMuxes = 1, i;
+ int fItIsTime;
+
+ // skip if the node is aleady visited
+ assert( !Fraig_IsComplement(pNode) );
+ if ( pNode->TravId == pMan->nTravIds )
+ return;
+ pNode->TravId = pMan->nTravIds;
+
+ // collect the node's number (closer to reverse topological order)
+ Msat_IntVecPush( pMan->vVarsInt, pNode->Num );
+ Msat_IntVecWriteEntry( pMan->vVarsUsed, pNode->Num, 1 );
+ if ( !Fraig_NodeIsAnd( pNode ) )
+ return;
+
+ // if the node does not have fanins, create them
+ fItIsTime = 0;
+ if ( pNode->vFanins == NULL )
+ {
+ fItIsTime = 1;
+ // create the fanins of the supergate
+ assert( pNode->fClauses == 0 );
+ if ( fUseMuxes && Fraig_NodeIsMuxType(pNode) )
+ {
+ pNode->vFanins = Fraig_NodeVecAlloc( 4 );
+ Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p1) );
+ Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p2) );
+ Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p1) );
+ Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p2) );
+ Fraig_SupergateAddClausesMux( pMan, pNode );
+ }
+ else
+ {
+ pNode->vFanins = Fraig_CollectSupergate( pNode, fUseMuxes );
+ Fraig_SupergateAddClauses( pMan, pNode, pNode->vFanins );
+ }
+ assert( pNode->vFanins->nSize > 1 );
+ pNode->fClauses = 1;
+ pMan->nVarsClauses++;
+
+ // add fanins
+ vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pNode->Num );
+ assert( Msat_IntVecReadSize( vAdjs ) == 0 );
+ for ( i = 0; i < pNode->vFanins->nSize; i++ )
+ {
+ pFanin = Fraig_Regular(pNode->vFanins->pArray[i]);
+ Msat_IntVecPush( vAdjs, pFanin->Num );
+ }
+ }
+
+ // recursively visit the fanins
+ for ( i = 0; i < pNode->vFanins->nSize; i++ )
+ Fraig_PrepareCones_rec( pMan, Fraig_Regular(pNode->vFanins->pArray[i]) );
+
+ if ( fItIsTime )
+ {
+ // recursively visit the fanins
+ for ( i = 0; i < pNode->vFanins->nSize; i++ )
+ {
+ pFanin = Fraig_Regular(pNode->vFanins->pArray[i]);
+ vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pFanin->Num );
+ Msat_IntVecPush( vAdjs, pNode->Num );
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collect variables using their proximity from the nodes.]
+
+ Description [This procedure creates a variable order based on collecting
+ first the nodes that are the closest to the given two target nodes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_OrderVariables( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew )
+{
+ Fraig_Node_t * pNode, * pFanin;
+ int i, k, Number, fUseMuxes = 1;
+ int nVarsAlloc;
+
+ assert( pOld != pNew );
+ assert( !Fraig_IsComplement(pOld) );
+ assert( !Fraig_IsComplement(pNew) );
+
+ pMan->nTravIds++;
+
+ // clean the variables
+ nVarsAlloc = Msat_IntVecReadSize(pMan->vVarsUsed);
+ Msat_IntVecFill( pMan->vVarsUsed, nVarsAlloc, 0 );
+ Msat_IntVecClear( pMan->vVarsInt );
+
+ // add the first node
+ Msat_IntVecPush( pMan->vVarsInt, pOld->Num );
+ Msat_IntVecWriteEntry( pMan->vVarsUsed, pOld->Num, 1 );
+ pOld->TravId = pMan->nTravIds;
+
+ // add the second node
+ Msat_IntVecPush( pMan->vVarsInt, pNew->Num );
+ Msat_IntVecWriteEntry( pMan->vVarsUsed, pNew->Num, 1 );
+ pNew->TravId = pMan->nTravIds;
+
+ // create the variable order
+ for ( i = 0; i < Msat_IntVecReadSize(pMan->vVarsInt); i++ )
+ {
+ // get the new node on the frontier
+ Number = Msat_IntVecReadEntry(pMan->vVarsInt, i);
+ pNode = pMan->vNodes->pArray[Number];
+ if ( !Fraig_NodeIsAnd(pNode) )
+ continue;
+
+ // if the node does not have fanins, create them
+ if ( pNode->vFanins == NULL )
+ {
+ // create the fanins of the supergate
+ assert( pNode->fClauses == 0 );
+ // detecting a fanout-free cone (experiment only)
+// Fraig_DetectFanoutFreeCone( pMan, pNode );
+
+ if ( fUseMuxes && Fraig_NodeIsMuxType(pNode) )
+ {
+ pNode->vFanins = Fraig_NodeVecAlloc( 4 );
+ Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p1) );
+ Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p2) );
+ Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p1) );
+ Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p2) );
+ Fraig_SupergateAddClausesMux( pMan, pNode );
+// Fraig_DetectFanoutFreeConeMux( pMan, pNode );
+
+ nMuxes++;
+ }
+ else
+ {
+ pNode->vFanins = Fraig_CollectSupergate( pNode, fUseMuxes );
+ Fraig_SupergateAddClauses( pMan, pNode, pNode->vFanins );
+ }
+ assert( pNode->vFanins->nSize > 1 );
+ pNode->fClauses = 1;
+ pMan->nVarsClauses++;
+
+ pNode->fMark2 = 1; // goes together with Fraig_SetupAdjacentMark()
+ }
+
+ // explore the implication fanins of pNode
+ for ( k = 0; k < pNode->vFanins->nSize; k++ )
+ {
+ pFanin = Fraig_Regular(pNode->vFanins->pArray[k]);
+ if ( pFanin->TravId == pMan->nTravIds ) // already collected
+ continue;
+ // collect and mark
+ Msat_IntVecPush( pMan->vVarsInt, pFanin->Num );
+ Msat_IntVecWriteEntry( pMan->vVarsUsed, pFanin->Num, 1 );
+ pFanin->TravId = pMan->nTravIds;
+ }
+ }
+
+ // set up the adjacent variable information
+// Fraig_SetupAdjacent( pMan, pMan->vVarsInt );
+ Fraig_SetupAdjacentMark( pMan, pMan->vVarsInt );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Set up the adjacent variable information.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_SetupAdjacent( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars )
+{
+ Fraig_Node_t * pNode, * pFanin;
+ Msat_IntVec_t * vAdjs;
+ int * pVars, nVars, i, k;
+
+ // clean the adjacents for the variables
+ nVars = Msat_IntVecReadSize( vConeVars );
+ pVars = Msat_IntVecReadArray( vConeVars );
+ for ( i = 0; i < nVars; i++ )
+ {
+ // process its connections
+ vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] );
+ Msat_IntVecClear( vAdjs );
+
+ pNode = pMan->vNodes->pArray[pVars[i]];
+ if ( !Fraig_NodeIsAnd(pNode) )
+ continue;
+
+ // add fanins
+ vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] );
+ for ( k = 0; k < pNode->vFanins->nSize; k++ )
+// for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- )
+ {
+ pFanin = Fraig_Regular(pNode->vFanins->pArray[k]);
+ Msat_IntVecPush( vAdjs, pFanin->Num );
+// Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num );
+ }
+ }
+ // add the fanouts
+ for ( i = 0; i < nVars; i++ )
+ {
+ pNode = pMan->vNodes->pArray[pVars[i]];
+ if ( !Fraig_NodeIsAnd(pNode) )
+ continue;
+
+ // add the edges
+ for ( k = 0; k < pNode->vFanins->nSize; k++ )
+// for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- )
+ {
+ pFanin = Fraig_Regular(pNode->vFanins->pArray[k]);
+ vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pFanin->Num );
+ Msat_IntVecPush( vAdjs, pNode->Num );
+// Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num );
+ }
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Set up the adjacent variable information.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_SetupAdjacentMark( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars )
+{
+ Fraig_Node_t * pNode, * pFanin;
+ Msat_IntVec_t * vAdjs;
+ int * pVars, nVars, i, k;
+
+ // clean the adjacents for the variables
+ nVars = Msat_IntVecReadSize( vConeVars );
+ pVars = Msat_IntVecReadArray( vConeVars );
+ for ( i = 0; i < nVars; i++ )
+ {
+ pNode = pMan->vNodes->pArray[pVars[i]];
+ if ( pNode->fMark2 == 0 )
+ continue;
+// pNode->fMark2 = 0;
+
+ // process its connections
+// vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] );
+// Msat_IntVecClear( vAdjs );
+
+ if ( !Fraig_NodeIsAnd(pNode) )
+ continue;
+
+ // add fanins
+ vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] );
+ for ( k = 0; k < pNode->vFanins->nSize; k++ )
+// for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- )
+ {
+ pFanin = Fraig_Regular(pNode->vFanins->pArray[k]);
+ Msat_IntVecPush( vAdjs, pFanin->Num );
+// Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num );
+ }
+ }
+ // add the fanouts
+ for ( i = 0; i < nVars; i++ )
+ {
+ pNode = pMan->vNodes->pArray[pVars[i]];
+ if ( pNode->fMark2 == 0 )
+ continue;
+ pNode->fMark2 = 0;
+
+ if ( !Fraig_NodeIsAnd(pNode) )
+ continue;
+
+ // add the edges
+ for ( k = 0; k < pNode->vFanins->nSize; k++ )
+// for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- )
+ {
+ pFanin = Fraig_Regular(pNode->vFanins->pArray[k]);
+ vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pFanin->Num );
+ Msat_IntVecPush( vAdjs, pNode->Num );
+// Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num );
+ }
+ }
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Adds clauses to the solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_SupergateAddClauses( Fraig_Man_t * p, Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper )
+{
+ int fComp1, RetValue, nVars, Var, Var1, i;
+
+ assert( Fraig_NodeIsAnd( pNode ) );
+ nVars = Msat_SolverReadVarNum(p->pSat);
+
+ Var = pNode->Num;
+ assert( Var < nVars );
+ for ( i = 0; i < vSuper->nSize; i++ )
+ {
+ // get the predecessor nodes
+ // get the complemented attributes of the nodes
+ fComp1 = Fraig_IsComplement(vSuper->pArray[i]);
+ // determine the variable numbers
+ Var1 = Fraig_Regular(vSuper->pArray[i])->Num;
+ // check that the variables are in the SAT manager
+ assert( Var1 < nVars );
+
+ // suppose the AND-gate is A * B = C
+ // add !A => !C or A + !C
+ // fprintf( pFile, "%d %d 0%c", Var1, -Var, 10 );
+ Msat_IntVecClear( p->vProj );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var1, fComp1) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var, 1) );
+ RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+ assert( RetValue );
+ }
+
+ // add A & B => C or !A + !B + C
+// fprintf( pFile, "%d %d %d 0%c", -Var1, -Var2, Var, 10 );
+ Msat_IntVecClear( p->vProj );
+ for ( i = 0; i < vSuper->nSize; i++ )
+ {
+ // get the predecessor nodes
+ // get the complemented attributes of the nodes
+ fComp1 = Fraig_IsComplement(vSuper->pArray[i]);
+ // determine the variable numbers
+ Var1 = Fraig_Regular(vSuper->pArray[i])->Num;
+
+ // add this variable to the array
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var1, !fComp1) );
+ }
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var, 0) );
+ RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+ assert( RetValue );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds clauses to the solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_SupergateAddClausesExor( Fraig_Man_t * p, Fraig_Node_t * pNode )
+{
+ Fraig_Node_t * pNode1, * pNode2;
+ int fComp, RetValue;
+
+ assert( !Fraig_IsComplement( pNode ) );
+ assert( Fraig_NodeIsExorType( pNode ) );
+ // get nodes
+ pNode1 = Fraig_Regular(Fraig_Regular(pNode->p1)->p1);
+ pNode2 = Fraig_Regular(Fraig_Regular(pNode->p1)->p2);
+ // get the complemented attribute of the EXOR/NEXOR gate
+ fComp = Fraig_NodeIsExor( pNode ); // 1 if EXOR, 0 if NEXOR
+
+ // create four clauses
+ Msat_IntVecClear( p->vProj );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, fComp) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num, fComp) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num, fComp) );
+ RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+ assert( RetValue );
+ Msat_IntVecClear( p->vProj );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, fComp) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num, !fComp) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num, !fComp) );
+ RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+ assert( RetValue );
+ Msat_IntVecClear( p->vProj );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, !fComp) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num, fComp) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num, !fComp) );
+ RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+ assert( RetValue );
+ Msat_IntVecClear( p->vProj );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, !fComp) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num, !fComp) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num, fComp) );
+ RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+ assert( RetValue );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds clauses to the solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_SupergateAddClausesMux( Fraig_Man_t * p, Fraig_Node_t * pNode )
+{
+ Fraig_Node_t * pNodeI, * pNodeT, * pNodeE;
+ int RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE;
+
+ assert( !Fraig_IsComplement( pNode ) );
+ assert( Fraig_NodeIsMuxType( pNode ) );
+ // get nodes (I = if, T = then, E = else)
+ pNodeI = Fraig_NodeRecognizeMux( pNode, &pNodeT, &pNodeE );
+ // get the variable numbers
+ VarF = pNode->Num;
+ VarI = pNodeI->Num;
+ VarT = Fraig_Regular(pNodeT)->Num;
+ VarE = Fraig_Regular(pNodeE)->Num;
+ // get the complementation flags
+ fCompT = Fraig_IsComplement(pNodeT);
+ fCompE = Fraig_IsComplement(pNodeE);
+
+ // f = ITE(i, t, e)
+
+ // i' + t' + f
+ // i' + t + f'
+ // i + e' + f
+ // i + e + f'
+
+ // create four clauses
+ Msat_IntVecClear( p->vProj );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI, 1) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT, 1^fCompT) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 0) );
+ RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+ assert( RetValue );
+ Msat_IntVecClear( p->vProj );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI, 1) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT, 0^fCompT) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 1) );
+ RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+ assert( RetValue );
+ Msat_IntVecClear( p->vProj );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI, 0) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE, 1^fCompE) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 0) );
+ RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+ assert( RetValue );
+ Msat_IntVecClear( p->vProj );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI, 0) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE, 0^fCompE) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 1) );
+ RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+ assert( RetValue );
+
+ // two additional clauses
+ // t' & e' -> f'
+ // t & e -> f
+
+ // t + e + f'
+ // t' + e' + f
+
+ if ( VarT == VarE )
+ {
+// assert( fCompT == !fCompE );
+ return;
+ }
+
+ Msat_IntVecClear( p->vProj );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT, 0^fCompT) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE, 0^fCompE) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 1) );
+ RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+ assert( RetValue );
+ Msat_IntVecClear( p->vProj );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT, 1^fCompT) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE, 1^fCompE) );
+ Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 0) );
+ RetValue = Msat_SolverAddClause( p->pSat, p->vProj );
+ assert( RetValue );
+
+}
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_DetectFanoutFreeCone_rec( Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper, Fraig_NodeVec_t * vInside, int fFirst )
+{
+ // make the pointer regular
+ pNode = Fraig_Regular(pNode);
+ // if the new node is complemented or a PI, another gate begins
+ if ( (!fFirst && pNode->nRefs > 1) || Fraig_NodeIsVar(pNode) )
+ {
+ Fraig_NodeVecPushUnique( vSuper, pNode );
+ return;
+ }
+ // go through the branches
+ Fraig_DetectFanoutFreeCone_rec( pNode->p1, vSuper, vInside, 0 );
+ Fraig_DetectFanoutFreeCone_rec( pNode->p2, vSuper, vInside, 0 );
+ // add the node
+ Fraig_NodeVecPushUnique( vInside, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+/*
+void Fraig_DetectFanoutFreeCone( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
+{
+ Fraig_NodeVec_t * vFanins;
+ Fraig_NodeVec_t * vInside;
+ int nCubes;
+ extern int Fraig_CutSopCountCubes( Fraig_Man_t * pMan, Fraig_NodeVec_t * vFanins, Fraig_NodeVec_t * vInside );
+
+ vFanins = Fraig_NodeVecAlloc( 8 );
+ vInside = Fraig_NodeVecAlloc( 8 );
+
+ Fraig_DetectFanoutFreeCone_rec( pNode, vFanins, vInside, 1 );
+ assert( vInside->pArray[vInside->nSize-1] == pNode );
+
+ nCubes = Fraig_CutSopCountCubes( pMan, vFanins, vInside );
+
+printf( "%d(%d)", vFanins->nSize, nCubes );
+ Fraig_NodeVecFree( vFanins );
+ Fraig_NodeVecFree( vInside );
+}
+*/
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_DetectFanoutFreeConeMux_rec( Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper, Fraig_NodeVec_t * vInside, int fFirst )
+{
+ // make the pointer regular
+ pNode = Fraig_Regular(pNode);
+ // if the new node is complemented or a PI, another gate begins
+ if ( (!fFirst && pNode->nRefs > 1) || Fraig_NodeIsVar(pNode) || !Fraig_NodeIsMuxType(pNode) )
+ {
+ Fraig_NodeVecPushUnique( vSuper, pNode );
+ return;
+ }
+ // go through the branches
+ Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p1)->p1, vSuper, vInside, 0 );
+ Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p1)->p2, vSuper, vInside, 0 );
+ Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p2)->p1, vSuper, vInside, 0 );
+ Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p2)->p2, vSuper, vInside, 0 );
+ // add the node
+ Fraig_NodeVecPushUnique( vInside, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_DetectFanoutFreeConeMux( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
+{
+ Fraig_NodeVec_t * vFanins;
+ Fraig_NodeVec_t * vInside;
+ int nCubes;
+ extern int Fraig_CutSopCountCubes( Fraig_Man_t * pMan, Fraig_NodeVec_t * vFanins, Fraig_NodeVec_t * vInside );
+
+ vFanins = Fraig_NodeVecAlloc( 8 );
+ vInside = Fraig_NodeVecAlloc( 8 );
+
+ Fraig_DetectFanoutFreeConeMux_rec( pNode, vFanins, vInside, 1 );
+ assert( vInside->pArray[vInside->nSize-1] == pNode );
+
+// nCubes = Fraig_CutSopCountCubes( pMan, vFanins, vInside );
+ nCubes = 0;
+
+printf( "%d(%d)", vFanins->nSize, nCubes );
+ Fraig_NodeVecFree( vFanins );
+ Fraig_NodeVecFree( vInside );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Collect variables using their proximity from the nodes.]
+
+ Description [This procedure creates a variable order based on collecting
+ first the nodes that are the closest to the given two target nodes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_SetActivity( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew )
+{
+ Fraig_Node_t * pNode;
+ int i, Number, MaxLevel;
+ float * pFactors = Msat_SolverReadFactors(pMan->pSat);
+ if ( pFactors == NULL )
+ return;
+ MaxLevel = Abc_MaxInt( pOld->Level, pNew->Level );
+ // create the variable order
+ for ( i = 0; i < Msat_IntVecReadSize(pMan->vVarsInt); i++ )
+ {
+ // get the new node on the frontier
+ Number = Msat_IntVecReadEntry(pMan->vVarsInt, i);
+ pNode = pMan->vNodes->pArray[Number];
+ pFactors[pNode->Num] = (float)pow( 0.97, MaxLevel - pNode->Level );
+// if ( pNode->Num % 50 == 0 )
+// printf( "(%d) %.2f ", MaxLevel - pNode->Level, pFactors[pNode->Num] );
+ }
+// printf( "\n" );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fraig/fraigTable.c b/src/proof/fraig/fraigTable.c
new file mode 100644
index 00000000..6611e4fa
--- /dev/null
+++ b/src/proof/fraig/fraigTable.c
@@ -0,0 +1,662 @@
+/**CFile****************************************************************
+
+ FileName [fraigTable.c]
+
+ PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+ Synopsis [Structural and functional hash tables.]
+
+ Author [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - October 1, 2004]
+
+ Revision [$Id: fraigTable.c,v 1.7 2005/07/08 01:01:34 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fraigInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static void Fraig_TableResizeS( Fraig_HashTable_t * p );
+static void Fraig_TableResizeF( Fraig_HashTable_t * p, int fUseSimR );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates the hash table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_HashTable_t * Fraig_HashTableCreate( int nSize )
+{
+ Fraig_HashTable_t * p;
+ // allocate the table
+ p = ABC_ALLOC( Fraig_HashTable_t, 1 );
+ memset( p, 0, sizeof(Fraig_HashTable_t) );
+ // allocate and clean the bins
+ p->nBins = Abc_PrimeCudd(nSize);
+ p->pBins = ABC_ALLOC( Fraig_Node_t *, p->nBins );
+ memset( p->pBins, 0, sizeof(Fraig_Node_t *) * p->nBins );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates the supergate hash table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_HashTableFree( Fraig_HashTable_t * p )
+{
+ ABC_FREE( p->pBins );
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Looks up an entry in the structural hash table.]
+
+ Description [If the entry with the same children does not exists,
+ creates it, inserts it into the table, and returns 0. If the entry
+ with the same children exists, finds it, and return 1. In both cases,
+ the new/old entry is returned in ppNodeRes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_HashTableLookupS( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2, Fraig_Node_t ** ppNodeRes )
+{
+ Fraig_HashTable_t * p = pMan->pTableS;
+ Fraig_Node_t * pEnt;
+ unsigned Key;
+
+ // order the arguments
+ if ( Fraig_Regular(p1)->Num > Fraig_Regular(p2)->Num )
+ pEnt = p1, p1 = p2, p2 = pEnt;
+
+ Key = Fraig_HashKey2( p1, p2, p->nBins );
+ Fraig_TableBinForEachEntryS( p->pBins[Key], pEnt )
+ if ( pEnt->p1 == p1 && pEnt->p2 == p2 )
+ {
+ *ppNodeRes = pEnt;
+ return 1;
+ }
+ // check if it is a good time for table resizing
+ if ( p->nEntries >= 2 * p->nBins )
+ {
+ Fraig_TableResizeS( p );
+ Key = Fraig_HashKey2( p1, p2, p->nBins );
+ }
+ // create the new node
+ pEnt = Fraig_NodeCreate( pMan, p1, p2 );
+ // add the node to the corresponding linked list in the table
+ pEnt->pNextS = p->pBins[Key];
+ p->pBins[Key] = pEnt;
+ *ppNodeRes = pEnt;
+ p->nEntries++;
+ return 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Insert the entry in the functional hash table.]
+
+ Description [If the entry with the same key exists, return it right away.
+ If the entry with the same key does not exists, inserts it and returns NULL. ]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_HashTableLookupF( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
+{
+ Fraig_HashTable_t * p = pMan->pTableF;
+ Fraig_Node_t * pEnt, * pEntD;
+ unsigned Key;
+
+ // go through the hash table entries
+ Key = pNode->uHashR % p->nBins;
+ Fraig_TableBinForEachEntryF( p->pBins[Key], pEnt )
+ {
+ // if their simulation info differs, skip
+ if ( !Fraig_CompareSimInfo( pNode, pEnt, pMan->nWordsRand, 1 ) )
+ continue;
+ // equivalent up to the complement
+ Fraig_TableBinForEachEntryD( pEnt, pEntD )
+ {
+ // if their simulation info differs, skip
+ if ( !Fraig_CompareSimInfo( pNode, pEntD, pMan->iWordStart, 0 ) )
+ continue;
+ // found a simulation-equivalent node
+ return pEntD;
+ }
+ // did not find a simulation equivalent node
+ // add the node to the corresponding linked list
+ pNode->pNextD = pEnt->pNextD;
+ pEnt->pNextD = pNode;
+ // return NULL, because there is no functional equivalence in this case
+ return NULL;
+ }
+
+ // check if it is a good time for table resizing
+ if ( p->nEntries >= 2 * p->nBins )
+ {
+ Fraig_TableResizeF( p, 1 );
+ Key = pNode->uHashR % p->nBins;
+ }
+
+ // add the node to the corresponding linked list in the table
+ pNode->pNextF = p->pBins[Key];
+ p->pBins[Key] = pNode;
+ p->nEntries++;
+ // return NULL, because there is no functional equivalence in this case
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Insert the entry in the functional hash table.]
+
+ Description [If the entry with the same key exists, return it right away.
+ If the entry with the same key does not exists, inserts it and returns NULL. ]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_HashTableLookupF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
+{
+ Fraig_HashTable_t * p = pMan->pTableF0;
+ Fraig_Node_t * pEnt;
+ unsigned Key;
+
+ // go through the hash table entries
+ Key = pNode->uHashD % p->nBins;
+ Fraig_TableBinForEachEntryF( p->pBins[Key], pEnt )
+ {
+ // if their simulation info differs, skip
+ if ( !Fraig_CompareSimInfo( pNode, pEnt, pMan->iWordStart, 0 ) )
+ continue;
+ // found a simulation-equivalent node
+ return pEnt;
+ }
+
+ // check if it is a good time for table resizing
+ if ( p->nEntries >= 2 * p->nBins )
+ {
+ Fraig_TableResizeF( p, 0 );
+ Key = pNode->uHashD % p->nBins;
+ }
+
+ // add the node to the corresponding linked list in the table
+ pNode->pNextF = p->pBins[Key];
+ p->pBins[Key] = pNode;
+ p->nEntries++;
+ // return NULL, because there is no functional equivalence in this case
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Insert the entry in the functional hash table.]
+
+ Description [Unconditionally add the node to the corresponding
+ linked list in the table.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_HashTableInsertF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
+{
+ Fraig_HashTable_t * p = pMan->pTableF0;
+ unsigned Key = pNode->uHashD % p->nBins;
+
+ pNode->pNextF = p->pBins[Key];
+ p->pBins[Key] = pNode;
+ p->nEntries++;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Resizes the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_TableResizeS( Fraig_HashTable_t * p )
+{
+ Fraig_Node_t ** pBinsNew;
+ Fraig_Node_t * pEnt, * pEnt2;
+ int nBinsNew, Counter, i, clk;
+ unsigned Key;
+
+clk = clock();
+ // get the new table size
+ nBinsNew = Abc_PrimeCudd(2 * p->nBins);
+ // allocate a new array
+ pBinsNew = ABC_ALLOC( Fraig_Node_t *, nBinsNew );
+ memset( pBinsNew, 0, sizeof(Fraig_Node_t *) * nBinsNew );
+ // rehash the entries from the old table
+ Counter = 0;
+ for ( i = 0; i < p->nBins; i++ )
+ Fraig_TableBinForEachEntrySafeS( p->pBins[i], pEnt, pEnt2 )
+ {
+ Key = Fraig_HashKey2( pEnt->p1, pEnt->p2, nBinsNew );
+ pEnt->pNextS = pBinsNew[Key];
+ pBinsNew[Key] = pEnt;
+ Counter++;
+ }
+ assert( Counter == p->nEntries );
+// printf( "Increasing the structural table size from %6d to %6d. ", p->nBins, nBinsNew );
+// ABC_PRT( "Time", clock() - clk );
+ // replace the table and the parameters
+ ABC_FREE( p->pBins );
+ p->pBins = pBinsNew;
+ p->nBins = nBinsNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resizes the table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_TableResizeF( Fraig_HashTable_t * p, int fUseSimR )
+{
+ Fraig_Node_t ** pBinsNew;
+ Fraig_Node_t * pEnt, * pEnt2;
+ int nBinsNew, Counter, i, clk;
+ unsigned Key;
+
+clk = clock();
+ // get the new table size
+ nBinsNew = Abc_PrimeCudd(2 * p->nBins);
+ // allocate a new array
+ pBinsNew = ABC_ALLOC( Fraig_Node_t *, nBinsNew );
+ memset( pBinsNew, 0, sizeof(Fraig_Node_t *) * nBinsNew );
+ // rehash the entries from the old table
+ Counter = 0;
+ for ( i = 0; i < p->nBins; i++ )
+ Fraig_TableBinForEachEntrySafeF( p->pBins[i], pEnt, pEnt2 )
+ {
+ if ( fUseSimR )
+ Key = pEnt->uHashR % nBinsNew;
+ else
+ Key = pEnt->uHashD % nBinsNew;
+ pEnt->pNextF = pBinsNew[Key];
+ pBinsNew[Key] = pEnt;
+ Counter++;
+ }
+ assert( Counter == p->nEntries );
+// printf( "Increasing the functional table size from %6d to %6d. ", p->nBins, nBinsNew );
+// ABC_PRT( "Time", clock() - clk );
+ // replace the table and the parameters
+ ABC_FREE( p->pBins );
+ p->pBins = pBinsNew;
+ p->nBins = nBinsNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Compares two pieces of simulation info.]
+
+ Description [Returns 1 if they are equal.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_CompareSimInfo( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand )
+{
+ int i;
+ assert( !Fraig_IsComplement(pNode1) );
+ assert( !Fraig_IsComplement(pNode2) );
+ if ( fUseRand )
+ {
+ // if their signatures differ, skip
+ if ( pNode1->uHashR != pNode2->uHashR )
+ return 0;
+ // check the simulation info
+ for ( i = 0; i < iWordLast; i++ )
+ if ( pNode1->puSimR[i] != pNode2->puSimR[i] )
+ return 0;
+ }
+ else
+ {
+ // if their signatures differ, skip
+ if ( pNode1->uHashD != pNode2->uHashD )
+ return 0;
+ // check the simulation info
+ for ( i = 0; i < iWordLast; i++ )
+ if ( pNode1->puSimD[i] != pNode2->puSimD[i] )
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find the number of the different pattern.]
+
+ Description [Returns -1 if there is no such pattern]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_FindFirstDiff( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int fCompl, int iWordLast, int fUseRand )
+{
+ int i, v;
+ assert( !Fraig_IsComplement(pNode1) );
+ assert( !Fraig_IsComplement(pNode2) );
+ // take into account possible internal complementation
+ fCompl ^= pNode1->fInv;
+ fCompl ^= pNode2->fInv;
+ // find the pattern
+ if ( fCompl )
+ {
+ if ( fUseRand )
+ {
+ for ( i = 0; i < iWordLast; i++ )
+ if ( pNode1->puSimR[i] != ~pNode2->puSimR[i] )
+ for ( v = 0; v < 32; v++ )
+ if ( (pNode1->puSimR[i] ^ ~pNode2->puSimR[i]) & (1 << v) )
+ return i * 32 + v;
+ }
+ else
+ {
+ for ( i = 0; i < iWordLast; i++ )
+ if ( pNode1->puSimD[i] != ~pNode2->puSimD[i] )
+ for ( v = 0; v < 32; v++ )
+ if ( (pNode1->puSimD[i] ^ ~pNode2->puSimD[i]) & (1 << v) )
+ return i * 32 + v;
+ }
+ }
+ else
+ {
+ if ( fUseRand )
+ {
+ for ( i = 0; i < iWordLast; i++ )
+ if ( pNode1->puSimR[i] != pNode2->puSimR[i] )
+ for ( v = 0; v < 32; v++ )
+ if ( (pNode1->puSimR[i] ^ pNode2->puSimR[i]) & (1 << v) )
+ return i * 32 + v;
+ }
+ else
+ {
+ for ( i = 0; i < iWordLast; i++ )
+ if ( pNode1->puSimD[i] != pNode2->puSimD[i] )
+ for ( v = 0; v < 32; v++ )
+ if ( (pNode1->puSimD[i] ^ pNode2->puSimD[i]) & (1 << v) )
+ return i * 32 + v;
+ }
+ }
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares two pieces of simulation info.]
+
+ Description [Returns 1 if they are equal.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_CompareSimInfoUnderMask( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask )
+{
+ unsigned * pSims1, * pSims2;
+ int i;
+ assert( !Fraig_IsComplement(pNode1) );
+ assert( !Fraig_IsComplement(pNode2) );
+ // get hold of simulation info
+ pSims1 = fUseRand? pNode1->puSimR : pNode1->puSimD;
+ pSims2 = fUseRand? pNode2->puSimR : pNode2->puSimD;
+ // check the simulation info
+ for ( i = 0; i < iWordLast; i++ )
+ if ( (pSims1[i] & puMask[i]) != (pSims2[i] & puMask[i]) )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares two pieces of simulation info.]
+
+ Description [Returns 1 if they are equal.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_CollectXors( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask )
+{
+ unsigned * pSims1, * pSims2;
+ int i;
+ assert( !Fraig_IsComplement(pNode1) );
+ assert( !Fraig_IsComplement(pNode2) );
+ // get hold of simulation info
+ pSims1 = fUseRand? pNode1->puSimR : pNode1->puSimD;
+ pSims2 = fUseRand? pNode2->puSimR : pNode2->puSimD;
+ // check the simulation info
+ for ( i = 0; i < iWordLast; i++ )
+ puMask[i] = ( pSims1[i] ^ pSims2[i] );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints stats of the structural table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_TablePrintStatsS( Fraig_Man_t * pMan )
+{
+ Fraig_HashTable_t * pT = pMan->pTableS;
+ Fraig_Node_t * pNode;
+ int i, Counter;
+
+ printf( "Structural table. Table size = %d. Number of entries = %d.\n", pT->nBins, pT->nEntries );
+ for ( i = 0; i < pT->nBins; i++ )
+ {
+ Counter = 0;
+ Fraig_TableBinForEachEntryS( pT->pBins[i], pNode )
+ Counter++;
+ if ( Counter > 1 )
+ {
+ printf( "%d ", Counter );
+ if ( Counter > 50 )
+ printf( "{%d} ", i );
+ }
+ }
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints stats of the structural table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_TablePrintStatsF( Fraig_Man_t * pMan )
+{
+ Fraig_HashTable_t * pT = pMan->pTableF;
+ Fraig_Node_t * pNode;
+ int i, Counter;
+
+ printf( "Functional table. Table size = %d. Number of entries = %d.\n", pT->nBins, pT->nEntries );
+ for ( i = 0; i < pT->nBins; i++ )
+ {
+ Counter = 0;
+ Fraig_TableBinForEachEntryF( pT->pBins[i], pNode )
+ Counter++;
+ if ( Counter > 1 )
+ printf( "{%d} ", Counter );
+ }
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints stats of the structural table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_TablePrintStatsF0( Fraig_Man_t * pMan )
+{
+ Fraig_HashTable_t * pT = pMan->pTableF0;
+ Fraig_Node_t * pNode;
+ int i, Counter;
+
+ printf( "Zero-node table. Table size = %d. Number of entries = %d.\n", pT->nBins, pT->nEntries );
+ for ( i = 0; i < pT->nBins; i++ )
+ {
+ Counter = 0;
+ Fraig_TableBinForEachEntryF( pT->pBins[i], pNode )
+ Counter++;
+ if ( Counter == 0 )
+ continue;
+/*
+ printf( "\nBin = %4d : Number of entries = %4d\n", i, Counter );
+ Fraig_TableBinForEachEntryF( pT->pBins[i], pNode )
+ printf( "Node %5d. Hash = %10d.\n", pNode->Num, pNode->uHashD );
+*/
+ }
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Rehashes the table after the simulation info has changed.]
+
+ Description [Assumes that the hash values have been updated after performing
+ additional simulation. Rehashes the table using the new hash values.
+ Uses pNextF to link the entries in the bins. Uses pNextD to link the entries
+ with identical hash values. Returns 1 if the identical entries have been found.
+ Note that identical hash values may mean that the simulation data is different.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_TableRehashF0( Fraig_Man_t * pMan, int fLinkEquiv )
+{
+ Fraig_HashTable_t * pT = pMan->pTableF0;
+ Fraig_Node_t ** pBinsNew;
+ Fraig_Node_t * pEntF, * pEntF2, * pEnt, * pEntD2, * pEntN;
+ int ReturnValue, Counter, i;
+ unsigned Key;
+
+ // allocate a new array of bins
+ pBinsNew = ABC_ALLOC( Fraig_Node_t *, pT->nBins );
+ memset( pBinsNew, 0, sizeof(Fraig_Node_t *) * pT->nBins );
+
+ // rehash the entries in the table
+ // go through all the nodes in the F-lists (and possible in D-lists, if used)
+ Counter = 0;
+ ReturnValue = 0;
+ for ( i = 0; i < pT->nBins; i++ )
+ Fraig_TableBinForEachEntrySafeF( pT->pBins[i], pEntF, pEntF2 )
+ Fraig_TableBinForEachEntrySafeD( pEntF, pEnt, pEntD2 )
+ {
+ // decide where to put entry pEnt
+ Key = pEnt->uHashD % pT->nBins;
+ if ( fLinkEquiv )
+ {
+ // go through the entries in the new bin
+ Fraig_TableBinForEachEntryF( pBinsNew[Key], pEntN )
+ {
+ // if they have different values skip
+ if ( pEnt->uHashD != pEntN->uHashD )
+ continue;
+ // they have the same hash value, add pEnt to the D-list pEnt3
+ pEnt->pNextD = pEntN->pNextD;
+ pEntN->pNextD = pEnt;
+ ReturnValue = 1;
+ Counter++;
+ break;
+ }
+ if ( pEntN != NULL ) // already linked
+ continue;
+ // we did not find equal entry
+ }
+ // link the new entry
+ pEnt->pNextF = pBinsNew[Key];
+ pBinsNew[Key] = pEnt;
+ pEnt->pNextD = NULL;
+ Counter++;
+ }
+ assert( Counter == pT->nEntries );
+ // replace the table and the parameters
+ ABC_FREE( pT->pBins );
+ pT->pBins = pBinsNew;
+ return ReturnValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fraig/fraigUtil.c b/src/proof/fraig/fraigUtil.c
new file mode 100644
index 00000000..ae78a61f
--- /dev/null
+++ b/src/proof/fraig/fraigUtil.c
@@ -0,0 +1,1039 @@
+/**CFile****************************************************************
+
+ FileName [fraigUtil.c]
+
+ PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+ Synopsis [Various utilities.]
+
+ Author [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - October 1, 2004]
+
+ Revision [$Id: fraigUtil.c,v 1.15 2005/07/08 01:01:34 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fraigInt.h"
+#include <limits.h>
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static int bit_count[256] = {
+ 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
+};
+
+static void Fraig_Dfs_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_NodeVec_t * vNodes, int fEquiv );
+static int Fraig_CheckTfi_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_Node_t * pOld );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes the DFS ordering of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_NodeVec_t * Fraig_Dfs( Fraig_Man_t * pMan, int fEquiv )
+{
+ Fraig_NodeVec_t * vNodes;
+ int i;
+ pMan->nTravIds++;
+ vNodes = Fraig_NodeVecAlloc( 100 );
+ for ( i = 0; i < pMan->vOutputs->nSize; i++ )
+ Fraig_Dfs_rec( pMan, Fraig_Regular(pMan->vOutputs->pArray[i]), vNodes, fEquiv );
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the DFS ordering of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_NodeVec_t * Fraig_DfsOne( Fraig_Man_t * pMan, Fraig_Node_t * pNode, int fEquiv )
+{
+ Fraig_NodeVec_t * vNodes;
+ pMan->nTravIds++;
+ vNodes = Fraig_NodeVecAlloc( 100 );
+ Fraig_Dfs_rec( pMan, Fraig_Regular(pNode), vNodes, fEquiv );
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the DFS ordering of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_NodeVec_t * Fraig_DfsNodes( Fraig_Man_t * pMan, Fraig_Node_t ** ppNodes, int nNodes, int fEquiv )
+{
+ Fraig_NodeVec_t * vNodes;
+ int i;
+ pMan->nTravIds++;
+ vNodes = Fraig_NodeVecAlloc( 100 );
+ for ( i = 0; i < nNodes; i++ )
+ Fraig_Dfs_rec( pMan, Fraig_Regular(ppNodes[i]), vNodes, fEquiv );
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively computes the DFS ordering of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_Dfs_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_NodeVec_t * vNodes, int fEquiv )
+{
+ assert( !Fraig_IsComplement(pNode) );
+ // skip the visited node
+ if ( pNode->TravId == pMan->nTravIds )
+ return;
+ pNode->TravId = pMan->nTravIds;
+ // visit the transitive fanin
+ if ( Fraig_NodeIsAnd(pNode) )
+ {
+ Fraig_Dfs_rec( pMan, Fraig_Regular(pNode->p1), vNodes, fEquiv );
+ Fraig_Dfs_rec( pMan, Fraig_Regular(pNode->p2), vNodes, fEquiv );
+ }
+ if ( fEquiv && pNode->pNextE )
+ Fraig_Dfs_rec( pMan, pNode->pNextE, vNodes, fEquiv );
+ // save the node
+ Fraig_NodeVecPush( vNodes, pNode );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the DFS ordering of the nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_CountNodes( Fraig_Man_t * pMan, int fEquiv )
+{
+ Fraig_NodeVec_t * vNodes;
+ int RetValue;
+ vNodes = Fraig_Dfs( pMan, fEquiv );
+ RetValue = vNodes->nSize;
+ Fraig_NodeVecFree( vNodes );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if pOld is in the TFI of pNew.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_CheckTfi( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew )
+{
+ assert( !Fraig_IsComplement(pOld) );
+ assert( !Fraig_IsComplement(pNew) );
+ pMan->nTravIds++;
+ return Fraig_CheckTfi_rec( pMan, pNew, pOld );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if pOld is in the TFI of pNew.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_CheckTfi_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_Node_t * pOld )
+{
+ // check the trivial cases
+ if ( pNode == NULL )
+ return 0;
+ if ( pNode->Num < pOld->Num && !pMan->fChoicing )
+ return 0;
+ if ( pNode == pOld )
+ return 1;
+ // skip the visited node
+ if ( pNode->TravId == pMan->nTravIds )
+ return 0;
+ pNode->TravId = pMan->nTravIds;
+ // check the children
+ if ( Fraig_CheckTfi_rec( pMan, Fraig_Regular(pNode->p1), pOld ) )
+ return 1;
+ if ( Fraig_CheckTfi_rec( pMan, Fraig_Regular(pNode->p2), pOld ) )
+ return 1;
+ // check equivalent nodes
+ return Fraig_CheckTfi_rec( pMan, pNode->pNextE, pOld );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if pOld is in the TFI of pNew.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_CheckTfi2( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew )
+{
+ Fraig_NodeVec_t * vNodes;
+ int RetValue;
+ vNodes = Fraig_DfsOne( pMan, pNew, 1 );
+ RetValue = (pOld->TravId == pMan->nTravIds);
+ Fraig_NodeVecFree( vNodes );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the number of fanouts (none, one, or many).]
+
+ Description [This procedure collects the nodes reachable from
+ the POs of the AIG and sets the type of fanout counter (none, one,
+ or many) for each node. This procedure is useful to determine
+ fanout-free cones of AND-nodes, which is helpful for rebalancing
+ the AIG (see procedure Fraig_ManRebalance, or something like that).]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_ManMarkRealFanouts( Fraig_Man_t * p )
+{
+ Fraig_NodeVec_t * vNodes;
+ Fraig_Node_t * pNodeR;
+ int i;
+ // collect the nodes reachable
+ vNodes = Fraig_Dfs( p, 0 );
+ // clean the fanouts field
+ for ( i = 0; i < vNodes->nSize; i++ )
+ {
+ vNodes->pArray[i]->nFanouts = 0;
+ vNodes->pArray[i]->pData0 = NULL;
+ }
+ // mark reachable nodes by setting the two-bit counter pNode->nFans
+ for ( i = 0; i < vNodes->nSize; i++ )
+ {
+ pNodeR = Fraig_Regular(vNodes->pArray[i]->p1);
+ if ( pNodeR && ++pNodeR->nFanouts == 3 )
+ pNodeR->nFanouts = 2;
+ pNodeR = Fraig_Regular(vNodes->pArray[i]->p2);
+ if ( pNodeR && ++pNodeR->nFanouts == 3 )
+ pNodeR->nFanouts = 2;
+ }
+ Fraig_NodeVecFree( vNodes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates the constant 1 node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_BitStringCountOnes( unsigned * pString, int nWords )
+{
+ unsigned char * pSuppBytes = (unsigned char *)pString;
+ int i, nOnes, nBytes = sizeof(unsigned) * nWords;
+ // count the number of ones in the simulation vector
+ for ( i = nOnes = 0; i < nBytes; i++ )
+ nOnes += bit_count[pSuppBytes[i]];
+ return nOnes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verify one useful property.]
+
+ Description [This procedure verifies one useful property. After
+ the FRAIG construction with choice nodes is over, each primary node
+ should have fanins that are primary nodes. The primary nodes is the
+ one that does not have pNode->pRepr set to point to another node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_ManCheckConsistency( Fraig_Man_t * p )
+{
+ Fraig_Node_t * pNode;
+ Fraig_NodeVec_t * pVec;
+ int i;
+ pVec = Fraig_Dfs( p, 0 );
+ for ( i = 0; i < pVec->nSize; i++ )
+ {
+ pNode = pVec->pArray[i];
+ if ( Fraig_NodeIsVar(pNode) )
+ {
+ if ( pNode->pRepr )
+ printf( "Primary input %d is a secondary node.\n", pNode->Num );
+ }
+ else if ( Fraig_NodeIsConst(pNode) )
+ {
+ if ( pNode->pRepr )
+ printf( "Constant 1 %d is a secondary node.\n", pNode->Num );
+ }
+ else
+ {
+ if ( pNode->pRepr )
+ printf( "Internal node %d is a secondary node.\n", pNode->Num );
+ if ( Fraig_Regular(pNode->p1)->pRepr )
+ printf( "Internal node %d has first fanin %d that is a secondary node.\n",
+ pNode->Num, Fraig_Regular(pNode->p1)->Num );
+ if ( Fraig_Regular(pNode->p2)->pRepr )
+ printf( "Internal node %d has second fanin %d that is a secondary node.\n",
+ pNode->Num, Fraig_Regular(pNode->p2)->Num );
+ }
+ }
+ Fraig_NodeVecFree( pVec );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_PrintNode( Fraig_Man_t * p, Fraig_Node_t * pNode )
+{
+ Fraig_NodeVec_t * vNodes;
+ Fraig_Node_t * pTemp;
+ int fCompl1, fCompl2, i;
+
+ vNodes = Fraig_DfsOne( p, pNode, 0 );
+ for ( i = 0; i < vNodes->nSize; i++ )
+ {
+ pTemp = vNodes->pArray[i];
+ if ( Fraig_NodeIsVar(pTemp) )
+ {
+ printf( "%3d : PI ", pTemp->Num );
+ Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimR, 20 );
+ printf( " " );
+ Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimD, 20 );
+ printf( " %d\n", pTemp->fInv );
+ continue;
+ }
+
+ fCompl1 = Fraig_IsComplement(pTemp->p1);
+ fCompl2 = Fraig_IsComplement(pTemp->p2);
+ printf( "%3d : %c%3d %c%3d ", pTemp->Num,
+ (fCompl1? '-':'+'), Fraig_Regular(pTemp->p1)->Num,
+ (fCompl2? '-':'+'), Fraig_Regular(pTemp->p2)->Num );
+ Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimR, 20 );
+ printf( " " );
+ Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimD, 20 );
+ printf( " %d\n", pTemp->fInv );
+ }
+ Fraig_NodeVecFree( vNodes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the bit string.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_PrintBinary( FILE * pFile, unsigned * pSign, int nBits )
+{
+ int Remainder, nWords;
+ int w, i;
+
+ Remainder = (nBits%(sizeof(unsigned)*8));
+ nWords = (nBits/(sizeof(unsigned)*8)) + (Remainder>0);
+
+ for ( w = nWords-1; w >= 0; w-- )
+ for ( i = ((w == nWords-1 && Remainder)? Remainder-1: 31); i >= 0; i-- )
+ fprintf( pFile, "%c", '0' + (int)((pSign[w] & (1<<i)) > 0) );
+
+// fprintf( pFile, "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets up the mask.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_GetMaxLevel( Fraig_Man_t * pMan )
+{
+ int nLevelMax, i;
+ nLevelMax = 0;
+ for ( i = 0; i < pMan->vOutputs->nSize; i++ )
+ nLevelMax = nLevelMax > Fraig_Regular(pMan->vOutputs->pArray[i])->Level?
+ nLevelMax : Fraig_Regular(pMan->vOutputs->pArray[i])->Level;
+ return nLevelMax;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Analyses choice nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_MappingUpdateLevel_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, int fMaximum )
+{
+ Fraig_Node_t * pTemp;
+ int Level1, Level2, LevelE;
+ assert( !Fraig_IsComplement(pNode) );
+ if ( !Fraig_NodeIsAnd(pNode) )
+ return pNode->Level;
+ // skip the visited node
+ if ( pNode->TravId == pMan->nTravIds )
+ return pNode->Level;
+ pNode->TravId = pMan->nTravIds;
+ // compute levels of the children nodes
+ Level1 = Fraig_MappingUpdateLevel_rec( pMan, Fraig_Regular(pNode->p1), fMaximum );
+ Level2 = Fraig_MappingUpdateLevel_rec( pMan, Fraig_Regular(pNode->p2), fMaximum );
+ pNode->Level = 1 + Abc_MaxInt( Level1, Level2 );
+ if ( pNode->pNextE )
+ {
+ LevelE = Fraig_MappingUpdateLevel_rec( pMan, pNode->pNextE, fMaximum );
+ if ( fMaximum )
+ {
+ if ( pNode->Level < LevelE )
+ pNode->Level = LevelE;
+ }
+ else
+ {
+ if ( pNode->Level > LevelE )
+ pNode->Level = LevelE;
+ }
+ // set the level of all equivalent nodes to be the same minimum
+ if ( pNode->pRepr == NULL ) // the primary node
+ for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE )
+ pTemp->Level = pNode->Level;
+ }
+ return pNode->Level;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resets the levels of the nodes in the choice graph.]
+
+ Description [Makes the level of the choice nodes to be equal to the
+ maximum of the level of the nodes in the equivalence class. This way
+ sorting by level leads to the reverse topological order, which is
+ needed for the required time computation.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_MappingSetChoiceLevels( Fraig_Man_t * pMan, int fMaximum )
+{
+ int i;
+ pMan->nTravIds++;
+ for ( i = 0; i < pMan->vOutputs->nSize; i++ )
+ Fraig_MappingUpdateLevel_rec( pMan, Fraig_Regular(pMan->vOutputs->pArray[i]), fMaximum );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reports statistics on choice nodes.]
+
+ Description [The number of choice nodes is the number of primary nodes,
+ which has pNextE set to a pointer. The number of choices is the number
+ of entries in the equivalent-node lists of the primary nodes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_ManReportChoices( Fraig_Man_t * pMan )
+{
+ Fraig_Node_t * pNode, * pTemp;
+ int nChoiceNodes, nChoices;
+ int i, LevelMax1, LevelMax2;
+
+ // report the number of levels
+ LevelMax1 = Fraig_GetMaxLevel( pMan );
+ Fraig_MappingSetChoiceLevels( pMan, 0 );
+ LevelMax2 = Fraig_GetMaxLevel( pMan );
+
+ // report statistics about choices
+ nChoiceNodes = nChoices = 0;
+ for ( i = 0; i < pMan->vNodes->nSize; i++ )
+ {
+ pNode = pMan->vNodes->pArray[i];
+ if ( pNode->pRepr == NULL && pNode->pNextE != NULL )
+ { // this is a choice node = the primary node that has equivalent nodes
+ nChoiceNodes++;
+ for ( pTemp = pNode; pTemp; pTemp = pTemp->pNextE )
+ nChoices++;
+ }
+ }
+ printf( "Maximum level: Original = %d. Reduced due to choices = %d.\n", LevelMax1, LevelMax2 );
+ printf( "Choice stats: Choice nodes = %d. Total choices = %d.\n", nChoiceNodes, nChoices );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the node is the root of EXOR/NEXOR gate.]
+
+ Description [The node can be complemented.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_NodeIsExorType( Fraig_Node_t * pNode )
+{
+ Fraig_Node_t * pNode1, * pNode2;
+ // make the node regular (it does not matter for EXOR/NEXOR)
+ pNode = Fraig_Regular(pNode);
+ // if the node or its children are not ANDs or not compl, this cannot be EXOR type
+ if ( !Fraig_NodeIsAnd(pNode) )
+ return 0;
+ if ( !Fraig_NodeIsAnd(pNode->p1) || !Fraig_IsComplement(pNode->p1) )
+ return 0;
+ if ( !Fraig_NodeIsAnd(pNode->p2) || !Fraig_IsComplement(pNode->p2) )
+ return 0;
+
+ // get children
+ pNode1 = Fraig_Regular(pNode->p1);
+ pNode2 = Fraig_Regular(pNode->p2);
+ assert( pNode1->Num < pNode2->Num );
+
+ // compare grandchildren
+ return pNode1->p1 == Fraig_Not(pNode2->p1) && pNode1->p2 == Fraig_Not(pNode2->p2);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.]
+
+ Description [The node can be complemented.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_NodeIsMuxType( Fraig_Node_t * pNode )
+{
+ Fraig_Node_t * pNode1, * pNode2;
+
+ // make the node regular (it does not matter for EXOR/NEXOR)
+ pNode = Fraig_Regular(pNode);
+ // if the node or its children are not ANDs or not compl, this cannot be EXOR type
+ if ( !Fraig_NodeIsAnd(pNode) )
+ return 0;
+ if ( !Fraig_NodeIsAnd(pNode->p1) || !Fraig_IsComplement(pNode->p1) )
+ return 0;
+ if ( !Fraig_NodeIsAnd(pNode->p2) || !Fraig_IsComplement(pNode->p2) )
+ return 0;
+
+ // get children
+ pNode1 = Fraig_Regular(pNode->p1);
+ pNode2 = Fraig_Regular(pNode->p2);
+ assert( pNode1->Num < pNode2->Num );
+
+ // compare grandchildren
+ // node is an EXOR/NEXOR
+ if ( pNode1->p1 == Fraig_Not(pNode2->p1) && pNode1->p2 == Fraig_Not(pNode2->p2) )
+ return 1;
+
+ // otherwise the node is MUX iff it has a pair of equal grandchildren
+ return pNode1->p1 == Fraig_Not(pNode2->p1) ||
+ pNode1->p1 == Fraig_Not(pNode2->p2) ||
+ pNode1->p2 == Fraig_Not(pNode2->p1) ||
+ pNode1->p2 == Fraig_Not(pNode2->p2);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the node is EXOR, 0 if it is NEXOR.]
+
+ Description [The node should be EXOR type and not complemented.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_NodeIsExor( Fraig_Node_t * pNode )
+{
+ Fraig_Node_t * pNode1;
+ assert( !Fraig_IsComplement(pNode) );
+ assert( Fraig_NodeIsExorType(pNode) );
+ assert( Fraig_IsComplement(pNode->p1) );
+ // get children
+ pNode1 = Fraig_Regular(pNode->p1);
+ return Fraig_IsComplement(pNode1->p1) == Fraig_IsComplement(pNode1->p2);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recognizes what nodes are control and data inputs of a MUX.]
+
+ Description [If the node is a MUX, returns the control variable C.
+ Assigns nodes T and E to be the then and else variables of the MUX.
+ Node C is never complemented. Nodes T and E can be complemented.
+ This function also recognizes EXOR/NEXOR gates as MUXes.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_NodeRecognizeMux( Fraig_Node_t * pNode, Fraig_Node_t ** ppNodeT, Fraig_Node_t ** ppNodeE )
+{
+ Fraig_Node_t * pNode1, * pNode2;
+ assert( !Fraig_IsComplement(pNode) );
+ assert( Fraig_NodeIsMuxType(pNode) );
+ // get children
+ pNode1 = Fraig_Regular(pNode->p1);
+ pNode2 = Fraig_Regular(pNode->p2);
+ // find the control variable
+ if ( pNode1->p1 == Fraig_Not(pNode2->p1) )
+ {
+ if ( Fraig_IsComplement(pNode1->p1) )
+ { // pNode2->p1 is positive phase of C
+ *ppNodeT = Fraig_Not(pNode2->p2);
+ *ppNodeE = Fraig_Not(pNode1->p2);
+ return pNode2->p1;
+ }
+ else
+ { // pNode1->p1 is positive phase of C
+ *ppNodeT = Fraig_Not(pNode1->p2);
+ *ppNodeE = Fraig_Not(pNode2->p2);
+ return pNode1->p1;
+ }
+ }
+ else if ( pNode1->p1 == Fraig_Not(pNode2->p2) )
+ {
+ if ( Fraig_IsComplement(pNode1->p1) )
+ { // pNode2->p2 is positive phase of C
+ *ppNodeT = Fraig_Not(pNode2->p1);
+ *ppNodeE = Fraig_Not(pNode1->p2);
+ return pNode2->p2;
+ }
+ else
+ { // pNode1->p1 is positive phase of C
+ *ppNodeT = Fraig_Not(pNode1->p2);
+ *ppNodeE = Fraig_Not(pNode2->p1);
+ return pNode1->p1;
+ }
+ }
+ else if ( pNode1->p2 == Fraig_Not(pNode2->p1) )
+ {
+ if ( Fraig_IsComplement(pNode1->p2) )
+ { // pNode2->p1 is positive phase of C
+ *ppNodeT = Fraig_Not(pNode2->p2);
+ *ppNodeE = Fraig_Not(pNode1->p1);
+ return pNode2->p1;
+ }
+ else
+ { // pNode1->p2 is positive phase of C
+ *ppNodeT = Fraig_Not(pNode1->p1);
+ *ppNodeE = Fraig_Not(pNode2->p2);
+ return pNode1->p2;
+ }
+ }
+ else if ( pNode1->p2 == Fraig_Not(pNode2->p2) )
+ {
+ if ( Fraig_IsComplement(pNode1->p2) )
+ { // pNode2->p2 is positive phase of C
+ *ppNodeT = Fraig_Not(pNode2->p1);
+ *ppNodeE = Fraig_Not(pNode1->p1);
+ return pNode2->p2;
+ }
+ else
+ { // pNode1->p2 is positive phase of C
+ *ppNodeT = Fraig_Not(pNode1->p1);
+ *ppNodeE = Fraig_Not(pNode2->p1);
+ return pNode1->p2;
+ }
+ }
+ assert( 0 ); // this is not MUX
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of EXOR type nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_ManCountExors( Fraig_Man_t * pMan )
+{
+ int i, nExors;
+ nExors = 0;
+ for ( i = 0; i < pMan->vNodes->nSize; i++ )
+ nExors += Fraig_NodeIsExorType( pMan->vNodes->pArray[i] );
+ return nExors;
+
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of EXOR type nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_ManCountMuxes( Fraig_Man_t * pMan )
+{
+ int i, nMuxes;
+ nMuxes = 0;
+ for ( i = 0; i < pMan->vNodes->nSize; i++ )
+ nMuxes += Fraig_NodeIsMuxType( pMan->vNodes->pArray[i] );
+ return nMuxes;
+
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if siminfo of Node1 is contained in siminfo of Node2.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_NodeSimsContained( Fraig_Man_t * pMan, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 )
+{
+ unsigned * pUnsigned1, * pUnsigned2;
+ int i;
+
+ // compare random siminfo
+ pUnsigned1 = pNode1->puSimR;
+ pUnsigned2 = pNode2->puSimR;
+ for ( i = 0; i < pMan->nWordsRand; i++ )
+ if ( pUnsigned1[i] & ~pUnsigned2[i] )
+ return 0;
+
+ // compare systematic siminfo
+ pUnsigned1 = pNode1->puSimD;
+ pUnsigned2 = pNode2->puSimD;
+ for ( i = 0; i < pMan->iWordStart; i++ )
+ if ( pUnsigned1[i] & ~pUnsigned2[i] )
+ return 0;
+
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Count the number of PI variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_CountPis( Fraig_Man_t * p, Msat_IntVec_t * vVarNums )
+{
+ int * pVars, nVars, i, Counter;
+
+ nVars = Msat_IntVecReadSize(vVarNums);
+ pVars = Msat_IntVecReadArray(vVarNums);
+ Counter = 0;
+ for ( i = 0; i < nVars; i++ )
+ Counter += Fraig_NodeIsVar( p->vNodes->pArray[pVars[i]] );
+ return Counter;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of EXOR type nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_ManPrintRefs( Fraig_Man_t * pMan )
+{
+ Fraig_NodeVec_t * vPivots;
+ Fraig_Node_t * pNode, * pNode2;
+ int i, k, Counter, nProved;
+ int clk;
+
+ vPivots = Fraig_NodeVecAlloc( 1000 );
+ for ( i = 0; i < pMan->vNodes->nSize; i++ )
+ {
+ pNode = pMan->vNodes->pArray[i];
+
+ if ( pNode->nOnes == 0 || pNode->nOnes == (unsigned)pMan->nWordsRand * 32 )
+ continue;
+
+ if ( pNode->nRefs > 5 )
+ {
+ Fraig_NodeVecPush( vPivots, pNode );
+// printf( "Node %6d : nRefs = %2d Level = %3d.\n", pNode->Num, pNode->nRefs, pNode->Level );
+ }
+ }
+ printf( "Total nodes = %d. Referenced nodes = %d.\n", pMan->vNodes->nSize, vPivots->nSize );
+
+clk = clock();
+ // count implications
+ Counter = nProved = 0;
+ for ( i = 0; i < vPivots->nSize; i++ )
+ for ( k = i+1; k < vPivots->nSize; k++ )
+ {
+ pNode = vPivots->pArray[i];
+ pNode2 = vPivots->pArray[k];
+ if ( Fraig_NodeSimsContained( pMan, pNode, pNode2 ) )
+ {
+ if ( Fraig_NodeIsImplication( pMan, pNode, pNode2, -1 ) )
+ nProved++;
+ Counter++;
+ }
+ else if ( Fraig_NodeSimsContained( pMan, pNode2, pNode ) )
+ {
+ if ( Fraig_NodeIsImplication( pMan, pNode2, pNode, -1 ) )
+ nProved++;
+ Counter++;
+ }
+ }
+ printf( "Number of candidate pairs = %d. Proved = %d.\n", Counter, nProved );
+//ABC_PRT( "Time", clock() - clk );
+ return 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Checks if pNew exists among the implication fanins of pOld.]
+
+ Description [If pNew is an implication fanin of pOld, returns 1.
+ If Fraig_Not(pNew) is an implication fanin of pOld, return -1.
+ Otherwise returns 0.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_NodeIsInSupergate( Fraig_Node_t * pOld, Fraig_Node_t * pNew )
+{
+ int RetValue1, RetValue2;
+ if ( Fraig_Regular(pOld) == Fraig_Regular(pNew) )
+ return (pOld == pNew)? 1 : -1;
+ if ( Fraig_IsComplement(pOld) || Fraig_NodeIsVar(pOld) )
+ return 0;
+ RetValue1 = Fraig_NodeIsInSupergate( pOld->p1, pNew );
+ RetValue2 = Fraig_NodeIsInSupergate( pOld->p2, pNew );
+ if ( RetValue1 == -1 || RetValue2 == -1 )
+ return -1;
+ if ( RetValue1 == 1 || RetValue2 == 1 )
+ return 1;
+ return 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_CollectSupergate_rec( Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper, int fFirst, int fStopAtMux )
+{
+ // if the new node is complemented or a PI, another gate begins
+// if ( Fraig_IsComplement(pNode) || Fraig_NodeIsVar(pNode) || Fraig_NodeIsMuxType(pNode) )
+ if ( (!fFirst && Fraig_Regular(pNode)->nRefs > 1) ||
+ Fraig_IsComplement(pNode) || Fraig_NodeIsVar(pNode) ||
+ (fStopAtMux && Fraig_NodeIsMuxType(pNode)) )
+ {
+ Fraig_NodeVecPushUnique( vSuper, pNode );
+ return;
+ }
+ // go through the branches
+ Fraig_CollectSupergate_rec( pNode->p1, vSuper, 0, fStopAtMux );
+ Fraig_CollectSupergate_rec( pNode->p2, vSuper, 0, fStopAtMux );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_NodeVec_t * Fraig_CollectSupergate( Fraig_Node_t * pNode, int fStopAtMux )
+{
+ Fraig_NodeVec_t * vSuper;
+ vSuper = Fraig_NodeVecAlloc( 8 );
+ Fraig_CollectSupergate_rec( pNode, vSuper, 1, fStopAtMux );
+ return vSuper;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_ManIncrementTravId( Fraig_Man_t * pMan )
+{
+ pMan->nTravIds2++;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_NodeSetTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
+{
+ pNode->TravId2 = pMan->nTravIds2;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_NodeIsTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
+{
+ return pNode->TravId2 == pMan->nTravIds2;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_NodeIsTravIdPrevious( Fraig_Man_t * pMan, Fraig_Node_t * pNode )
+{
+ return pNode->TravId2 == pMan->nTravIds2 - 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fraig/fraigVec.c b/src/proof/fraig/fraigVec.c
new file mode 100644
index 00000000..25d50bf3
--- /dev/null
+++ b/src/proof/fraig/fraigVec.c
@@ -0,0 +1,550 @@
+/**CFile****************************************************************
+
+ FileName [fraigVec.c]
+
+ PackageName [FRAIG: Functionally reduced AND-INV graphs.]
+
+ Synopsis [Vector of FRAIG nodes.]
+
+ Author [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 2.0. Started - October 1, 2004]
+
+ Revision [$Id: fraigVec.c,v 1.7 2005/07/08 01:01:34 alanmi Exp $]
+
+***********************************************************************/
+
+#include "fraigInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Allocates a vector with the given capacity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_NodeVec_t * Fraig_NodeVecAlloc( int nCap )
+{
+ Fraig_NodeVec_t * p;
+ p = ABC_ALLOC( Fraig_NodeVec_t, 1 );
+ if ( nCap > 0 && nCap < 8 )
+ nCap = 8;
+ p->nSize = 0;
+ p->nCap = nCap;
+ p->pArray = p->nCap? ABC_ALLOC( Fraig_Node_t *, p->nCap ) : NULL;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_NodeVecFree( Fraig_NodeVec_t * p )
+{
+ ABC_FREE( p->pArray );
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates the integer array.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_NodeVec_t * Fraig_NodeVecDup( Fraig_NodeVec_t * pVec )
+{
+ Fraig_NodeVec_t * p;
+ p = ABC_ALLOC( Fraig_NodeVec_t, 1 );
+ p->nSize = pVec->nSize;
+ p->nCap = pVec->nCap;
+ p->pArray = p->nCap? ABC_ALLOC( Fraig_Node_t *, p->nCap ) : NULL;
+ memcpy( p->pArray, pVec->pArray, sizeof(Fraig_Node_t *) * pVec->nSize );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_Node_t ** Fraig_NodeVecReadArray( Fraig_NodeVec_t * p )
+{
+ return p->pArray;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_NodeVecReadSize( Fraig_NodeVec_t * p )
+{
+ return p->nSize;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resizes the vector to the given capacity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_NodeVecGrow( Fraig_NodeVec_t * p, int nCapMin )
+{
+ if ( p->nCap >= nCapMin )
+ return;
+ p->pArray = ABC_REALLOC( Fraig_Node_t *, p->pArray, nCapMin );
+ p->nCap = nCapMin;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_NodeVecShrink( Fraig_NodeVec_t * p, int nSizeNew )
+{
+ assert( p->nSize >= nSizeNew );
+ p->nSize = nSizeNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_NodeVecClear( Fraig_NodeVec_t * p )
+{
+ p->nSize = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_NodeVecPush( Fraig_NodeVec_t * p, Fraig_Node_t * Entry )
+{
+ if ( p->nSize == p->nCap )
+ {
+ if ( p->nCap < 16 )
+ Fraig_NodeVecGrow( p, 16 );
+ else
+ Fraig_NodeVecGrow( p, 2 * p->nCap );
+ }
+ p->pArray[p->nSize++] = Entry;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Add the element while ensuring uniqueness.]
+
+ Description [Returns 1 if the element was found, and 0 if it was new. ]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_NodeVecPushUnique( Fraig_NodeVec_t * p, Fraig_Node_t * Entry )
+{
+ int i;
+ for ( i = 0; i < p->nSize; i++ )
+ if ( p->pArray[i] == Entry )
+ return 1;
+ Fraig_NodeVecPush( p, Entry );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts a new node in the order by arrival times.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_NodeVecPushOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode )
+{
+ Fraig_Node_t * pNode1, * pNode2;
+ int i;
+ Fraig_NodeVecPush( p, pNode );
+ // find the p of the node
+ for ( i = p->nSize-1; i > 0; i-- )
+ {
+ pNode1 = p->pArray[i ];
+ pNode2 = p->pArray[i-1];
+ if ( pNode1 >= pNode2 )
+ break;
+ p->pArray[i ] = pNode2;
+ p->pArray[i-1] = pNode1;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Add the element while ensuring uniqueness in the order.]
+
+ Description [Returns 1 if the element was found, and 0 if it was new. ]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_NodeVecPushUniqueOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode )
+{
+ int i;
+ for ( i = 0; i < p->nSize; i++ )
+ if ( p->pArray[i] == pNode )
+ return 1;
+ Fraig_NodeVecPushOrder( p, pNode );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Inserts a new node in the order by arrival times.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_NodeVecPushOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode )
+{
+ Fraig_Node_t * pNode1, * pNode2;
+ int i;
+ Fraig_NodeVecPush( p, pNode );
+ // find the p of the node
+ for ( i = p->nSize-1; i > 0; i-- )
+ {
+ pNode1 = p->pArray[i ];
+ pNode2 = p->pArray[i-1];
+ if ( Fraig_Regular(pNode1)->Level <= Fraig_Regular(pNode2)->Level )
+ break;
+ p->pArray[i ] = pNode2;
+ p->pArray[i-1] = pNode1;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Add the element while ensuring uniqueness in the order.]
+
+ Description [Returns 1 if the element was found, and 0 if it was new. ]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_NodeVecPushUniqueOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode )
+{
+ int i;
+ for ( i = 0; i < p->nSize; i++ )
+ if ( p->pArray[i] == pNode )
+ return 1;
+ Fraig_NodeVecPushOrderByLevel( p, pNode );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_NodeVecPop( Fraig_NodeVec_t * p )
+{
+ return p->pArray[--p->nSize];
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_NodeVecRemove( Fraig_NodeVec_t * p, Fraig_Node_t * Entry )
+{
+ int i;
+ for ( i = 0; i < p->nSize; i++ )
+ if ( p->pArray[i] == Entry )
+ break;
+ assert( i < p->nSize );
+ for ( i++; i < p->nSize; i++ )
+ p->pArray[i-1] = p->pArray[i];
+ p->nSize--;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_NodeVecWriteEntry( Fraig_NodeVec_t * p, int i, Fraig_Node_t * Entry )
+{
+ assert( i >= 0 && i < p->nSize );
+ p->pArray[i] = Entry;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Fraig_Node_t * Fraig_NodeVecReadEntry( Fraig_NodeVec_t * p, int i )
+{
+ assert( i >= 0 && i < p->nSize );
+ return p->pArray[i];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Comparison procedure for two clauses.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_NodeVecCompareLevelsIncreasing( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 )
+{
+ int Level1 = Fraig_Regular(*pp1)->Level;
+ int Level2 = Fraig_Regular(*pp2)->Level;
+ if ( Level1 < Level2 )
+ return -1;
+ if ( Level1 > Level2 )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Comparison procedure for two clauses.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_NodeVecCompareLevelsDecreasing( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 )
+{
+ int Level1 = Fraig_Regular(*pp1)->Level;
+ int Level2 = Fraig_Regular(*pp2)->Level;
+ if ( Level1 > Level2 )
+ return -1;
+ if ( Level1 < Level2 )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Comparison procedure for two clauses.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_NodeVecCompareNumbers( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 )
+{
+ int Num1 = Fraig_Regular(*pp1)->Num;
+ int Num2 = Fraig_Regular(*pp2)->Num;
+ if ( Num1 < Num2 )
+ return -1;
+ if ( Num1 > Num2 )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Comparison procedure for two clauses.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Fraig_NodeVecCompareRefCounts( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 )
+{
+ int nRefs1 = Fraig_Regular(*pp1)->nRefs;
+ int nRefs2 = Fraig_Regular(*pp2)->nRefs;
+
+ if ( nRefs1 < nRefs2 )
+ return -1;
+ if ( nRefs1 > nRefs2 )
+ return 1;
+
+ nRefs1 = Fraig_Regular(*pp1)->Level;
+ nRefs2 = Fraig_Regular(*pp2)->Level;
+
+ if ( nRefs1 < nRefs2 )
+ return -1;
+ if ( nRefs1 > nRefs2 )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sorting the entries by their integer value.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_NodeVecSortByLevel( Fraig_NodeVec_t * p, int fIncreasing )
+{
+ if ( fIncreasing )
+ qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *),
+ (int (*)(const void *, const void *)) Fraig_NodeVecCompareLevelsIncreasing );
+ else
+ qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *),
+ (int (*)(const void *, const void *)) Fraig_NodeVecCompareLevelsDecreasing );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sorting the entries by their integer value.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_NodeVecSortByNumber( Fraig_NodeVec_t * p )
+{
+ qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *),
+ (int (*)(const void *, const void *)) Fraig_NodeVecCompareNumbers );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sorting the entries by their integer value.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Fraig_NodeVecSortByRefCount( Fraig_NodeVec_t * p )
+{
+ qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *),
+ (int (*)(const void *, const void *)) Fraig_NodeVecCompareRefCounts );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/fraig/module.make b/src/proof/fraig/module.make
new file mode 100644
index 00000000..4ca7cdce
--- /dev/null
+++ b/src/proof/fraig/module.make
@@ -0,0 +1,12 @@
+SRC += src/proof/fraig/fraigApi.c \
+ src/proof/fraig/fraigCanon.c \
+ src/proof/fraig/fraigFanout.c \
+ src/proof/fraig/fraigFeed.c \
+ src/proof/fraig/fraigMan.c \
+ src/proof/fraig/fraigMem.c \
+ src/proof/fraig/fraigNode.c \
+ src/proof/fraig/fraigPrime.c \
+ src/proof/fraig/fraigSat.c \
+ src/proof/fraig/fraigTable.c \
+ src/proof/fraig/fraigUtil.c \
+ src/proof/fraig/fraigVec.c
diff --git a/src/proof/int/int.h b/src/proof/int/int.h
new file mode 100644
index 00000000..a93e3c93
--- /dev/null
+++ b/src/proof/int/int.h
@@ -0,0 +1,94 @@
+/**CFile****************************************************************
+
+ FileName [int.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Interpolation engine.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 24, 2008.]
+
+ Revision [$Id: int.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__int__int_h
+#define ABC__aig__int__int_h
+
+
+/*
+ The interpolation algorithm implemented here was introduced in the paper:
+ K. L. McMillan. Interpolation and SAT-based model checking. CAV’03, pp. 1-13.
+*/
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+// simulation manager
+typedef struct Inter_ManParams_t_ Inter_ManParams_t;
+struct Inter_ManParams_t_
+{
+ int nBTLimit; // limit on the number of conflicts
+ int nFramesMax; // the max number timeframes to unroll
+ int nSecLimit; // time limit in seconds
+ int nFramesK; // the number of timeframes to use in induction
+ int fRewrite; // use additional rewriting to simplify timeframes
+ int fTransLoop; // add transition into the init state under new PI var
+ int fUsePudlak; // use Pudluk interpolation procedure
+ int fUseOther; // use other undisclosed option
+ int fUseMiniSat; // use MiniSat-1.14p instead of internal proof engine
+ int fCheckKstep; // check using K-step induction
+ int fUseBias; // bias decisions to global variables
+ int fUseBackward; // perform backward interpolation
+ int fUseSeparate; // solve each output separately
+ int fDropSatOuts; // replace by 1 the solved outputs
+ int fDropInvar; // dump inductive invariant into file
+ int fVerbose; // print verbose statistics
+ int iFrameMax; // the time frame reached
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== intCore.c ==========================================================*/
+extern void Inter_ManSetDefaultParams( Inter_ManParams_t * p );
+extern int Inter_ManPerformInterpolation( Aig_Man_t * pAig, Inter_ManParams_t * pPars, int * piFrame );
+
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/proof/int/intCheck.c b/src/proof/int/intCheck.c
new file mode 100644
index 00000000..6b36fe30
--- /dev/null
+++ b/src/proof/int/intCheck.c
@@ -0,0 +1,305 @@
+/**CFile****************************************************************
+
+ FileName [intCheck.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Interpolation engine.]
+
+ Synopsis [Procedures to perform incremental inductive check.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 24, 2008.]
+
+ Revision [$Id: intCheck.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "intInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// checking manager
+struct Inter_Check_t_
+{
+ int nFramesK; // the number of timeframes (K=1 for simple induction)
+ int nVars; // the current number of variables in the solver
+ Aig_Man_t * pFrames; // unrolled timeframes
+ Cnf_Dat_t * pCnf; // CNF of unrolled timeframes
+ sat_solver * pSat; // SAT solver
+ Vec_Int_t * vOrLits; // OR vars in each time frame (total number is the number nFrames)
+ Vec_Int_t * vAndLits; // AND vars in the last timeframe (total number is the number of interpolants)
+ Vec_Int_t * vAssLits; // assumptions (the union of the two)
+};
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Create timeframes of the manager for interpolation.]
+
+ Description [The resulting manager is combinational. The primary inputs
+ corresponding to register outputs are ordered first.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Inter_ManUnrollFrames( Aig_Man_t * pAig, int nFrames )
+{
+ Aig_Man_t * pFrames;
+ Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+ int i, f;
+ assert( Saig_ManRegNum(pAig) > 0 );
+ pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFrames );
+ // map the constant node
+ Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames );
+ // create variables for register outputs
+ Saig_ManForEachLo( pAig, pObj, i )
+ pObj->pData = Aig_ObjCreatePi( pFrames );
+ // add timeframes
+ for ( f = 0; f < nFrames; f++ )
+ {
+ // create PI nodes for this frame
+ Saig_ManForEachPi( pAig, pObj, i )
+ pObj->pData = Aig_ObjCreatePi( pFrames );
+ // add internal nodes of this frame
+ Aig_ManForEachNode( pAig, pObj, i )
+ pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+ // save register inputs
+ Saig_ManForEachLi( pAig, pObj, i )
+ pObj->pData = Aig_ObjChild0Copy(pObj);
+ // transfer to register outputs
+ Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
+ {
+ pObjLo->pData = pObjLi->pData;
+ Aig_ObjCreatePo( pFrames, (Aig_Obj_t *)pObjLo->pData );
+ }
+ }
+ Aig_ManCleanup( pFrames );
+ return pFrames;
+}
+
+/**Function*************************************************************
+
+ Synopsis [This procedure sets default values of interpolation parameters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Inter_Check_t * Inter_CheckStart( Aig_Man_t * pTrans, int nFramesK )
+{
+ Inter_Check_t * p;
+ // create solver
+ p = ABC_CALLOC( Inter_Check_t, 1 );
+ p->vOrLits = Vec_IntAlloc( 100 );
+ p->vAndLits = Vec_IntAlloc( 100 );
+ p->vAssLits = Vec_IntAlloc( 100 );
+ // generate the timeframes
+ p->pFrames = Inter_ManUnrollFrames( pTrans, nFramesK );
+ assert( Aig_ManPiNum(p->pFrames) == nFramesK * Saig_ManPiNum(pTrans) + Saig_ManRegNum(pTrans) );
+ assert( Aig_ManPoNum(p->pFrames) == nFramesK * Saig_ManRegNum(pTrans) );
+ // convert to CNF
+ p->pCnf = Cnf_Derive( p->pFrames, Aig_ManPoNum(p->pFrames) );
+ p->pSat = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 );
+ // assign parameters
+ p->nFramesK = nFramesK;
+ p->nVars = p->pCnf->nVars;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [This procedure sets default values of interpolation parameters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Inter_CheckStop( Inter_Check_t * p )
+{
+ if ( p == NULL )
+ return;
+ Vec_IntFree( p->vOrLits );
+ Vec_IntFree( p->vAndLits );
+ Vec_IntFree( p->vAssLits );
+ Cnf_DataFree( p->pCnf );
+ Aig_ManStop( p->pFrames );
+ sat_solver_delete( p->pSat );
+ ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Creates one OR-gate: A + B = C.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Inter_CheckAddOrGate( Inter_Check_t * p, int iVarA, int iVarB, int iVarC )
+{
+ int RetValue, pLits[3];
+ // add A => C or !A + C
+ pLits[0] = toLitCond(iVarA, 1);
+ pLits[1] = toLitCond(iVarC, 0);
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+ assert( RetValue );
+ // add B => C or !B + C
+ pLits[0] = toLitCond(iVarB, 1);
+ pLits[1] = toLitCond(iVarC, 0);
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+ assert( RetValue );
+ // add !A & !B => !C or A + B + !C
+ pLits[0] = toLitCond(iVarA, 0);
+ pLits[1] = toLitCond(iVarB, 0);
+ pLits[2] = toLitCond(iVarC, 1);
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates equality: A = B.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Inter_CheckAddEqual( Inter_Check_t * p, int iVarA, int iVarB )
+{
+ int RetValue, pLits[3];
+ // add A => B or !A + B
+ pLits[0] = toLitCond(iVarA, 1);
+ pLits[1] = toLitCond(iVarB, 0);
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+ assert( RetValue );
+ // add B => A or !B + A
+ pLits[0] = toLitCond(iVarB, 1);
+ pLits[1] = toLitCond(iVarA, 0);
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+ assert( RetValue );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Perform the checking.]
+
+ Description [Returns 1 if the check has passed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Inter_CheckPerform( Inter_Check_t * p, Cnf_Dat_t * pCnfInt, int nTimeNewOut )
+{
+ Aig_Obj_t * pObj, * pObj2;
+ int i, f, VarA, VarB, RetValue, Entry, status;
+ int nRegs = Aig_ManPiNum(pCnfInt->pMan);
+ assert( Aig_ManPoNum(p->pCnf->pMan) == p->nFramesK * nRegs );
+ assert( Aig_ManPoNum(pCnfInt->pMan) == 1 );
+
+ // set runtime limit
+ if ( nTimeNewOut )
+ sat_solver_set_runtime_limit( p->pSat, nTimeNewOut );
+
+ // add clauses to the SAT solver
+ Cnf_DataLift( pCnfInt, p->nVars );
+ for ( f = 0; f <= p->nFramesK; f++ )
+ {
+ // add clauses to the solver
+ for ( i = 0; i < pCnfInt->nClauses; i++ )
+ {
+ RetValue = sat_solver_addclause( p->pSat, pCnfInt->pClauses[i], pCnfInt->pClauses[i+1] );
+ assert( RetValue );
+ }
+ // add equality clauses for the flop variables
+ Aig_ManForEachPi( pCnfInt->pMan, pObj, i )
+ {
+ pObj2 = f ? Aig_ManPo(p->pFrames, i + (f-1) * nRegs) : Aig_ManPi(p->pFrames, i);
+ Inter_CheckAddEqual( p, pCnfInt->pVarNums[pObj->Id], p->pCnf->pVarNums[pObj2->Id] );
+ }
+ // add final clauses
+ if ( f < p->nFramesK )
+ {
+ if ( f == Vec_IntSize(p->vOrLits) ) // find time here
+ {
+ // add literal to this frame
+ VarB = pCnfInt->pVarNums[ Aig_ManPo(pCnfInt->pMan, 0)->Id ];
+ Vec_IntPush( p->vOrLits, VarB );
+ }
+ else
+ {
+ // add OR gate for this frame
+ VarA = Vec_IntEntry( p->vOrLits, f );
+ VarB = pCnfInt->pVarNums[ Aig_ManPo(pCnfInt->pMan, 0)->Id ];
+ Inter_CheckAddOrGate( p, VarA, VarB, p->nVars + pCnfInt->nVars );
+ Vec_IntWriteEntry( p->vOrLits, f, p->nVars + pCnfInt->nVars ); // using var ID!
+ }
+ }
+ else
+ {
+ // add AND gate for this frame
+ VarB = pCnfInt->pVarNums[ Aig_ManPo(pCnfInt->pMan, 0)->Id ];
+ Vec_IntPush( p->vAndLits, VarB );
+ }
+ // update variable IDs
+ Cnf_DataLift( pCnfInt, pCnfInt->nVars + 1 );
+ p->nVars += pCnfInt->nVars + 1;
+ }
+ Cnf_DataLift( pCnfInt, -p->nVars );
+ assert( Vec_IntSize(p->vOrLits) == p->nFramesK );
+
+ // collect the assumption literals
+ Vec_IntClear( p->vAssLits );
+ Vec_IntForEachEntry( p->vOrLits, Entry, i )
+ Vec_IntPush( p->vAssLits, toLitCond(Entry, 0) );
+ Vec_IntForEachEntry( p->vAndLits, Entry, i )
+ Vec_IntPush( p->vAssLits, toLitCond(Entry, 1) );
+/*
+ if ( pCnfInt->nLiterals == 3635 )
+ {
+ int s = 0;
+ }
+*/
+ // call the SAT solver
+ status = sat_solver_solve( p->pSat, Vec_IntArray(p->vAssLits),
+ Vec_IntArray(p->vAssLits) + Vec_IntSize(p->vAssLits),
+ (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+
+ return status == l_False;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/int/intContain.c b/src/proof/int/intContain.c
new file mode 100644
index 00000000..58b408d7
--- /dev/null
+++ b/src/proof/int/intContain.c
@@ -0,0 +1,341 @@
+/**CFile****************************************************************
+
+ FileName [intContain.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Interpolation engine.]
+
+ Synopsis [Interpolant containment checking.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 24, 2008.]
+
+ Revision [$Id: intContain.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "intInt.h"
+#include "src/proof/fra/fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern int Inter_ManCheckUniqueness( Aig_Man_t * p, sat_solver * pSat, Cnf_Dat_t * pCnf, int nFrames );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Checks constainment of two interpolants.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Inter_ManCheckContainment( Aig_Man_t * pNew, Aig_Man_t * pOld )
+{
+ Aig_Man_t * pMiter, * pAigTemp;
+ int RetValue;
+ pMiter = Aig_ManCreateMiter( pNew, pOld, 1 );
+// pMiter = Dar_ManRwsat( pAigTemp = pMiter, 1, 0 );
+// Aig_ManStop( pAigTemp );
+ RetValue = Fra_FraigMiterStatus( pMiter );
+ if ( RetValue == -1 )
+ {
+ pAigTemp = Fra_FraigEquivence( pMiter, 1000000, 1 );
+ RetValue = Fra_FraigMiterStatus( pAigTemp );
+ Aig_ManStop( pAigTemp );
+// RetValue = Fra_FraigSat( pMiter, 1000000, 0, 0, 0, 0 );
+ }
+ assert( RetValue != -1 );
+ Aig_ManStop( pMiter );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks constainment of two interpolants.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Inter_ManCheckEquivalence( Aig_Man_t * pNew, Aig_Man_t * pOld )
+{
+ Aig_Man_t * pMiter, * pAigTemp;
+ int RetValue;
+ pMiter = Aig_ManCreateMiter( pNew, pOld, 0 );
+// pMiter = Dar_ManRwsat( pAigTemp = pMiter, 1, 0 );
+// Aig_ManStop( pAigTemp );
+ RetValue = Fra_FraigMiterStatus( pMiter );
+ if ( RetValue == -1 )
+ {
+ pAigTemp = Fra_FraigEquivence( pMiter, 1000000, 1 );
+ RetValue = Fra_FraigMiterStatus( pAigTemp );
+ Aig_ManStop( pAigTemp );
+// RetValue = Fra_FraigSat( pMiter, 1000000, 0, 0, 0, 0 );
+ }
+ assert( RetValue != -1 );
+ Aig_ManStop( pMiter );
+ return RetValue;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Create timeframes of the manager for interpolation.]
+
+ Description [The resulting manager is combinational. The primary inputs
+ corresponding to register outputs are ordered first.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Inter_ManFramesLatches( Aig_Man_t * pAig, int nFrames, Vec_Ptr_t ** pvMapReg )
+{
+ Aig_Man_t * pFrames;
+ Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+ int i, f;
+ assert( Saig_ManRegNum(pAig) > 0 );
+ pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFrames );
+ // map the constant node
+ Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames );
+ // create variables for register outputs
+ *pvMapReg = Vec_PtrAlloc( (nFrames+1) * Saig_ManRegNum(pAig) );
+ Saig_ManForEachLo( pAig, pObj, i )
+ {
+ pObj->pData = Aig_ObjCreatePi( pFrames );
+ Vec_PtrPush( *pvMapReg, pObj->pData );
+ }
+ // add timeframes
+ for ( f = 0; f < nFrames; f++ )
+ {
+ // create PI nodes for this frame
+ Saig_ManForEachPi( pAig, pObj, i )
+ pObj->pData = Aig_ObjCreatePi( pFrames );
+ // add internal nodes of this frame
+ Aig_ManForEachNode( pAig, pObj, i )
+ pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+ // save register inputs
+ Saig_ManForEachLi( pAig, pObj, i )
+ pObj->pData = Aig_ObjChild0Copy(pObj);
+ // transfer to register outputs
+ Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
+ {
+ pObjLo->pData = pObjLi->pData;
+ Vec_PtrPush( *pvMapReg, pObjLo->pData );
+ }
+ }
+ return pFrames;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates AIG while mapping PIs into the given array.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Inter_ManAppendCone( Aig_Man_t * pOld, Aig_Man_t * pNew, Aig_Obj_t ** ppNewPis, int fCompl )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ assert( Aig_ManPoNum(pOld) == 1 );
+ // create the PIs
+ Aig_ManCleanData( pOld );
+ Aig_ManConst1(pOld)->pData = Aig_ManConst1(pNew);
+ Aig_ManForEachPi( pOld, pObj, i )
+ pObj->pData = ppNewPis[i];
+ // duplicate internal nodes
+ Aig_ManForEachNode( pOld, pObj, i )
+ pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+ // add one PO to new
+ pObj = Aig_ManPo( pOld, 0 );
+ Aig_ObjCreatePo( pNew, Aig_NotCond( Aig_ObjChild0Copy(pObj), fCompl ) );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Checks constainment of two interpolants inductively.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Inter_ManCheckInductiveContainment( Aig_Man_t * pTrans, Aig_Man_t * pInter, int nSteps, int fBackward )
+{
+ Aig_Man_t * pFrames;
+ Aig_Obj_t ** ppNodes;
+ Vec_Ptr_t * vMapRegs;
+ Cnf_Dat_t * pCnf;
+ sat_solver * pSat;
+ int f, nRegs, status;
+ nRegs = Saig_ManRegNum(pTrans);
+ assert( nRegs > 0 );
+ // generate the timeframes
+ pFrames = Inter_ManFramesLatches( pTrans, nSteps, &vMapRegs );
+ assert( Vec_PtrSize(vMapRegs) == (nSteps + 1) * nRegs );
+ // add main constraints to the timeframes
+ ppNodes = (Aig_Obj_t **)Vec_PtrArray(vMapRegs);
+ if ( !fBackward )
+ {
+ // forward inductive check: p -> p -> ... -> !p
+ for ( f = 0; f < nSteps; f++ )
+ Inter_ManAppendCone( pInter, pFrames, ppNodes + f * nRegs, 0 );
+ Inter_ManAppendCone( pInter, pFrames, ppNodes + f * nRegs, 1 );
+ }
+ else
+ {
+ // backward inductive check: p -> !p -> ... -> !p
+ Inter_ManAppendCone( pInter, pFrames, ppNodes + 0 * nRegs, 1 );
+ for ( f = 1; f <= nSteps; f++ )
+ Inter_ManAppendCone( pInter, pFrames, ppNodes + f * nRegs, 0 );
+ }
+ Vec_PtrFree( vMapRegs );
+ Aig_ManCleanup( pFrames );
+
+ // convert to CNF
+ pCnf = Cnf_Derive( pFrames, 0 );
+ pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+// Cnf_DataFree( pCnf );
+// Aig_ManStop( pFrames );
+
+ if ( pSat == NULL )
+ {
+ Cnf_DataFree( pCnf );
+ Aig_ManStop( pFrames );
+ return 1;
+ }
+
+ // solve the problem
+ status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+
+// Inter_ManCheckUniqueness( pTrans, pSat, pCnf, nSteps );
+
+ Cnf_DataFree( pCnf );
+ Aig_ManStop( pFrames );
+
+ sat_solver_delete( pSat );
+ return status == l_False;
+}
+ABC_NAMESPACE_IMPL_END
+
+#include "src/proof/fra/fra.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/**Function*************************************************************
+
+ Synopsis [Check if cex satisfies uniqueness constraints.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Inter_ManCheckUniqueness( Aig_Man_t * p, sat_solver * pSat, Cnf_Dat_t * pCnf, int nFrames )
+{
+ extern int Fra_SmlNodesCompareInFrame( Fra_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1, int iFrame0, int iFrame1 );
+ extern void Fra_SmlAssignConst( Fra_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame );
+ extern void Fra_SmlSimulateOne( Fra_Sml_t * p );
+
+ Fra_Sml_t * pSml;
+ Vec_Int_t * vPis;
+ Aig_Obj_t * pObj, * pObj0;
+ int i, k, v, iBit, * pCounterEx;
+ int Counter;
+ if ( nFrames == 1 )
+ return 1;
+// if ( pSat->model.size == 0 )
+
+ // possible consequences here!!!
+ assert( 0 );
+
+ if ( sat_solver_nvars(pSat) == 0 )
+ return 1;
+// assert( Saig_ManPoNum(p) == 1 );
+ assert( Aig_ManRegNum(p) > 0 );
+ assert( Aig_ManRegNum(p) < Aig_ManPiNum(p) );
+
+ // get the counter-example
+ vPis = Vec_IntAlloc( 100 );
+ Aig_ManForEachPi( pCnf->pMan, pObj, k )
+ Vec_IntPush( vPis, pCnf->pVarNums[Aig_ObjId(pObj)] );
+ assert( Vec_IntSize(vPis) == Aig_ManRegNum(p) + nFrames * Saig_ManPiNum(p) );
+ pCounterEx = Sat_SolverGetModel( pSat, vPis->pArray, vPis->nSize );
+ Vec_IntFree( vPis );
+
+ // start a new sequential simulator
+ pSml = Fra_SmlStart( p, 0, nFrames, 1 );
+ // assign simulation info for the registers
+ iBit = 0;
+ Aig_ManForEachLoSeq( p, pObj, i )
+ Fra_SmlAssignConst( pSml, pObj, pCounterEx[iBit++], 0 );
+ // assign simulation info for the primary inputs
+ for ( i = 0; i < nFrames; i++ )
+ Aig_ManForEachPiSeq( p, pObj, k )
+ Fra_SmlAssignConst( pSml, pObj, pCounterEx[iBit++], i );
+ assert( iBit == Aig_ManPiNum(pCnf->pMan) );
+ // run simulation
+ Fra_SmlSimulateOne( pSml );
+
+ // check if the given output has failed
+// RetValue = !Fra_SmlNodeIsZero( pSml, Aig_ManPo(pAig, 0) );
+// assert( RetValue );
+
+ // check values at the internal nodes
+ Counter = 0;
+ for ( i = 0; i < nFrames; i++ )
+ for ( k = i+1; k < nFrames; k++ )
+ {
+ for ( v = 0; v < Aig_ManRegNum(p); v++ )
+ {
+ pObj0 = Aig_ManLo(p, v);
+ if ( !Fra_SmlNodesCompareInFrame( pSml, pObj0, pObj0, i, k ) )
+ break;
+ }
+ if ( v == Aig_ManRegNum(p) )
+ Counter++;
+ }
+ printf( "Uniquness does not hold in %d frames.\n", Counter );
+
+ Fra_SmlStop( pSml );
+ ABC_FREE( pCounterEx );
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/int/intCore.c b/src/proof/int/intCore.c
new file mode 100644
index 00000000..3bd111be
--- /dev/null
+++ b/src/proof/int/intCore.c
@@ -0,0 +1,389 @@
+/**CFile****************************************************************
+
+ FileName [intCore.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Interpolation engine.]
+
+ Synopsis [Core procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 24, 2008.]
+
+ Revision [$Id: intCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "intInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [This procedure sets default values of interpolation parameters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Inter_ManSetDefaultParams( Inter_ManParams_t * p )
+{
+ memset( p, 0, sizeof(Inter_ManParams_t) );
+ p->nBTLimit = 10000; // limit on the number of conflicts
+ p->nFramesMax = 40; // the max number timeframes to unroll
+ p->nSecLimit = 0; // time limit in seconds
+ p->nFramesK = 1; // the number of timeframes to use in induction
+ p->fRewrite = 0; // use additional rewriting to simplify timeframes
+ p->fTransLoop = 0; // add transition into the init state under new PI var
+ p->fUsePudlak = 0; // use Pudluk interpolation procedure
+ p->fUseOther = 0; // use other undisclosed option
+ p->fUseMiniSat = 0; // use MiniSat-1.14p instead of internal proof engine
+ p->fCheckKstep = 1; // check using K-step induction
+ p->fUseBias = 0; // bias decisions to global variables
+ p->fUseBackward = 0; // perform backward interpolation
+ p->fUseSeparate = 0; // solve each output separately
+ p->fDropSatOuts = 0; // replace by 1 the solved outputs
+ p->fVerbose = 0; // print verbose statistics
+ p->iFrameMax =-1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Interplates while the number of conflicts is not exceeded.]
+
+ Description [Returns 1 if proven. 0 if failed. -1 if undecided.]
+
+ SideEffects [Does not check the property in 0-th frame.]
+
+ SeeAlso []
+
+***********************************************************************/
+int Inter_ManPerformInterpolation( Aig_Man_t * pAig, Inter_ManParams_t * pPars, int * piFrame )
+{
+ extern int Inter_ManCheckInductiveContainment( Aig_Man_t * pTrans, Aig_Man_t * pInter, int nSteps, int fBackward );
+ Inter_Man_t * p;
+ Inter_Check_t * pCheck = NULL;
+ Aig_Man_t * pAigTemp;
+ int s, i, RetValue, Status, clk, clk2, clkTotal = clock(), timeTemp;
+ int nTimeNewOut = pPars->nSecLimit ? time(NULL) + pPars->nSecLimit : 0;
+
+ // sanity checks
+ assert( Saig_ManRegNum(pAig) > 0 );
+ assert( Saig_ManPiNum(pAig) > 0 );
+ assert( Saig_ManPoNum(pAig)-Saig_ManConstrNum(pAig) == 1 );
+ if ( pPars->fVerbose && Saig_ManConstrNum(pAig) )
+ printf( "Performing interpolation with %d constraints...\n", Saig_ManConstrNum(pAig) );
+
+ if ( Inter_ManCheckInitialState(pAig) )
+ {
+ *piFrame = 0;
+ printf( "Property trivially fails in the initial state.\n" );
+ return 0;
+ }
+/*
+ if ( Inter_ManCheckAllStates(pAig) )
+ {
+ printf( "Property trivially holds in all states.\n" );
+ return 1;
+ }
+*/
+ // create interpolation manager
+ // can perform SAT sweeping and/or rewriting of this AIG...
+ p = Inter_ManCreate( pAig, pPars );
+ if ( pPars->fTransLoop )
+ p->pAigTrans = Inter_ManStartOneOutput( pAig, 0 );
+ else
+ p->pAigTrans = Inter_ManStartDuplicated( pAig );
+ // derive CNF for the transformed AIG
+clk = clock();
+ p->pCnfAig = Cnf_Derive( p->pAigTrans, Aig_ManRegNum(p->pAigTrans) );
+p->timeCnf += clock() - clk;
+ if ( pPars->fVerbose )
+ {
+ printf( "AIG: PI/PO/Reg = %d/%d/%d. And = %d. Lev = %d. CNF: Var/Cla = %d/%d.\n",
+ Saig_ManPiNum(pAig), Saig_ManPoNum(pAig), Saig_ManRegNum(pAig),
+ Aig_ManAndNum(pAig), Aig_ManLevelNum(pAig),
+ p->pCnfAig->nVars, p->pCnfAig->nClauses );
+ }
+
+ // derive interpolant
+ *piFrame = -1;
+ p->nFrames = 1;
+ for ( s = 0; ; s++ )
+ {
+ Cnf_Dat_t * pCnfInter2;
+
+clk2 = clock();
+ // initial state
+ if ( pPars->fUseBackward )
+ p->pInter = Inter_ManStartOneOutput( pAig, 1 );
+ else
+ p->pInter = Inter_ManStartInitState( Aig_ManRegNum(pAig) );
+ assert( Aig_ManPoNum(p->pInter) == 1 );
+clk = clock();
+ p->pCnfInter = Cnf_Derive( p->pInter, 0 );
+p->timeCnf += clock() - clk;
+ // timeframes
+ p->pFrames = Inter_ManFramesInter( pAig, p->nFrames, pPars->fUseBackward );
+clk = clock();
+ if ( pPars->fRewrite )
+ {
+ p->pFrames = Dar_ManRwsat( pAigTemp = p->pFrames, 1, 0 );
+ Aig_ManStop( pAigTemp );
+// p->pFrames = Fra_FraigEquivence( pAigTemp = p->pFrames, 100, 0 );
+// Aig_ManStop( pAigTemp );
+ }
+p->timeRwr += clock() - clk;
+ // can also do SAT sweeping on the timeframes...
+clk = clock();
+ if ( pPars->fUseBackward )
+ p->pCnfFrames = Cnf_Derive( p->pFrames, Aig_ManPoNum(p->pFrames) );
+ else
+// p->pCnfFrames = Cnf_Derive( p->pFrames, 0 );
+ p->pCnfFrames = Cnf_DeriveSimple( p->pFrames, 0 );
+p->timeCnf += clock() - clk;
+ // report statistics
+ if ( pPars->fVerbose )
+ {
+ printf( "Step = %2d. Frames = 1 + %d. And = %5d. Lev = %5d. ",
+ s+1, p->nFrames, Aig_ManNodeNum(p->pFrames), Aig_ManLevelNum(p->pFrames) );
+ ABC_PRT( "Time", clock() - clk2 );
+ }
+
+
+ //////////////////////////////////////////
+ // start containment checking
+ if ( !(pPars->fTransLoop || pPars->fUseBackward) )
+ {
+ pCheck = Inter_CheckStart( p->pAigTrans, pPars->nFramesK );
+ // try new containment check for the initial state
+clk = clock();
+ pCnfInter2 = Cnf_Derive( p->pInter, 1 );
+p->timeCnf += clock() - clk;
+ RetValue = Inter_CheckPerform( pCheck, pCnfInter2, nTimeNewOut );
+// assert( RetValue == 0 );
+ Cnf_DataFree( pCnfInter2 );
+ if ( p->vInters )
+ Vec_PtrPush( p->vInters, Aig_ManDupSimple(p->pInter) );
+ }
+ //////////////////////////////////////////
+
+ // iterate the interpolation procedure
+ for ( i = 0; ; i++ )
+ {
+ if ( p->nFrames + i >= pPars->nFramesMax )
+ {
+ if ( pPars->fVerbose )
+ printf( "Reached limit (%d) on the number of timeframes.\n", pPars->nFramesMax );
+ p->timeTotal = clock() - clkTotal;
+ Inter_ManStop( p, 0 );
+ Inter_CheckStop( pCheck );
+ return -1;
+ }
+
+ // perform interpolation
+ clk = clock();
+#ifdef ABC_USE_LIBRARIES
+ if ( pPars->fUseMiniSat )
+ {
+ assert( !pPars->fUseBackward );
+ RetValue = Inter_ManPerformOneStepM114p( p, pPars->fUsePudlak, pPars->fUseOther );
+ }
+ else
+#endif
+ RetValue = Inter_ManPerformOneStep( p, pPars->fUseBias, pPars->fUseBackward, nTimeNewOut );
+
+ if ( pPars->fVerbose )
+ {
+ printf( " I = %2d. Bmc =%3d. IntAnd =%6d. IntLev =%5d. Conf =%6d. ",
+ i+1, i + 1 + p->nFrames, Aig_ManNodeNum(p->pInter), Aig_ManLevelNum(p->pInter), p->nConfCur );
+ ABC_PRT( "Time", clock() - clk );
+ }
+ // remember the number of timeframes completed
+ pPars->iFrameMax = i + 1 + p->nFrames;
+ if ( RetValue == 0 ) // found a (spurious?) counter-example
+ {
+ if ( i == 0 ) // real counterexample
+ {
+ if ( pPars->fVerbose )
+ printf( "Found a real counterexample in frame %d.\n", p->nFrames );
+ p->timeTotal = clock() - clkTotal;
+ *piFrame = p->nFrames;
+// pAig->pSeqModel = (Abc_Cex_t *)Inter_ManGetCounterExample( pAig, p->nFrames+1, pPars->fVerbose );
+ {
+ int RetValue;
+ Saig_ParBmc_t ParsBmc, * pParsBmc = &ParsBmc;
+ Saig_ParBmcSetDefaultParams( pParsBmc );
+ pParsBmc->nConfLimit = 100000000;
+ pParsBmc->nStart = p->nFrames;
+ pParsBmc->fVerbose = pPars->fVerbose;
+ RetValue = Saig_ManBmcScalable( pAig, pParsBmc );
+ if ( RetValue == 1 )
+ printf( "Error: The problem should be SAT but it is UNSAT.\n" );
+ else if ( RetValue == -1 )
+ printf( "Error: The problem timed out.\n" );
+ }
+ Inter_ManStop( p, 0 );
+ Inter_CheckStop( pCheck );
+ return 0;
+ }
+ // likely spurious counter-example
+ p->nFrames += i;
+ Inter_ManClean( p );
+ break;
+ }
+ else if ( RetValue == -1 )
+ {
+ if ( pPars->nSecLimit && time(NULL) > nTimeNewOut ) // timed out
+ {
+ if ( pPars->fVerbose )
+ printf( "Reached timeout (%d seconds).\n", pPars->nSecLimit );
+ }
+ else
+ {
+ assert( p->nConfCur >= p->nConfLimit );
+ if ( pPars->fVerbose )
+ printf( "Reached limit (%d) on the number of conflicts.\n", p->nConfLimit );
+ }
+ p->timeTotal = clock() - clkTotal;
+ Inter_ManStop( p, 0 );
+ Inter_CheckStop( pCheck );
+ return -1;
+ }
+ assert( RetValue == 1 ); // found new interpolant
+ // compress the interpolant
+clk = clock();
+ if ( p->pInterNew )
+ {
+// Ioa_WriteAiger( p->pInterNew, "interpol.aig", 0, 0 );
+ p->pInterNew = Dar_ManRwsat( pAigTemp = p->pInterNew, 1, 0 );
+// p->pInterNew = Dar_ManRwsat( pAigTemp = p->pInterNew, 0, 0 );
+ Aig_ManStop( pAigTemp );
+ }
+p->timeRwr += clock() - clk;
+
+ // check if interpolant is trivial
+ if ( p->pInterNew == NULL || Aig_ObjChild0(Aig_ManPo(p->pInterNew,0)) == Aig_ManConst0(p->pInterNew) )
+ {
+// printf( "interpolant is constant 0\n" );
+ if ( pPars->fVerbose )
+ printf( "The problem is trivially true for all states.\n" );
+ p->timeTotal = clock() - clkTotal;
+ Inter_ManStop( p, 1 );
+ Inter_CheckStop( pCheck );
+ return 1;
+ }
+
+ // check containment of interpolants
+clk = clock();
+ if ( pPars->fCheckKstep ) // k-step unique-state induction
+ {
+ if ( Aig_ManPiNum(p->pInterNew) == Aig_ManPiNum(p->pInter) )
+ {
+ if ( pPars->fTransLoop || pPars->fUseBackward )
+ Status = Inter_ManCheckInductiveContainment( p->pAigTrans, p->pInterNew, pPars->nFramesK, pPars->fUseBackward );
+ else
+ { // new containment check
+clk2 = clock();
+ pCnfInter2 = Cnf_Derive( p->pInterNew, 1 );
+p->timeCnf += clock() - clk2;
+timeTemp = clock() - clk2;
+
+ Status = Inter_CheckPerform( pCheck, pCnfInter2, nTimeNewOut );
+ Cnf_DataFree( pCnfInter2 );
+ if ( p->vInters )
+ Vec_PtrPush( p->vInters, Aig_ManDupSimple(p->pInterNew) );
+ }
+ }
+ else
+ Status = 0;
+ }
+ else // combinational containment
+ {
+ if ( Aig_ManPiNum(p->pInterNew) == Aig_ManPiNum(p->pInter) )
+ Status = Inter_ManCheckContainment( p->pInterNew, p->pInter );
+ else
+ Status = 0;
+ }
+p->timeEqu += clock() - clk - timeTemp;
+ if ( Status ) // contained
+ {
+ if ( pPars->fVerbose )
+ printf( "Proved containment of interpolants.\n" );
+ p->timeTotal = clock() - clkTotal;
+ Inter_ManStop( p, 1 );
+ Inter_CheckStop( pCheck );
+ return 1;
+ }
+ if ( pPars->nSecLimit && time(NULL) > nTimeNewOut )
+ {
+ printf( "Reached timeout (%d seconds).\n", pPars->nSecLimit );
+ p->timeTotal = clock() - clkTotal;
+ Inter_ManStop( p, 1 );
+ Inter_CheckStop( pCheck );
+ return -1;
+ }
+ // save interpolant and convert it into CNF
+ if ( pPars->fTransLoop )
+ {
+ Aig_ManStop( p->pInter );
+ p->pInter = p->pInterNew;
+ }
+ else
+ {
+ if ( pPars->fUseBackward )
+ {
+ p->pInter = Aig_ManCreateMiter( pAigTemp = p->pInter, p->pInterNew, 2 );
+ Aig_ManStop( pAigTemp );
+ Aig_ManStop( p->pInterNew );
+ // compress the interpolant
+clk = clock();
+ p->pInter = Dar_ManRwsat( pAigTemp = p->pInter, 1, 0 );
+ Aig_ManStop( pAigTemp );
+p->timeRwr += clock() - clk;
+ }
+ else // forward with the new containment checking (using only the frontier)
+ {
+ Aig_ManStop( p->pInter );
+ p->pInter = p->pInterNew;
+ }
+ }
+ p->pInterNew = NULL;
+ Cnf_DataFree( p->pCnfInter );
+clk = clock();
+ p->pCnfInter = Cnf_Derive( p->pInter, 0 );
+p->timeCnf += clock() - clk;
+ }
+
+ // start containment checking
+ Inter_CheckStop( pCheck );
+ }
+ assert( 0 );
+ return RetValue;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/int/intCtrex.c b/src/proof/int/intCtrex.c
new file mode 100644
index 00000000..9ba8c9df
--- /dev/null
+++ b/src/proof/int/intCtrex.c
@@ -0,0 +1,167 @@
+/**CFile****************************************************************
+
+ FileName [intCtrex.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Interpolation engine.]
+
+ Synopsis [Counter-example generation after disproving the property.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 24, 2008.]
+
+ Revision [$Id: intCtrex.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "intInt.h"
+#include "src/proof/ssw/ssw.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Unroll the circuit the given number of timeframes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Inter_ManFramesBmc( Aig_Man_t * pAig, int nFrames )
+{
+ Aig_Man_t * pFrames;
+ Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+ int i, f;
+ assert( Saig_ManRegNum(pAig) > 0 );
+ assert( Saig_ManPoNum(pAig) == 1 );
+ pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFrames );
+ // map the constant node
+ Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames );
+ // create variables for register outputs
+ Saig_ManForEachLo( pAig, pObj, i )
+ pObj->pData = Aig_ManConst0( pFrames );
+ // add timeframes
+ for ( f = 0; f < nFrames; f++ )
+ {
+ // create PI nodes for this frame
+ Saig_ManForEachPi( pAig, pObj, i )
+ pObj->pData = Aig_ObjCreatePi( pFrames );
+ // add internal nodes of this frame
+ Aig_ManForEachNode( pAig, pObj, i )
+ pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+ if ( f == nFrames - 1 )
+ break;
+ // transfer to register outputs
+ Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
+ pObjLi->pData = Aig_ObjChild0Copy(pObjLi);
+ // transfer to register outputs
+ Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
+ pObjLo->pData = pObjLi->pData;
+ }
+ // create POs for the output of the last frame
+ pObj = Aig_ManPo( pAig, 0 );
+ Aig_ObjCreatePo( pFrames, Aig_ObjChild0Copy(pObj) );
+ Aig_ManCleanup( pFrames );
+ return pFrames;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Run the SAT solver on the unrolled instance.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void * Inter_ManGetCounterExample( Aig_Man_t * pAig, int nFrames, int fVerbose )
+{
+ int nConfLimit = 1000000;
+ Abc_Cex_t * pCtrex = NULL;
+ Aig_Man_t * pFrames;
+ sat_solver * pSat;
+ Cnf_Dat_t * pCnf;
+ int status, clk = clock();
+ Vec_Int_t * vCiIds;
+ // create timeframes
+ assert( Saig_ManPoNum(pAig) == 1 );
+ pFrames = Inter_ManFramesBmc( pAig, nFrames );
+ // derive CNF
+ pCnf = Cnf_Derive( pFrames, 0 );
+ Cnf_DataTranformPolarity( pCnf, 0 );
+ vCiIds = Cnf_DataCollectPiSatNums( pCnf, pFrames );
+ Aig_ManStop( pFrames );
+ // convert into SAT solver
+ pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+ Cnf_DataFree( pCnf );
+ if ( pSat == NULL )
+ {
+ printf( "Counter-example generation in command \"int\" has failed.\n" );
+ printf( "Use command \"bmc2\" to produce a valid counter-example.\n" );
+ Vec_IntFree( vCiIds );
+ return NULL;
+ }
+ // simplify the problem
+ status = sat_solver_simplify(pSat);
+ if ( status == 0 )
+ {
+ Vec_IntFree( vCiIds );
+ sat_solver_delete( pSat );
+ return NULL;
+ }
+ // solve the miter
+ status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+ // if the problem is SAT, get the counterexample
+ if ( status == l_True )
+ {
+ int i, * pModel = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize );
+ pCtrex = Abc_CexAlloc( Saig_ManRegNum(pAig), Saig_ManPiNum(pAig), nFrames );
+ pCtrex->iFrame = nFrames - 1;
+ pCtrex->iPo = 0;
+ for ( i = 0; i < Vec_IntSize(vCiIds); i++ )
+ if ( pModel[i] )
+ Abc_InfoSetBit( pCtrex->pData, Saig_ManRegNum(pAig) + i );
+ ABC_FREE( pModel );
+ }
+ // free the sat_solver
+ sat_solver_delete( pSat );
+ Vec_IntFree( vCiIds );
+ // verify counter-example
+ status = Saig_ManVerifyCex( pAig, pCtrex );
+ if ( status == 0 )
+ printf( "Inter_ManGetCounterExample(): Counter-example verification has FAILED.\n" );
+ // report the results
+ if ( fVerbose )
+ {
+ ABC_PRT( "Total ctrex generation time", clock() - clk );
+ }
+ return pCtrex;
+
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/int/intDup.c b/src/proof/int/intDup.c
new file mode 100644
index 00000000..551473ef
--- /dev/null
+++ b/src/proof/int/intDup.c
@@ -0,0 +1,184 @@
+/**CFile****************************************************************
+
+ FileName [intDup.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Interpolation engine.]
+
+ Synopsis [Specialized AIG duplication procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 24, 2008.]
+
+ Revision [$Id: intDup.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "intInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Create trivial AIG manager for the init state.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Inter_ManStartInitState( int nRegs )
+{
+ Aig_Man_t * p;
+ Aig_Obj_t * pRes;
+ Aig_Obj_t ** ppInputs;
+ int i;
+ assert( nRegs > 0 );
+ ppInputs = ABC_ALLOC( Aig_Obj_t *, nRegs );
+ p = Aig_ManStart( nRegs );
+ for ( i = 0; i < nRegs; i++ )
+ ppInputs[i] = Aig_Not( Aig_ObjCreatePi(p) );
+ pRes = Aig_Multi( p, ppInputs, nRegs, AIG_OBJ_AND );
+ Aig_ObjCreatePo( p, pRes );
+ ABC_FREE( ppInputs );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicate the AIG w/o POs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Inter_ManStartDuplicated( Aig_Man_t * p )
+{
+ Aig_Man_t * pNew;
+ Aig_Obj_t * pObj;
+ int i;
+ assert( Aig_ManRegNum(p) > 0 );
+ // create the new manager
+ pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+ pNew->pName = Abc_UtilStrsav( p->pName );
+ pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+ // create the PIs
+ Aig_ManCleanData( p );
+ Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+ Aig_ManForEachPi( p, pObj, i )
+ pObj->pData = Aig_ObjCreatePi( pNew );
+ // set registers
+ pNew->nTruePis = p->nTruePis;
+ pNew->nTruePos = Saig_ManConstrNum(p);
+ pNew->nRegs = p->nRegs;
+ // duplicate internal nodes
+ Aig_ManForEachNode( p, pObj, i )
+ pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+
+ // create constraint outputs
+ Saig_ManForEachPo( p, pObj, i )
+ {
+ if ( i < Saig_ManPoNum(p)-Saig_ManConstrNum(p) )
+ continue;
+ Aig_ObjCreatePo( pNew, Aig_Not( Aig_ObjChild0Copy(pObj) ) );
+ }
+
+ // create register inputs with MUXes
+ Saig_ManForEachLi( p, pObj, i )
+ Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) );
+ Aig_ManCleanup( pNew );
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicate the AIG w/o POs and transforms to transit into init state.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Inter_ManStartOneOutput( Aig_Man_t * p, int fAddFirstPo )
+{
+ Aig_Man_t * pNew;
+ Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+ Aig_Obj_t * pCtrl = NULL; // Suppress "might be used uninitialized"
+ int i;
+ assert( Aig_ManRegNum(p) > 0 );
+ // create the new manager
+ pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
+ pNew->pName = Abc_UtilStrsav( p->pName );
+ pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+ // create the PIs
+ Aig_ManCleanData( p );
+ Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
+ Aig_ManForEachPi( p, pObj, i )
+ {
+ if ( i == Saig_ManPiNum(p) )
+ pCtrl = Aig_ObjCreatePi( pNew );
+ pObj->pData = Aig_ObjCreatePi( pNew );
+ }
+ // set registers
+ pNew->nRegs = fAddFirstPo? 0 : p->nRegs;
+ pNew->nTruePis = fAddFirstPo? Aig_ManPiNum(p) + 1 : p->nTruePis + 1;
+ pNew->nTruePos = fAddFirstPo + Saig_ManConstrNum(p);
+ // duplicate internal nodes
+ Aig_ManForEachNode( p, pObj, i )
+ pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+
+ // create constraint outputs
+ Saig_ManForEachPo( p, pObj, i )
+ {
+ if ( i < Saig_ManPoNum(p)-Saig_ManConstrNum(p) )
+ continue;
+ Aig_ObjCreatePo( pNew, Aig_Not( Aig_ObjChild0Copy(pObj) ) );
+ }
+
+ // add the PO
+ if ( fAddFirstPo )
+ {
+ pObj = Aig_ManPo( p, 0 );
+ Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) );
+ }
+ else
+ {
+ // create register inputs with MUXes
+ Saig_ManForEachLiLo( p, pObjLi, pObjLo, i )
+ {
+ pObj = Aig_Mux( pNew, pCtrl, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) );
+ // pObj = Aig_Mux( pNew, pCtrl, Aig_ManConst0(pNew), Aig_ObjChild0Copy(pObjLi) );
+ Aig_ObjCreatePo( pNew, pObj );
+ }
+ }
+ Aig_ManCleanup( pNew );
+ return pNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/int/intFrames.c b/src/proof/int/intFrames.c
new file mode 100644
index 00000000..0fbab6cb
--- /dev/null
+++ b/src/proof/int/intFrames.c
@@ -0,0 +1,115 @@
+/**CFile****************************************************************
+
+ FileName [intFrames.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Interpolation engine.]
+
+ Synopsis [Sequential AIG unrolling for interpolation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 24, 2008.]
+
+ Revision [$Id: intFrames.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "intInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Create timeframes of the manager for interpolation.]
+
+ Description [The resulting manager is combinational. The primary inputs
+ corresponding to register outputs are ordered first. The only POs of the
+ manager is the property output of the last timeframe.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Inter_ManFramesInter( Aig_Man_t * pAig, int nFrames, int fAddRegOuts )
+{
+ Aig_Man_t * pFrames;
+ Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+ int i, f;
+ assert( Saig_ManRegNum(pAig) > 0 );
+ assert( Saig_ManPoNum(pAig)-Saig_ManConstrNum(pAig) == 1 );
+ pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFrames );
+ // map the constant node
+ Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames );
+ // create variables for register outputs
+ if ( fAddRegOuts )
+ {
+ Saig_ManForEachLo( pAig, pObj, i )
+ pObj->pData = Aig_ManConst0( pFrames );
+ }
+ else
+ {
+ Saig_ManForEachLo( pAig, pObj, i )
+ pObj->pData = Aig_ObjCreatePi( pFrames );
+ }
+ // add timeframes
+ for ( f = 0; f < nFrames; f++ )
+ {
+ // create PI nodes for this frame
+ Saig_ManForEachPi( pAig, pObj, i )
+ pObj->pData = Aig_ObjCreatePi( pFrames );
+ // add internal nodes of this frame
+ Aig_ManForEachNode( pAig, pObj, i )
+ pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+ // add outputs for constraints
+ Saig_ManForEachPo( pAig, pObj, i )
+ {
+ if ( i < Saig_ManPoNum(pAig)-Saig_ManConstrNum(pAig) )
+ continue;
+ Aig_ObjCreatePo( pFrames, Aig_Not( Aig_ObjChild0Copy(pObj) ) );
+ }
+ if ( f == nFrames - 1 )
+ break;
+ // save register inputs
+ Saig_ManForEachLi( pAig, pObj, i )
+ pObj->pData = Aig_ObjChild0Copy(pObj);
+ // transfer to register outputs
+ Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
+ pObjLo->pData = pObjLi->pData;
+ }
+ // create POs for each register output
+ if ( fAddRegOuts )
+ {
+ Saig_ManForEachLi( pAig, pObj, i )
+ Aig_ObjCreatePo( pFrames, Aig_ObjChild0Copy(pObj) );
+ }
+ // create the only PO of the manager
+ else
+ {
+ pObj = Aig_ManPo( pAig, 0 );
+ Aig_ObjCreatePo( pFrames, Aig_ObjChild0Copy(pObj) );
+ }
+ Aig_ManCleanup( pFrames );
+ return pFrames;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/int/intInt.h b/src/proof/int/intInt.h
new file mode 100644
index 00000000..6a033d85
--- /dev/null
+++ b/src/proof/int/intInt.h
@@ -0,0 +1,142 @@
+/**CFile****************************************************************
+
+ FileName [intInt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Interpolation engine.]
+
+ Synopsis [Internal declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 24, 2008.]
+
+ Revision [$Id: intInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__int__intInt_h
+#define ABC__aig__int__intInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include "src/aig/saig/saig.h"
+#include "src/sat/cnf/cnf.h"
+#include "src/sat/bsat/satSolver.h"
+#include "src/sat/bsat/satStore.h"
+#include "int.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+// interpolation manager
+typedef struct Inter_Man_t_ Inter_Man_t;
+struct Inter_Man_t_
+{
+ // AIG manager
+ Aig_Man_t * pAig; // the original AIG manager
+ Aig_Man_t * pAigTrans; // the transformed original AIG manager
+ Cnf_Dat_t * pCnfAig; // CNF for the original manager
+ // interpolant
+ Aig_Man_t * pInter; // the current interpolant
+ Cnf_Dat_t * pCnfInter; // CNF for the current interplant
+ // timeframes
+ Aig_Man_t * pFrames; // the timeframes
+ Cnf_Dat_t * pCnfFrames; // CNF for the timeframes
+ // other data
+ Vec_Int_t * vVarsAB; // the variables participating in
+ // temporary place for the new interpolant
+ Aig_Man_t * pInterNew;
+ Vec_Ptr_t * vInters;
+ // parameters
+ int nFrames; // the number of timeframes
+ int nConfCur; // the current number of conflicts
+ int nConfLimit; // the limit on the number of conflicts
+ int fVerbose; // the verbosiness flag
+ // runtime
+ int timeRwr;
+ int timeCnf;
+ int timeSat;
+ int timeInt;
+ int timeEqu;
+ int timeOther;
+ int timeTotal;
+};
+
+// containment checking manager
+typedef struct Inter_Check_t_ Inter_Check_t;
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== intCheck.c ============================================================*/
+extern Inter_Check_t * Inter_CheckStart( Aig_Man_t * pTrans, int nFramesK );
+extern void Inter_CheckStop( Inter_Check_t * p );
+extern int Inter_CheckPerform( Inter_Check_t * p, Cnf_Dat_t * pCnf, int nTimeNewOut );
+
+/*=== intContain.c ============================================================*/
+extern int Inter_ManCheckContainment( Aig_Man_t * pNew, Aig_Man_t * pOld );
+extern int Inter_ManCheckEquivalence( Aig_Man_t * pNew, Aig_Man_t * pOld );
+extern int Inter_ManCheckInductiveContainment( Aig_Man_t * pTrans, Aig_Man_t * pInter, int nSteps, int fBackward );
+
+/*=== intCtrex.c ============================================================*/
+extern void * Inter_ManGetCounterExample( Aig_Man_t * pAig, int nFrames, int fVerbose );
+
+/*=== intDup.c ============================================================*/
+extern Aig_Man_t * Inter_ManStartInitState( int nRegs );
+extern Aig_Man_t * Inter_ManStartDuplicated( Aig_Man_t * p );
+extern Aig_Man_t * Inter_ManStartOneOutput( Aig_Man_t * p, int fAddFirstPo );
+
+/*=== intFrames.c ============================================================*/
+extern Aig_Man_t * Inter_ManFramesInter( Aig_Man_t * pAig, int nFrames, int fAddRegOuts );
+
+/*=== intMan.c ============================================================*/
+extern Inter_Man_t * Inter_ManCreate( Aig_Man_t * pAig, Inter_ManParams_t * pPars );
+extern void Inter_ManClean( Inter_Man_t * p );
+extern void Inter_ManStop( Inter_Man_t * p, int fProved );
+
+/*=== intM114.c ============================================================*/
+extern int Inter_ManPerformOneStep( Inter_Man_t * p, int fUseBias, int fUseBackward, int nTimeNewOut );
+
+/*=== intM114p.c ============================================================*/
+#ifdef ABC_USE_LIBRARIES
+extern int Inter_ManPerformOneStepM114p( Inter_Man_t * p, int fUsePudlak, int fUseOther );
+#endif
+
+/*=== intUtil.c ============================================================*/
+extern int Inter_ManCheckInitialState( Aig_Man_t * p );
+extern int Inter_ManCheckAllStates( Aig_Man_t * p );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/proof/int/intInter.c b/src/proof/int/intInter.c
new file mode 100644
index 00000000..ef32294b
--- /dev/null
+++ b/src/proof/int/intInter.c
@@ -0,0 +1,145 @@
+/**CFile****************************************************************
+
+ FileName [intInter.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Interpolation engine.]
+
+ Synopsis [Experimental procedures to derive and compare interpolants.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 24, 2008.]
+
+ Revision [$Id: intInter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "intInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Inter_ManDupExpand( Aig_Man_t * pInter, Aig_Man_t * pOther )
+{
+ Aig_Man_t * pInterC;
+ assert( Aig_ManPiNum(pInter) <= Aig_ManPiNum(pOther) );
+ pInterC = Aig_ManDupSimple( pInter );
+ Aig_IthVar( pInterC, Aig_ManPiNum(pOther)-1 );
+ assert( Aig_ManPiNum(pInterC) == Aig_ManPiNum(pOther) );
+ return pInterC;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Inter_ManVerifyInterpolant1( Inta_Man_t * pMan, Sto_Man_t * pCnf, Aig_Man_t * pInter )
+{
+ extern Aig_Man_t * Inta_ManDeriveClauses( Inta_Man_t * pMan, Sto_Man_t * pCnf, int fClausesA );
+ Aig_Man_t * pLower, * pUpper, * pInterC;
+ int RetValue1, RetValue2;
+
+ pLower = Inta_ManDeriveClauses( pMan, pCnf, 1 );
+ pUpper = Inta_ManDeriveClauses( pMan, pCnf, 0 );
+ Aig_ManFlipFirstPo( pUpper );
+
+ pInterC = Inter_ManDupExpand( pInter, pLower );
+ RetValue1 = Inter_ManCheckContainment( pLower, pInterC );
+ Aig_ManStop( pInterC );
+
+ pInterC = Inter_ManDupExpand( pInter, pUpper );
+ RetValue2 = Inter_ManCheckContainment( pInterC, pUpper );
+ Aig_ManStop( pInterC );
+
+ if ( RetValue1 && RetValue2 )
+ printf( "Im is correct.\n" );
+ if ( !RetValue1 )
+ printf( "Property A => Im fails.\n" );
+ if ( !RetValue2 )
+ printf( "Property Im => !B fails.\n" );
+
+ Aig_ManStop( pLower );
+ Aig_ManStop( pUpper );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Inter_ManVerifyInterpolant2( Intb_Man_t * pMan, Sto_Man_t * pCnf, Aig_Man_t * pInter )
+{
+ extern Aig_Man_t * Intb_ManDeriveClauses( Intb_Man_t * pMan, Sto_Man_t * pCnf, int fClausesA );
+ Aig_Man_t * pLower, * pUpper, * pInterC;
+ int RetValue1, RetValue2;
+
+ pLower = Intb_ManDeriveClauses( pMan, pCnf, 1 );
+ pUpper = Intb_ManDeriveClauses( pMan, pCnf, 0 );
+ Aig_ManFlipFirstPo( pUpper );
+
+ pInterC = Inter_ManDupExpand( pInter, pLower );
+//Aig_ManPrintStats( pLower );
+//Aig_ManPrintStats( pUpper );
+//Aig_ManPrintStats( pInterC );
+//Aig_ManDumpBlif( pInterC, "inter_c.blif", NULL, NULL );
+ RetValue1 = Inter_ManCheckContainment( pLower, pInterC );
+ Aig_ManStop( pInterC );
+
+ pInterC = Inter_ManDupExpand( pInter, pUpper );
+ RetValue2 = Inter_ManCheckContainment( pInterC, pUpper );
+ Aig_ManStop( pInterC );
+
+ if ( RetValue1 && RetValue2 )
+ printf( "Ip is correct.\n" );
+ if ( !RetValue1 )
+ printf( "Property A => Ip fails.\n" );
+ if ( !RetValue2 )
+ printf( "Property Ip => !B fails.\n" );
+
+ Aig_ManStop( pLower );
+ Aig_ManStop( pUpper );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/int/intM114.c b/src/proof/int/intM114.c
new file mode 100644
index 00000000..139c9bbd
--- /dev/null
+++ b/src/proof/int/intM114.c
@@ -0,0 +1,320 @@
+/**CFile****************************************************************
+
+ FileName [intM114.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Interpolation engine.]
+
+ Synopsis [Intepolation using ABC's proof generator added to MiniSat-1.14c.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 24, 2008.]
+
+ Revision [$Id: intM114.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "intInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Returns the SAT solver for one interpolation run.]
+
+ Description [pInter is the previous interpolant. pAig is one time frame.
+ pFrames is the unrolled time frames.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+sat_solver * Inter_ManDeriveSatSolver(
+ Aig_Man_t * pInter, Cnf_Dat_t * pCnfInter,
+ Aig_Man_t * pAig, Cnf_Dat_t * pCnfAig,
+ Aig_Man_t * pFrames, Cnf_Dat_t * pCnfFrames,
+ Vec_Int_t * vVarsAB, int fUseBackward )
+{
+ sat_solver * pSat;
+ Aig_Obj_t * pObj, * pObj2;
+ int i, Lits[2];
+
+//Aig_ManDumpBlif( pInter, "out_inter.blif", NULL, NULL );
+//Aig_ManDumpBlif( pAig, "out_aig.blif", NULL, NULL );
+//Aig_ManDumpBlif( pFrames, "out_frames.blif", NULL, NULL );
+
+ // sanity checks
+ assert( Aig_ManRegNum(pInter) == 0 );
+ assert( Aig_ManRegNum(pAig) > 0 );
+ assert( Aig_ManRegNum(pFrames) == 0 );
+ assert( Aig_ManPoNum(pInter) == 1 );
+ assert( Aig_ManPoNum(pFrames) == fUseBackward? Saig_ManRegNum(pAig) : 1 );
+ assert( fUseBackward || Aig_ManPiNum(pInter) == Aig_ManRegNum(pAig) );
+// assert( (Aig_ManPiNum(pFrames) - Aig_ManRegNum(pAig)) % Saig_ManPiNum(pAig) == 0 );
+
+ // prepare CNFs
+ Cnf_DataLift( pCnfAig, pCnfFrames->nVars );
+ Cnf_DataLift( pCnfInter, pCnfFrames->nVars + pCnfAig->nVars );
+
+ // start the solver
+ pSat = sat_solver_new();
+ sat_solver_store_alloc( pSat );
+ sat_solver_setnvars( pSat, pCnfInter->nVars + pCnfAig->nVars + pCnfFrames->nVars );
+
+ // add clauses of A
+ // interpolant
+ for ( i = 0; i < pCnfInter->nClauses; i++ )
+ {
+ if ( !sat_solver_addclause( pSat, pCnfInter->pClauses[i], pCnfInter->pClauses[i+1] ) )
+ {
+ sat_solver_delete( pSat );
+ // return clauses to the original state
+ Cnf_DataLift( pCnfAig, -pCnfFrames->nVars );
+ Cnf_DataLift( pCnfInter, -pCnfFrames->nVars -pCnfAig->nVars );
+ return NULL;
+ }
+ }
+ // connector clauses
+ if ( fUseBackward )
+ {
+ Saig_ManForEachLi( pAig, pObj2, i )
+ {
+ if ( Saig_ManRegNum(pAig) == Aig_ManPiNum(pInter) )
+ pObj = Aig_ManPi( pInter, i );
+ else
+ {
+ assert( Aig_ManPiNum(pAig) == Aig_ManPiNum(pInter) );
+ pObj = Aig_ManPi( pInter, Aig_ManPiNum(pAig)-Saig_ManRegNum(pAig) + i );
+ }
+
+ Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 0 );
+ Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 );
+ if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
+ assert( 0 );
+ Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 1 );
+ Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 );
+ if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
+ assert( 0 );
+ }
+ }
+ else
+ {
+ Aig_ManForEachPi( pInter, pObj, i )
+ {
+ pObj2 = Saig_ManLo( pAig, i );
+
+ Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 0 );
+ Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 );
+ if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
+ assert( 0 );
+ Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 1 );
+ Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 );
+ if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
+ assert( 0 );
+ }
+ }
+ // one timeframe
+ for ( i = 0; i < pCnfAig->nClauses; i++ )
+ {
+ if ( !sat_solver_addclause( pSat, pCnfAig->pClauses[i], pCnfAig->pClauses[i+1] ) )
+ assert( 0 );
+ }
+ // connector clauses
+ Vec_IntClear( vVarsAB );
+ if ( fUseBackward )
+ {
+ Aig_ManForEachPo( pFrames, pObj, i )
+ {
+ assert( pCnfFrames->pVarNums[pObj->Id] >= 0 );
+ Vec_IntPush( vVarsAB, pCnfFrames->pVarNums[pObj->Id] );
+
+ pObj2 = Saig_ManLo( pAig, i );
+ Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 0 );
+ Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 );
+ if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
+ assert( 0 );
+ Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 1 );
+ Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 );
+ if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
+ assert( 0 );
+ }
+ }
+ else
+ {
+ Aig_ManForEachPi( pFrames, pObj, i )
+ {
+ if ( i == Aig_ManRegNum(pAig) )
+ break;
+ Vec_IntPush( vVarsAB, pCnfFrames->pVarNums[pObj->Id] );
+
+ pObj2 = Saig_ManLi( pAig, i );
+ Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 0 );
+ Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 );
+ if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
+ assert( 0 );
+ Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 1 );
+ Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 );
+ if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) )
+ assert( 0 );
+ }
+ }
+ // add clauses of B
+ sat_solver_store_mark_clauses_a( pSat );
+ for ( i = 0; i < pCnfFrames->nClauses; i++ )
+ {
+ if ( !sat_solver_addclause( pSat, pCnfFrames->pClauses[i], pCnfFrames->pClauses[i+1] ) )
+ {
+ pSat->fSolved = 1;
+ break;
+ }
+ }
+ sat_solver_store_mark_roots( pSat );
+ // return clauses to the original state
+ Cnf_DataLift( pCnfAig, -pCnfFrames->nVars );
+ Cnf_DataLift( pCnfInter, -pCnfFrames->nVars -pCnfAig->nVars );
+ return pSat;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs one SAT run with interpolation.]
+
+ Description [Returns 1 if proven. 0 if failed. -1 if undecided.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Inter_ManPerformOneStep( Inter_Man_t * p, int fUseBias, int fUseBackward, int nTimeNewOut )
+{
+ sat_solver * pSat;
+ void * pSatCnf = NULL;
+ Inta_Man_t * pManInterA;
+// Intb_Man_t * pManInterB;
+ int * pGlobalVars;
+ int clk, status, RetValue;
+ int i, Var;
+// assert( p->pInterNew == NULL );
+
+ // derive the SAT solver
+ pSat = Inter_ManDeriveSatSolver( p->pInter, p->pCnfInter, p->pAigTrans, p->pCnfAig, p->pFrames, p->pCnfFrames, p->vVarsAB, fUseBackward );
+ if ( pSat == NULL )
+ {
+ p->pInterNew = NULL;
+ return 1;
+ }
+
+ // set runtime limit
+ if ( nTimeNewOut )
+ sat_solver_set_runtime_limit( pSat, nTimeNewOut );
+
+ // collect global variables
+ pGlobalVars = ABC_CALLOC( int, sat_solver_nvars(pSat) );
+ Vec_IntForEachEntry( p->vVarsAB, Var, i )
+ pGlobalVars[Var] = 1;
+ pSat->pGlobalVars = fUseBias? pGlobalVars : NULL;
+
+ // solve the problem
+clk = clock();
+ status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)p->nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+ p->nConfCur = pSat->stats.conflicts;
+p->timeSat += clock() - clk;
+
+ pSat->pGlobalVars = NULL;
+ ABC_FREE( pGlobalVars );
+ if ( status == l_False )
+ {
+ pSatCnf = sat_solver_store_release( pSat );
+ RetValue = 1;
+ }
+ else if ( status == l_True )
+ {
+ RetValue = 0;
+ }
+ else
+ {
+ RetValue = -1;
+ }
+ sat_solver_delete( pSat );
+ if ( pSatCnf == NULL )
+ return RetValue;
+
+ // create the resulting manager
+clk = clock();
+/*
+ if ( !fUseIp )
+ {
+ pManInterA = Inta_ManAlloc();
+ p->pInterNew = Inta_ManInterpolate( pManInterA, pSatCnf, p->vVarsAB, 0 );
+ Inta_ManFree( pManInterA );
+ }
+ else
+ {
+ Aig_Man_t * pInterNew2;
+ int RetValue;
+
+ pManInterA = Inta_ManAlloc();
+ p->pInterNew = Inta_ManInterpolate( pManInterA, pSatCnf, p->vVarsAB, 0 );
+// Inter_ManVerifyInterpolant1( pManInterA, pSatCnf, p->pInterNew );
+ Inta_ManFree( pManInterA );
+
+ pManInterB = Intb_ManAlloc();
+ pInterNew2 = Intb_ManInterpolate( pManInterB, pSatCnf, p->vVarsAB, 0 );
+ Inter_ManVerifyInterpolant2( pManInterB, pSatCnf, pInterNew2 );
+ Intb_ManFree( pManInterB );
+
+ // check relationship
+ RetValue = Inter_ManCheckEquivalence( pInterNew2, p->pInterNew );
+ if ( RetValue )
+ printf( "Equivalence \"Ip == Im\" holds\n" );
+ else
+ {
+// printf( "Equivalence \"Ip == Im\" does not hold\n" );
+ RetValue = Inter_ManCheckContainment( pInterNew2, p->pInterNew );
+ if ( RetValue )
+ printf( "Containment \"Ip -> Im\" holds\n" );
+ else
+ printf( "Containment \"Ip -> Im\" does not hold\n" );
+
+ RetValue = Inter_ManCheckContainment( p->pInterNew, pInterNew2 );
+ if ( RetValue )
+ printf( "Containment \"Im -> Ip\" holds\n" );
+ else
+ printf( "Containment \"Im -> Ip\" does not hold\n" );
+ }
+
+ Aig_ManStop( pInterNew2 );
+ }
+*/
+
+ pManInterA = Inta_ManAlloc();
+ p->pInterNew = (Aig_Man_t *)Inta_ManInterpolate( pManInterA, (Sto_Man_t *)pSatCnf, p->vVarsAB, 0 );
+ Inta_ManFree( pManInterA );
+
+p->timeInt += clock() - clk;
+ Sto_ManFree( (Sto_Man_t *)pSatCnf );
+ return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/int/intM114p.c b/src/proof/int/intM114p.c
new file mode 100644
index 00000000..7c011426
--- /dev/null
+++ b/src/proof/int/intM114p.c
@@ -0,0 +1,442 @@
+/**CFile****************************************************************
+
+ FileName [intM114p.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Interpolation engine.]
+
+ Synopsis [Intepolation using interfaced to MiniSat-1.14p.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 24, 2008.]
+
+ Revision [$Id: intM114p.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "intInt.h"
+#include "src/sat/psat/m114p.h"
+
+#ifdef ABC_USE_LIBRARIES
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Returns the SAT solver for one interpolation run.]
+
+ Description [pInter is the previous interpolant. pAig is one time frame.
+ pFrames is the unrolled time frames.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+M114p_Solver_t Inter_ManDeriveSatSolverM114p(
+ Aig_Man_t * pInter, Cnf_Dat_t * pCnfInter,
+ Aig_Man_t * pAig, Cnf_Dat_t * pCnfAig,
+ Aig_Man_t * pFrames, Cnf_Dat_t * pCnfFrames,
+ Vec_Int_t ** pvMapRoots, Vec_Int_t ** pvMapVars )
+{
+ M114p_Solver_t pSat;
+ Aig_Obj_t * pObj, * pObj2;
+ int i, Lits[2];
+
+ // sanity checks
+ assert( Aig_ManRegNum(pInter) == 0 );
+ assert( Aig_ManRegNum(pAig) > 0 );
+ assert( Aig_ManRegNum(pFrames) == 0 );
+ assert( Aig_ManPoNum(pInter) == 1 );
+ assert( Aig_ManPoNum(pFrames) == 1 );
+ assert( Aig_ManPiNum(pInter) == Aig_ManRegNum(pAig) );
+// assert( (Aig_ManPiNum(pFrames) - Aig_ManRegNum(pAig)) % Saig_ManPiNum(pAig) == 0 );
+
+ // prepare CNFs
+ Cnf_DataLift( pCnfAig, pCnfFrames->nVars );
+ Cnf_DataLift( pCnfInter, pCnfFrames->nVars + pCnfAig->nVars );
+
+ *pvMapRoots = Vec_IntAlloc( 10000 );
+ *pvMapVars = Vec_IntAlloc( 0 );
+ Vec_IntFill( *pvMapVars, pCnfInter->nVars + pCnfAig->nVars + pCnfFrames->nVars, -1 );
+ for ( i = 0; i < pCnfFrames->nVars; i++ )
+ Vec_IntWriteEntry( *pvMapVars, i, -2 );
+
+ // start the solver
+ pSat = M114p_SolverNew( 1 );
+ M114p_SolverSetVarNum( pSat, pCnfInter->nVars + pCnfAig->nVars + pCnfFrames->nVars );
+
+ // add clauses of A
+ // interpolant
+ for ( i = 0; i < pCnfInter->nClauses; i++ )
+ {
+ Vec_IntPush( *pvMapRoots, 0 );
+ if ( !M114p_SolverAddClause( pSat, pCnfInter->pClauses[i], pCnfInter->pClauses[i+1] ) )
+ assert( 0 );
+ }
+ // connector clauses
+ Aig_ManForEachPi( pInter, pObj, i )
+ {
+ pObj2 = Saig_ManLo( pAig, i );
+ Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 0 );
+ Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 );
+ Vec_IntPush( *pvMapRoots, 0 );
+ if ( !M114p_SolverAddClause( pSat, Lits, Lits+2 ) )
+ assert( 0 );
+ Lits[0] = toLitCond( pCnfInter->pVarNums[pObj->Id], 1 );
+ Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 );
+ Vec_IntPush( *pvMapRoots, 0 );
+ if ( !M114p_SolverAddClause( pSat, Lits, Lits+2 ) )
+ assert( 0 );
+ }
+ // one timeframe
+ for ( i = 0; i < pCnfAig->nClauses; i++ )
+ {
+ Vec_IntPush( *pvMapRoots, 0 );
+ if ( !M114p_SolverAddClause( pSat, pCnfAig->pClauses[i], pCnfAig->pClauses[i+1] ) )
+ assert( 0 );
+ }
+ // connector clauses
+ Aig_ManForEachPi( pFrames, pObj, i )
+ {
+ if ( i == Aig_ManRegNum(pAig) )
+ break;
+// Vec_IntPush( vVarsAB, pCnfFrames->pVarNums[pObj->Id] );
+ Vec_IntWriteEntry( *pvMapVars, pCnfFrames->pVarNums[pObj->Id], i );
+
+ pObj2 = Saig_ManLi( pAig, i );
+ Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 0 );
+ Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 1 );
+ Vec_IntPush( *pvMapRoots, 0 );
+ if ( !M114p_SolverAddClause( pSat, Lits, Lits+2 ) )
+ assert( 0 );
+ Lits[0] = toLitCond( pCnfFrames->pVarNums[pObj->Id], 1 );
+ Lits[1] = toLitCond( pCnfAig->pVarNums[pObj2->Id], 0 );
+ Vec_IntPush( *pvMapRoots, 0 );
+ if ( !M114p_SolverAddClause( pSat, Lits, Lits+2 ) )
+ assert( 0 );
+ }
+ // add clauses of B
+ for ( i = 0; i < pCnfFrames->nClauses; i++ )
+ {
+ Vec_IntPush( *pvMapRoots, 1 );
+ if ( !M114p_SolverAddClause( pSat, pCnfFrames->pClauses[i], pCnfFrames->pClauses[i+1] ) )
+ {
+// assert( 0 );
+ break;
+ }
+ }
+ // return clauses to the original state
+ Cnf_DataLift( pCnfAig, -pCnfFrames->nVars );
+ Cnf_DataLift( pCnfInter, -pCnfFrames->nVars -pCnfAig->nVars );
+ return pSat;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs one resolution step.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Inter_ManResolveM114p( Vec_Int_t * vResolvent, int * pLits, int nLits, int iVar )
+{
+ int i, k, iLit = -1, fFound = 0;
+ // find the variable in the clause
+ for ( i = 0; i < vResolvent->nSize; i++ )
+ if ( lit_var(vResolvent->pArray[i]) == iVar )
+ {
+ iLit = vResolvent->pArray[i];
+ vResolvent->pArray[i] = vResolvent->pArray[--vResolvent->nSize];
+ break;
+ }
+ assert( iLit != -1 );
+ // add other variables
+ for ( i = 0; i < nLits; i++ )
+ {
+ if ( lit_var(pLits[i]) == iVar )
+ {
+ assert( iLit == lit_neg(pLits[i]) );
+ fFound = 1;
+ continue;
+ }
+ // check if this literal appears
+ for ( k = 0; k < vResolvent->nSize; k++ )
+ if ( vResolvent->pArray[k] == pLits[i] )
+ break;
+ if ( k < vResolvent->nSize )
+ continue;
+ // add this literal
+ Vec_IntPush( vResolvent, pLits[i] );
+ }
+ assert( fFound );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes interpolant using MiniSat-1.14p.]
+
+ Description [Assumes that the solver returned UNSAT and proof
+ logging was enabled. Array vMapRoots maps number of each root clause
+ into 0 (clause of A) or 1 (clause of B). Array vMapVars maps each SAT
+ solver variable into -1 (var of A), -2 (var of B), and <num> (var of C),
+ where <num> is the var's 0-based number in the ordering of C variables.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Inter_ManInterpolateM114pPudlak( M114p_Solver_t s, Vec_Int_t * vMapRoots, Vec_Int_t * vMapVars )
+{
+ Aig_Man_t * p;
+ Aig_Obj_t * pInter, * pInter2, * pVar;
+ Vec_Ptr_t * vInters;
+ Vec_Int_t * vLiterals, * vClauses, * vResolvent;
+ int * pLitsNext, nLitsNext, nOffset, iLit;
+ int * pLits, * pClauses, * pVars;
+ int nLits, nVars, i, k, v, iVar;
+ assert( M114p_SolverProofIsReady(s) );
+ vInters = Vec_PtrAlloc( 1000 );
+
+ vLiterals = Vec_IntAlloc( 10000 );
+ vClauses = Vec_IntAlloc( 1000 );
+ vResolvent = Vec_IntAlloc( 100 );
+
+ // create elementary variables
+ p = Aig_ManStart( 10000 );
+ Vec_IntForEachEntry( vMapVars, iVar, i )
+ if ( iVar >= 0 )
+ Aig_IthVar(p, iVar);
+ // process root clauses
+ M114p_SolverForEachRoot( s, &pLits, nLits, i )
+ {
+ if ( Vec_IntEntry(vMapRoots, i) == 1 ) // clause of B
+ pInter = Aig_ManConst1(p);
+ else // clause of A
+ pInter = Aig_ManConst0(p);
+ Vec_PtrPush( vInters, pInter );
+
+ // save the root clause
+ Vec_IntPush( vClauses, Vec_IntSize(vLiterals) );
+ Vec_IntPush( vLiterals, nLits );
+ for ( v = 0; v < nLits; v++ )
+ Vec_IntPush( vLiterals, pLits[v] );
+ }
+ assert( Vec_PtrSize(vInters) == Vec_IntSize(vMapRoots) );
+
+ // process learned clauses
+ M114p_SolverForEachChain( s, &pClauses, &pVars, nVars, i )
+ {
+ pInter = Vec_PtrEntry( vInters, pClauses[0] );
+
+ // initialize the resolvent
+ nOffset = Vec_IntEntry( vClauses, pClauses[0] );
+ nLitsNext = Vec_IntEntry( vLiterals, nOffset );
+ pLitsNext = Vec_IntArray(vLiterals) + nOffset + 1;
+ Vec_IntClear( vResolvent );
+ for ( v = 0; v < nLitsNext; v++ )
+ Vec_IntPush( vResolvent, pLitsNext[v] );
+
+ for ( k = 0; k < nVars; k++ )
+ {
+ iVar = Vec_IntEntry( vMapVars, pVars[k] );
+ pInter2 = Vec_PtrEntry( vInters, pClauses[k+1] );
+
+ // resolve it with the next clause
+ nOffset = Vec_IntEntry( vClauses, pClauses[k+1] );
+ nLitsNext = Vec_IntEntry( vLiterals, nOffset );
+ pLitsNext = Vec_IntArray(vLiterals) + nOffset + 1;
+ Inter_ManResolveM114p( vResolvent, pLitsNext, nLitsNext, pVars[k] );
+
+ if ( iVar == -1 ) // var of A
+ pInter = Aig_Or( p, pInter, pInter2 );
+ else if ( iVar == -2 ) // var of B
+ pInter = Aig_And( p, pInter, pInter2 );
+ else // var of C
+ {
+ // check polarity of the pivot variable in the clause
+ for ( v = 0; v < nLitsNext; v++ )
+ if ( lit_var(pLitsNext[v]) == pVars[k] )
+ break;
+ assert( v < nLitsNext );
+ pVar = Aig_NotCond( Aig_IthVar(p, iVar), lit_sign(pLitsNext[v]) );
+ pInter = Aig_Mux( p, pVar, pInter, pInter2 );
+ }
+ }
+ Vec_PtrPush( vInters, pInter );
+
+ // store the resulting clause
+ Vec_IntPush( vClauses, Vec_IntSize(vLiterals) );
+ Vec_IntPush( vLiterals, Vec_IntSize(vResolvent) );
+ Vec_IntForEachEntry( vResolvent, iLit, v )
+ Vec_IntPush( vLiterals, iLit );
+ }
+ assert( Vec_PtrSize(vInters) == M114p_SolverProofClauseNum(s) );
+ assert( Vec_IntSize(vResolvent) == 0 ); // the empty clause
+ Vec_PtrFree( vInters );
+ Vec_IntFree( vLiterals );
+ Vec_IntFree( vClauses );
+ Vec_IntFree( vResolvent );
+ Aig_ObjCreatePo( p, pInter );
+ Aig_ManCleanup( p );
+ return p;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes interpolant using MiniSat-1.14p.]
+
+ Description [Assumes that the solver returned UNSAT and proof
+ logging was enabled. Array vMapRoots maps number of each root clause
+ into 0 (clause of A) or 1 (clause of B). Array vMapVars maps each SAT
+ solver variable into -1 (var of A), -2 (var of B), and <num> (var of C),
+ where <num> is the var's 0-based number in the ordering of C variables.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Inter_ManpInterpolateM114( M114p_Solver_t s, Vec_Int_t * vMapRoots, Vec_Int_t * vMapVars )
+{
+ Aig_Man_t * p;
+ Aig_Obj_t * pInter, * pInter2, * pVar;
+ Vec_Ptr_t * vInters;
+ int * pLits, * pClauses, * pVars;
+ int nLits, nVars, i, k, iVar;
+ int nClauses;
+
+ nClauses = M114p_SolverProofClauseNum(s);
+
+ assert( M114p_SolverProofIsReady(s) );
+
+ vInters = Vec_PtrAlloc( 1000 );
+ // process root clauses
+ p = Aig_ManStart( 10000 );
+ M114p_SolverForEachRoot( s, &pLits, nLits, i )
+ {
+ if ( Vec_IntEntry(vMapRoots, i) == 1 ) // clause of B
+ pInter = Aig_ManConst1(p);
+ else // clause of A
+ {
+ pInter = Aig_ManConst0(p);
+ for ( k = 0; k < nLits; k++ )
+ {
+ iVar = Vec_IntEntry( vMapVars, lit_var(pLits[k]) );
+ if ( iVar < 0 ) // var of A or B
+ continue;
+ // this is a variable of C
+ pVar = Aig_NotCond( Aig_IthVar(p, iVar), lit_sign(pLits[k]) );
+ pInter = Aig_Or( p, pInter, pVar );
+ }
+ }
+ Vec_PtrPush( vInters, pInter );
+ }
+// assert( Vec_PtrSize(vInters) == Vec_IntSize(vMapRoots) );
+
+ // process learned clauses
+ M114p_SolverForEachChain( s, &pClauses, &pVars, nVars, i )
+ {
+ pInter = Vec_PtrEntry( vInters, pClauses[0] );
+ for ( k = 0; k < nVars; k++ )
+ {
+ iVar = Vec_IntEntry( vMapVars, pVars[k] );
+ pInter2 = Vec_PtrEntry( vInters, pClauses[k+1] );
+ if ( iVar == -1 ) // var of A
+ pInter = Aig_Or( p, pInter, pInter2 );
+ else // var of B or C
+ pInter = Aig_And( p, pInter, pInter2 );
+ }
+ Vec_PtrPush( vInters, pInter );
+ }
+
+ assert( Vec_PtrSize(vInters) == M114p_SolverProofClauseNum(s) );
+ Vec_PtrFree( vInters );
+ Aig_ObjCreatePo( p, pInter );
+ Aig_ManCleanup( p );
+ assert( Aig_ManCheck(p) );
+ return p;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs one SAT run with interpolation.]
+
+ Description [Returns 1 if proven. 0 if failed. -1 if undecided.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Inter_ManPerformOneStepM114p( Inter_Man_t * p, int fUsePudlak, int fUseOther )
+{
+ M114p_Solver_t pSat;
+ Vec_Int_t * vMapRoots, * vMapVars;
+ int clk, status, RetValue;
+ assert( p->pInterNew == NULL );
+ // derive the SAT solver
+ pSat = Inter_ManDeriveSatSolverM114p( p->pInter, p->pCnfInter,
+ p->pAigTrans, p->pCnfAig, p->pFrames, p->pCnfFrames,
+ &vMapRoots, &vMapVars );
+ // solve the problem
+clk = clock();
+ status = M114p_SolverSolve( pSat, NULL, NULL, 0 );
+ p->nConfCur = M114p_SolverGetConflictNum( pSat );
+p->timeSat += clock() - clk;
+ if ( status == 0 )
+ {
+ RetValue = 1;
+// Inter_ManpInterpolateM114Report( pSat, vMapRoots, vMapVars );
+
+clk = clock();
+ if ( fUsePudlak )
+ p->pInterNew = Inter_ManInterpolateM114pPudlak( pSat, vMapRoots, vMapVars );
+ else
+ p->pInterNew = Inter_ManpInterpolateM114( pSat, vMapRoots, vMapVars );
+p->timeInt += clock() - clk;
+ }
+ else if ( status == 1 )
+ {
+ RetValue = 0;
+ }
+ else
+ {
+ RetValue = -1;
+ }
+ M114p_SolverDelete( pSat );
+ Vec_IntFree( vMapRoots );
+ Vec_IntFree( vMapVars );
+ return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_IMPL_END
+
+#endif
+
+
diff --git a/src/proof/int/intMan.c b/src/proof/int/intMan.c
new file mode 100644
index 00000000..6fd81d7a
--- /dev/null
+++ b/src/proof/int/intMan.c
@@ -0,0 +1,163 @@
+/**CFile****************************************************************
+
+ FileName [intMan.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Interpolation engine.]
+
+ Synopsis [Interpolation manager procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 24, 2008.]
+
+ Revision [$Id: intMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "intInt.h"
+#include "src/aig/ioa/ioa.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Creates the interpolation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Inter_Man_t * Inter_ManCreate( Aig_Man_t * pAig, Inter_ManParams_t * pPars )
+{
+ Inter_Man_t * p;
+ // create interpolation manager
+ p = ABC_ALLOC( Inter_Man_t, 1 );
+ memset( p, 0, sizeof(Inter_Man_t) );
+ p->vVarsAB = Vec_IntAlloc( Aig_ManRegNum(pAig) );
+ p->nConfLimit = pPars->nBTLimit;
+ p->fVerbose = pPars->fVerbose;
+ p->pAig = pAig;
+ if ( pPars->fDropInvar )
+ p->vInters = Vec_PtrAlloc( 100 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Cleans the interpolation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Inter_ManClean( Inter_Man_t * p )
+{
+ if ( p->vInters )
+ {
+ Aig_Man_t * pMan;
+ int i;
+ Vec_PtrForEachEntry( Aig_Man_t *, p->vInters, pMan, i )
+ Aig_ManStop( pMan );
+ Vec_PtrClear( p->vInters );
+ }
+ if ( p->pCnfInter )
+ Cnf_DataFree( p->pCnfInter );
+ if ( p->pCnfFrames )
+ Cnf_DataFree( p->pCnfFrames );
+ if ( p->pInter )
+ Aig_ManStop( p->pInter );
+ if ( p->pFrames )
+ Aig_ManStop( p->pFrames );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes interpolant into a file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Inter_ManInterDump( Inter_Man_t * p, int fProved )
+{
+ Aig_Man_t * pMan;
+ pMan = Aig_ManDupArray( p->vInters );
+ Ioa_WriteAiger( pMan, "invar.aig", 0, 0 );
+ Aig_ManStop( pMan );
+ if ( fProved )
+ printf( "Inductive invariant is dumped into file \"invar.aig\".\n" );
+ else
+ printf( "Interpolants are dumped into file \"inter.aig\".\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the interpolation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Inter_ManStop( Inter_Man_t * p, int fProved )
+{
+ if ( p->fVerbose )
+ {
+ p->timeOther = p->timeTotal-p->timeRwr-p->timeCnf-p->timeSat-p->timeInt-p->timeEqu;
+ printf( "Runtime statistics:\n" );
+ ABC_PRTP( "Rewriting ", p->timeRwr, p->timeTotal );
+ ABC_PRTP( "CNF mapping", p->timeCnf, p->timeTotal );
+ ABC_PRTP( "SAT solving", p->timeSat, p->timeTotal );
+ ABC_PRTP( "Interpol ", p->timeInt, p->timeTotal );
+ ABC_PRTP( "Containment", p->timeEqu, p->timeTotal );
+ ABC_PRTP( "Other ", p->timeOther, p->timeTotal );
+ ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal );
+ }
+
+ if ( p->vInters )
+ Inter_ManInterDump( p, fProved );
+
+ if ( p->pCnfAig )
+ Cnf_DataFree( p->pCnfAig );
+ if ( p->pAigTrans )
+ Aig_ManStop( p->pAigTrans );
+ if ( p->pInterNew )
+ Aig_ManStop( p->pInterNew );
+ Inter_ManClean( p );
+ Vec_PtrFreeP( &p->vInters );
+ Vec_IntFreeP( &p->vVarsAB );
+ ABC_FREE( p );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/int/intUtil.c b/src/proof/int/intUtil.c
new file mode 100644
index 00000000..8027bdef
--- /dev/null
+++ b/src/proof/int/intUtil.c
@@ -0,0 +1,108 @@
+/**CFile****************************************************************
+
+ FileName [intUtil.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Interpolation engine.]
+
+ Synopsis [Various interpolation utilities.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 24, 2008.]
+
+ Revision [$Id: intUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "intInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the property fails in the initial state.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Inter_ManCheckInitialState( Aig_Man_t * p )
+{
+ Cnf_Dat_t * pCnf;
+ Aig_Obj_t * pObj;
+ sat_solver * pSat;
+ int i, status;
+ int clk = clock();
+ pCnf = Cnf_Derive( p, Saig_ManRegNum(p) );
+ pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 1 );
+ if ( pSat == NULL )
+ {
+ Cnf_DataFree( pCnf );
+ return 0;
+ }
+ status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+ ABC_PRT( "Time", clock() - clk );
+ if ( status == l_True )
+ {
+ p->pSeqModel = Abc_CexAlloc( Aig_ManRegNum(p), Saig_ManPiNum(p), 1 );
+ Saig_ManForEachPi( p, pObj, i )
+ if ( sat_solver_var_value( pSat, pCnf->pVarNums[Aig_ObjId(pObj)] ) )
+ Abc_InfoSetBit( p->pSeqModel->pData, Aig_ManRegNum(p) + i );
+ }
+ Cnf_DataFree( pCnf );
+ sat_solver_delete( pSat );
+ return status == l_True;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the property holds in all states.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Inter_ManCheckAllStates( Aig_Man_t * p )
+{
+ Cnf_Dat_t * pCnf;
+ sat_solver * pSat;
+ int status;
+ int clk = clock();
+ pCnf = Cnf_Derive( p, Saig_ManRegNum(p) );
+ pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+ Cnf_DataFree( pCnf );
+ if ( pSat == NULL )
+ return 1;
+ status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+ sat_solver_delete( pSat );
+ ABC_PRT( "Time", clock() - clk );
+ return status == l_False;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/int/module.make b/src/proof/int/module.make
new file mode 100644
index 00000000..4a66b6ca
--- /dev/null
+++ b/src/proof/int/module.make
@@ -0,0 +1,11 @@
+SRC += src/proof/int/intCheck.c \
+ src/proof/int/intContain.c \
+ src/proof/int/intCore.c \
+ src/proof/int/intCtrex.c \
+ src/proof/int/intDup.c \
+ src/proof/int/intFrames.c \
+ src/proof/int/intInter.c \
+ src/proof/int/intM114.c \
+ src/proof/int/intM114p.c \
+ src/proof/int/intMan.c \
+ src/proof/int/intUtil.c
diff --git a/src/proof/live/liveness.c b/src/proof/live/liveness.c
new file mode 100644
index 00000000..8368e121
--- /dev/null
+++ b/src/proof/live/liveness.c
@@ -0,0 +1,2575 @@
+/**CFile****************************************************************
+
+ FileName [liveness.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.c,v 1.00 2009/01/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include "src/base/main/main.h"
+#include "src/aig/aig/aig.h"
+#include "src/aig/saig/saig.h"
+#include <string.h>
+#include "src/base/main/mainInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+#define PROPAGATE_NAMES
+#define MULTIPLE_LTL_FORMULA
+#define ALLOW_SAFETY_PROPERTIES
+
+#define FULL_BIERE_MODE 0
+#define IGNORE_LIVENESS_KEEP_SAFETY_MODE 1
+#define IGNORE_SAFETY_KEEP_LIVENESS_MODE 2
+#define IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE 3
+#define FULL_BIERE_ONE_LOOP_MODE 4
+//#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);
+
+//******************************************
+//external functions defined in ltl_parser.c
+//******************************************
+typedef struct ltlNode_t ltlNode;
+extern ltlNode *readLtlFormula( char *formula );
+extern void traverseAbstractSyntaxTree( ltlNode *node );
+extern ltlNode *parseFormulaCreateAST( char *inputFormula );
+extern int isWellFormed( ltlNode *topNode );
+extern int checkSignalNameExistence( Abc_Ntk_t *pNtk, ltlNode *topASTNode );
+extern void populateBoolWithAigNodePtr( Abc_Ntk_t *pNtk, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, ltlNode *topASTNode );
+extern int checkAllBoolHaveAIGPointer( ltlNode *topASTNode );
+extern void populateAigPointerUnitGF( Aig_Man_t *pAigNew, ltlNode *topASTNode, Vec_Ptr_t *vSignal, Vec_Vec_t *vAigGFMap );
+extern void setAIGNodePtrOfGloballyNode( ltlNode *astNode, Aig_Obj_t *pObjLo );
+extern Aig_Obj_t *buildLogicFromLTLNode( Aig_Man_t *pAig, ltlNode *pLtlNode );
+extern Aig_Obj_t *retriveAIGPointerFromLTLNode( ltlNode *astNode );
+extern void traverseAbstractSyntaxTree_postFix( ltlNode *node );
+//**********************************
+//external function declaration ends
+//**********************************
+
+
+/*******************************************************************
+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 int nodeName_starts_with( Abc_Obj_t *pNode, const char *prefix )
+{
+ if( strstr( Abc_ObjName( pNode ), prefix ) == Abc_ObjName( pNode ) )
+ return 1;
+ else
+ return 0;
+}
+
+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) );
+ }
+}
+
+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;
+}
+
+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_ManForEachPi( pAigNew, pObj, index )
+ if( pObj == pObjPivot )
+ break;
+ assert( index < Aig_ManPiNum( pAigNew ) - Aig_ManRegNum( pAigNew ) );
+ if( index == Saig_ManPiNum( pAigNew ) - 1 )
+ return "SAVE_BIERE";
+ else
+ {
+ pObjOld = Aig_ManPi( pAigOld, index );
+ pNode = Abc_NtkPi( pNtkOld, index );
+ assert( pObjOld->pData == pObjPivot );
+ return Abc_ObjName( pNode );
+ }
+}
+
+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_ManPi( 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_ManPi( 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;
+ dummyStr[0] = '\0';
+ Saig_ManForEachPo( pAigOld, pObj, i )
+ {
+ pNode = Abc_NtkPo( pNtkOld, i );
+ //if( strstr( Abc_ObjName( pNode ), "assert_fair" ) != NULL )
+ if( nodeName_starts_with( pNode, "assert_fair" ) )
+ {
+ if( strMatch == oldIndex )
+ {
+ sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "LIVENESS");
+ //return dummyStr;
+ break;
+ }
+ else
+ strMatch++;
+ }
+ }
+ assert( dummyStr[0] != '\0' );
+ return dummyStr;
+ }
+ 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;
+ dummyStr[0] = '\0';
+ Saig_ManForEachPo( pAigOld, pObj, i )
+ {
+ pNode = Abc_NtkPo( pNtkOld, i );
+ //if( strstr( Abc_ObjName( pNode ), "assume_fair" ) != NULL )
+ if( nodeName_starts_with( pNode, "assume_fair" ) )
+ {
+ if( strMatch == oldIndex )
+ {
+ sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "FAIRNESS");
+ //return dummyStr;
+ break;
+ }
+ else
+ strMatch++;
+ }
+ }
+ assert( dummyStr[0] != '\0' );
+ return dummyStr;
+ }
+ else
+ return "UNKNOWN";
+}
+
+Vec_Ptr_t *vecPis, *vecPiNames;
+Vec_Ptr_t *vecLos, *vecLoNames;
+
+
+int Aig_ManPiCleanupBiere( Aig_Man_t * p )
+{
+ int k = 0, nPisOld = Aig_ManPiNum(p);
+
+ p->nObjs[AIG_OBJ_PI] = Vec_PtrSize( p->vPis );
+ if ( Aig_ManRegNum(p) )
+ p->nTruePis = Aig_ManPiNum(p) - Aig_ManRegNum(p);
+
+ return nPisOld - Aig_ManPiNum(p);
+}
+
+
+int Aig_ManPoCleanupBiere( Aig_Man_t * p )
+{
+ int k = 0, nPosOld = Aig_ManPoNum(p);
+
+ p->nObjs[AIG_OBJ_PO] = Vec_PtrSize( p->vPos );
+ if ( Aig_ManRegNum(p) )
+ p->nTruePos = Aig_ManPoNum(p) - Aig_ManRegNum(p);
+ return nPosOld - Aig_ManPoNum(p);
+}
+
+Aig_Man_t * LivenessToSafetyTransformation( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p,
+ Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety )
+{
+ 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, *pObjSaveAndNotSaved, *pObjSavedLoAndEquality;
+ Aig_Obj_t *pObjShadowLo, *pObjShadowLi, *pObjShadowLiDriver;
+ Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc;
+ Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate;
+ Aig_Obj_t *pObjSafetyPropertyOutput;
+ Aig_Obj_t *pObjOriginalSafetyPropertyOutput;
+ Aig_Obj_t *pDriverImage, *pArgument, *collectiveAssertSafety, *collectiveAssumeSafety;
+ char *nodeName;
+ int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, piVecIndex = 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 ) );
+
+ //****************************************************************
+ // 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 = (char *)malloc( strlen( pNtk->pName ) + strlen("_l2s") + 1 );
+ sprintf(pNew->pName, "%s_%s", pNtk->pName, "l2s");
+ 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_ObjCreatePi(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
+ //****************************************************************
+ if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+ {
+ pObjSavePi = Aig_ObjCreatePi( pNew );
+ nodeName = "SAVE_BIERE",
+ Vec_PtrPush( vecPiNames, nodeName );
+ }
+
+ //****************************************************************
+ // Step 5: create register outputs
+ //****************************************************************
+ Saig_ManForEachLo( p, pObj, i )
+ {
+ loCopied++;
+ pObj->pData = Aig_ObjCreatePi(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( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+ {
+ loCreated++;
+ pObjSavedLo = Aig_ObjCreatePi( pNew );
+ Vec_PtrPush( vecLos, pObjSavedLo );
+ nodeName = "SAVED_LO";
+ Vec_PtrPush( vecLoNames, nodeName );
+ }
+
+ //****************************************************************
+ // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi
+ //****************************************************************
+ if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+ {
+ pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo );
+ pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) );
+ }
+
+ //********************************************************************
+ // Step 8: create internal nodes
+ //********************************************************************
+ Aig_ManForEachNode( p, pObj, i )
+ {
+ pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+ }
+
+
+ //********************************************************************
+ // Step 8.x : create PO for each safety assertions
+ // NOTE : Here the output is purposely inverted as it will be thrown to
+ // dprove
+ //********************************************************************
+ if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE )
+ {
+ if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 )
+ {
+ pObjAndAcc = Aig_ManConst1( pNew );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i )
+ {
+ pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
+ pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc );
+ }
+ pObjOriginalSafetyPropertyOutput = Aig_ObjCreatePo( pNew, Aig_Not(pObjAndAcc) );
+ }
+ else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 )
+ {
+ pObjAndAcc = Aig_ManConst1( pNew );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i )
+ {
+ pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
+ pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc );
+ }
+ collectiveAssertSafety = pObjAndAcc;
+
+ pObjAndAcc = Aig_ManConst1( pNew );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i )
+ {
+ pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
+ pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc );
+ }
+ collectiveAssumeSafety = pObjAndAcc;
+ pObjOriginalSafetyPropertyOutput = Aig_ObjCreatePo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) );
+ }
+ else
+ {
+ printf("WARNING!! No safety property is found, a new (negated) constant 1 output is created\n");
+ pObjOriginalSafetyPropertyOutput = Aig_ObjCreatePo( pNew, Aig_Not( Aig_ManConst1(pNew) ) );
+ }
+ }
+
+ //********************************************************************
+ // Step 9: create the safety property output gate for the liveness properties
+ // discuss with Sat/Alan for an alternative implementation
+ //********************************************************************
+ if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+ {
+ pObjSafetyPropertyOutput = Aig_ObjCreatePo( 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_ObjCreatePo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) );
+ nRegCount++;
+ liCopied++;
+ }
+
+ // create register input corresponding to the register "saved"
+ if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+ {
+ #ifndef DUPLICATE_CKT_DEBUG
+ pObjSavedLi = Aig_ObjCreatePo( pNew, pObjSaveOrSaved );
+ nRegCount++;
+ liCreated++;
+
+ //Changed on October 13, 2009
+ //pObjAndAcc = NULL;
+ pObjAndAcc = Aig_ManConst1( pNew );
+
+ // 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_ObjCreatePi( 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, pObjSaveAndNotSaved, (Aig_Obj_t *)pObj->pData, pObjShadowLo );
+ pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver );
+ nRegCount++;
+ loCreated++; liCreated++;
+
+ pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, pObjShadowLo );
+ pObjXnor = Aig_Not( pObjXor );
+
+ pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAcc );
+ }
+
+ // 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 = Aig_ManConst1( pNew );
+ if( vLive == NULL || Vec_PtrSize( vLive ) == 0 )
+ {
+ printf("Circuit without any liveness property\n");
+ }
+ else
+ {
+ Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i )
+ {
+ liveLatch++;
+ pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj));
+ pObjShadowLo = Aig_ObjCreatePi( 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, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) );
+ pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver );
+ nRegCount++;
+ loCreated++; liCreated++;
+
+ pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc );
+ }
+ }
+
+ pObjLive = pObjAndAcc;
+
+ pObjAndAcc = Aig_ManConst1( pNew );
+ if( vFair == NULL || Vec_PtrSize( vFair ) == 0 )
+ printf("Circuit without any fairness property\n");
+ else
+ {
+ Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i )
+ {
+ fairLatch++;
+ pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj));
+ pObjShadowLo = Aig_ObjCreatePi( 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, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) );
+ pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver );
+ nRegCount++;
+ loCreated++; liCreated++;
+
+ pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc );
+ }
+ }
+
+ pObjFair = pObjAndAcc;
+
+ //pObjSafetyGate = Aig_Exor( pNew, Aig_Not(Aig_ManConst1( pNew )), Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ) );
+ //Following is the actual Biere translation
+ pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) );
+
+ Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate );
+ #endif
+ }
+
+ Aig_ManSetRegNum( pNew, nRegCount );
+
+ Aig_ManPiCleanupBiere( pNew );
+ Aig_ManPoCleanupBiere( pNew );
+
+ Aig_ManCleanup( pNew );
+
+ assert( Aig_ManCheck( pNew ) );
+
+ if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+ {
+ assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vPos, Saig_ManPoNum(pNew)+Aig_ObjPioNum(pObjSavedLo)-Saig_ManPiNum(p)-1) == pObjSavedLi);
+ assert( Saig_ManPiNum( p ) + 1 == Saig_ManPiNum( pNew ) );
+ assert( Saig_ManRegNum( pNew ) == Saig_ManRegNum( p ) * 2 + 1 + liveLatch + fairLatch );
+ }
+
+ return pNew;
+}
+
+
+
+
+
+Aig_Man_t * LivenessToSafetyTransformationAbs( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p, Vec_Int_t *vFlops,
+ Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety )
+{
+ Aig_Man_t * pNew;
+ int i, nRegCount, iEntry;
+ Aig_Obj_t * pObjSavePi;
+ Aig_Obj_t *pObjSavedLo, *pObjSavedLi;
+ Aig_Obj_t *pObj, *pMatch;
+ Aig_Obj_t *pObjSaveOrSaved, *pObjSaveAndNotSaved, *pObjSavedLoAndEquality;
+ Aig_Obj_t *pObjShadowLo, *pObjShadowLi, *pObjShadowLiDriver;
+ Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc;
+ Aig_Obj_t *pObjLive, *pObjFair, *pObjSafetyGate;
+ Aig_Obj_t *pObjSafetyPropertyOutput;
+ Aig_Obj_t *pDriverImage, *pArgument, *collectiveAssertSafety, *collectiveAssumeSafety;
+ char *nodeName;
+ int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, piVecIndex = 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 ) + Vec_IntSize( vFlops ) + 1 + Vec_PtrSize( vLive ) + Vec_PtrSize( vFair ) );
+ vecLoNames = Vec_PtrAlloc( Saig_ManRegNum( p ) + Vec_IntSize( vFlops ) + 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 = (char *)malloc( strlen( pNtk->pName ) + strlen("_l2s") + 1 );
+ sprintf(pNew->pName, "%s_%s", pNtk->pName, "l2s");
+ 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_ObjCreatePi(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
+ //****************************************************************
+ if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+ {
+ pObjSavePi = Aig_ObjCreatePi( pNew );
+ nodeName = "SAVE_BIERE",
+ Vec_PtrPush( vecPiNames, nodeName );
+ }
+
+ //****************************************************************
+ // Step 5: create register outputs
+ //****************************************************************
+ Saig_ManForEachLo( p, pObj, i )
+ {
+ loCopied++;
+ pObj->pData = Aig_ObjCreatePi(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( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+ {
+ loCreated++;
+ pObjSavedLo = Aig_ObjCreatePi( pNew );
+ Vec_PtrPush( vecLos, pObjSavedLo );
+ nodeName = "SAVED_LO";
+ Vec_PtrPush( vecLoNames, nodeName );
+ }
+
+ //****************************************************************
+ // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi
+ //****************************************************************
+ if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+ {
+ pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo );
+ pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) );
+ }
+
+ //********************************************************************
+ // Step 8: create internal nodes
+ //********************************************************************
+ Aig_ManForEachNode( p, pObj, i )
+ {
+ pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+ }
+
+
+ //********************************************************************
+ // Step 8.x : create PO for each safety assertions
+ // NOTE : Here the output is purposely inverted as it will be thrown to
+ // dprove
+ //********************************************************************
+ if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE )
+ {
+ if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 )
+ {
+ pObjAndAcc = Aig_ManConst1( pNew );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i )
+ {
+ pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
+ pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc );
+ }
+ Aig_ObjCreatePo( pNew, Aig_Not(pObjAndAcc) );
+ }
+ else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 )
+ {
+ pObjAndAcc = Aig_ManConst1( pNew );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i )
+ {
+ pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
+ pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc );
+ }
+ collectiveAssertSafety = pObjAndAcc;
+
+ pObjAndAcc = Aig_ManConst1( pNew );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i )
+ {
+ pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
+ pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc );
+ }
+ collectiveAssumeSafety = pObjAndAcc;
+ Aig_ObjCreatePo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) );
+ }
+ else
+ {
+ printf("WARNING!! No safety property is found, a new (negated) constant 1 output is created\n");
+ Aig_ObjCreatePo( pNew, Aig_Not( Aig_ManConst1(pNew) ) );
+ }
+ }
+
+ //********************************************************************
+ // Step 9: create the safety property output gate for the liveness properties
+ // discuss with Sat/Alan for an alternative implementation
+ //********************************************************************
+ if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+ {
+ pObjSafetyPropertyOutput = Aig_ObjCreatePo( 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_ObjCreatePo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) );
+ nRegCount++;
+ liCopied++;
+ }
+
+ // create register input corresponding to the register "saved"
+ if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+ {
+ #ifndef DUPLICATE_CKT_DEBUG
+ pObjSavedLi = Aig_ObjCreatePo( pNew, pObjSaveOrSaved );
+ nRegCount++;
+ liCreated++;
+
+ //Changed on October 13, 2009
+ //pObjAndAcc = NULL;
+ pObjAndAcc = Aig_ManConst1( pNew );
+
+ // create the family of shadow registers, then create the cascade of Xnor and And gates for the comparator
+ //Saig_ManForEachLo( p, pObj, i )
+ Saig_ManForEachLo( p, pObj, i )
+ {
+ printf("Flop[%d] = %s\n", i, Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ) );
+ }
+ Vec_IntForEachEntry( vFlops, iEntry, i )
+ {
+ pObjShadowLo = Aig_ObjCreatePi( pNew );
+ pObj = Aig_ManLo( p, iEntry );
+
+ #ifdef PROPAGATE_NAMES
+ Vec_PtrPush( vecLos, pObjShadowLo );
+ nodeName = (char *)malloc( strlen( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + iEntry ) ) ) + 10 );
+ sprintf( nodeName, "%s__%s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + iEntry ) ), "SHADOW" );
+ printf("Flop copied [%d] = %s\n", iEntry, nodeName );
+ Vec_PtrPush( vecLoNames, nodeName );
+ #endif
+
+ pObjShadowLiDriver = Aig_Mux( pNew, pObjSaveAndNotSaved, (Aig_Obj_t *)pObj->pData, pObjShadowLo );
+ pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver );
+ nRegCount++;
+ loCreated++; liCreated++;
+
+ pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, pObjShadowLo );
+ pObjXnor = Aig_Not( pObjXor );
+
+ pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAcc );
+ }
+
+ // 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 = Aig_ManConst1( pNew );
+ if( vLive == NULL || Vec_PtrSize( vLive ) == 0 )
+ {
+ printf("Circuit without any liveness property\n");
+ }
+ else
+ {
+ Vec_PtrForEachEntry( Aig_Obj_t *, vLive, pObj, i )
+ {
+ liveLatch++;
+ pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj));
+ pObjShadowLo = Aig_ObjCreatePi( 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, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) );
+ pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver );
+ nRegCount++;
+ loCreated++; liCreated++;
+
+ pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc );
+ }
+ }
+
+ pObjLive = pObjAndAcc;
+
+ pObjAndAcc = Aig_ManConst1( pNew );
+ if( vFair == NULL || Vec_PtrSize( vFair ) == 0 )
+ printf("Circuit without any fairness property\n");
+ else
+ {
+ Vec_PtrForEachEntry( Aig_Obj_t *, vFair, pObj, i )
+ {
+ fairLatch++;
+ pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj));
+ pObjShadowLo = Aig_ObjCreatePi( 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, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) );
+ pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver );
+ nRegCount++;
+ loCreated++; liCreated++;
+
+ pObjAndAcc = Aig_And( pNew, pObjShadowLo, pObjAndAcc );
+ }
+ }
+
+ pObjFair = pObjAndAcc;
+
+ //pObjSafetyGate = Aig_Exor( pNew, Aig_Not(Aig_ManConst1( pNew )), Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) ) );
+ //Following is the actual Biere translation
+ pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_And( pNew, pObjFair, Aig_Not( pObjLive ) ) );
+
+ Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate );
+ #endif
+ }
+
+ Aig_ManSetRegNum( pNew, nRegCount );
+
+ Aig_ManPiCleanupBiere( pNew );
+ Aig_ManPoCleanupBiere( pNew );
+
+ Aig_ManCleanup( pNew );
+
+ assert( Aig_ManCheck( pNew ) );
+
+ if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+ {
+ assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vPos, Saig_ManPoNum(pNew)+Aig_ObjPioNum(pObjSavedLo)-Saig_ManPiNum(p)-1) == pObjSavedLi);
+ assert( Saig_ManPiNum( p ) + 1 == Saig_ManPiNum( pNew ) );
+ assert( Saig_ManRegNum( pNew ) == Saig_ManRegNum( p ) + Vec_IntSize( vFlops ) + 1 + liveLatch + fairLatch );
+ }
+
+ return pNew;
+}
+
+
+
+Aig_Man_t * LivenessToSafetyTransformationOneStepLoop( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p,
+ Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety )
+{
+ 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;
+ Aig_Obj_t *pArgument;
+ Aig_Obj_t *collectiveAssertSafety, *collectiveAssumeSafety;
+
+ char *nodeName;
+ int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, piVecIndex = 0;
+
+ if( Aig_ManRegNum( p ) == 0 )
+ {
+ printf("The input AIG contains no register, returning the original AIG as it is\n");
+ return p;
+ }
+
+ 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_ObjCreatePi(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
+ //****************************************************************
+ if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE )
+ {
+ pObjSavePi = Aig_ObjCreatePi( pNew );
+ nodeName = "SAVE_BIERE",
+ Vec_PtrPush( vecPiNames, nodeName );
+ }
+
+ //****************************************************************
+ // Step 5: create register outputs
+ //****************************************************************
+ Saig_ManForEachLo( p, pObj, i )
+ {
+ loCopied++;
+ pObj->pData = Aig_ObjCreatePi(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_ObjCreatePi( 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) );
+ }
+
+#if 0
+ //********************************************************************
+ // Step 8.x : create PO for each safety assertions
+ //********************************************************************
+ Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i )
+ {
+ pObj->pData = Aig_ObjCreatePo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) );
+ }
+#endif
+
+ if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE )
+ {
+ if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 )
+ {
+ pObjAndAcc = NULL;
+ Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i )
+ {
+ //pObj->pData = Aig_ObjCreatePo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) );
+ pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
+ if( pObjAndAcc == NULL )
+ pObjAndAcc = pArgument;
+ else
+ {
+ pObjAndAccDummy = pObjAndAcc;
+ pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAccDummy );
+ }
+ }
+ Aig_ObjCreatePo( pNew, Aig_Not(pObjAndAcc) );
+ }
+ else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 )
+ {
+ pObjAndAcc = NULL;
+ Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i )
+ {
+ //pObj->pData = Aig_ObjCreatePo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) );
+ pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
+ if( pObjAndAcc == NULL )
+ pObjAndAcc = pArgument;
+ else
+ {
+ pObjAndAccDummy = pObjAndAcc;
+ pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAccDummy );
+ }
+ }
+ collectiveAssertSafety = pObjAndAcc;
+ pObjAndAcc = NULL;
+ Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i )
+ {
+ //pObj->pData = Aig_ObjCreatePo( pNew, Aig_NotCond(Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) ) );
+ pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
+ if( pObjAndAcc == NULL )
+ pObjAndAcc = pArgument;
+ else
+ {
+ pObjAndAccDummy = pObjAndAcc;
+ pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAccDummy );
+ }
+ }
+ collectiveAssumeSafety = pObjAndAcc;
+ Aig_ObjCreatePo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) );
+ }
+ else
+ printf("No safety property is specified, hence no safety gate is created\n");
+ }
+
+ //********************************************************************
+ // 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
+ //********************************************************************
+
+ if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE )
+ {
+ pObjSafetyPropertyOutput = Aig_ObjCreatePo( 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_ObjCreatePo( pNew, Aig_ObjChild0Copy(pMatch) );
+ Aig_ObjCreatePo( 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_ObjCreatePo( pNew, pObjSaveOrSaved );
+ nRegCount++;
+ liCreated++;7
+#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
+ //****************************************************************************************************
+
+ if( mode == FULL_BIERE_ONE_LOOP_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE )
+ {
+ 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("Circuit 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("Circuit 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->vPis ), pNew->nRegs );
+
+ Aig_ManPiCleanupBiere( pNew );
+ Aig_ManPoCleanupBiere( pNew );
+
+ Aig_ManCleanup( pNew );
+
+ assert( Aig_ManCheck( pNew ) );
+
+ return pNew;
+}
+
+
+
+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 )
+ if( nodeName_starts_with( pNode, "assert_fair" ) )
+ {
+ Vec_PtrPush( vLive, Aig_ManPo( pAig, i ) );
+ liveCounter++;
+ }
+ printf("Number of liveness property found = %d\n", liveCounter);
+ return vLive;
+}
+
+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 )
+ if( nodeName_starts_with( pNode, "assume_fair" ) )
+ {
+ Vec_PtrPush( vFair, Aig_ManPo( pAig, i ) );
+ fairCounter++;
+ }
+ printf("Number of fairness property found = %d\n", fairCounter);
+ return vFair;
+}
+
+Vec_Ptr_t * populateSafetyAssertionVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig )
+{
+ Abc_Obj_t * pNode;
+ int i, assertSafetyCounter = 0;
+ Vec_Ptr_t * vAssertSafety;
+
+ vAssertSafety = Vec_PtrAlloc( 100 );
+ Abc_NtkForEachPo( pNtk, pNode, i )
+ //if( strstr( Abc_ObjName( pNode ), "Assert") != NULL )
+ if( nodeName_starts_with( pNode, "assert_safety" ) || nodeName_starts_with( pNode, "Assert" ))
+ {
+ Vec_PtrPush( vAssertSafety, Aig_ManPo( pAig, i ) );
+ assertSafetyCounter++;
+ }
+ printf("Number of safety property found = %d\n", assertSafetyCounter);
+ return vAssertSafety;
+}
+
+Vec_Ptr_t * populateSafetyAssumptionVector( Abc_Ntk_t *pNtk, Aig_Man_t *pAig )
+{
+ Abc_Obj_t * pNode;
+ int i, assumeSafetyCounter = 0;
+ Vec_Ptr_t * vAssumeSafety;
+
+ vAssumeSafety = Vec_PtrAlloc( 100 );
+ Abc_NtkForEachPo( pNtk, pNode, i )
+ //if( strstr( Abc_ObjName( pNode ), "Assert") != NULL )
+ if( nodeName_starts_with( pNode, "assume_safety" ) || nodeName_starts_with( pNode, "Assume" ))
+ {
+ Vec_PtrPush( vAssumeSafety, Aig_ManPo( pAig, i ) );
+ assumeSafetyCounter++;
+ }
+ printf("Number of assume_safety property found = %d\n", assumeSafetyCounter);
+ return vAssumeSafety;
+}
+
+void updateNewNetworkNameManager( Abc_Ntk_t *pNtk, Aig_Man_t *pAig, Vec_Ptr_t *vPiNames, Vec_Ptr_t *vLoNames )
+{
+ Aig_Obj_t *pObj;
+ Abc_Obj_t *pNode;
+ int i, ntkObjId;
+
+ pNtk->pManName = Nm_ManCreate( Abc_NtkCiNum( pNtk ) );
+
+ if( vPiNames )
+ {
+ 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 );
+ }
+ }
+ if( vLoNames )
+ {
+ 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 );
+ }
+ }
+
+ Abc_NtkForEachPo(pNtk, pNode, i)
+ {
+ Abc_ObjAssignName(pNode, "assert_safety_", Abc_ObjName(pNode) );
+ }
+
+ // assign latch input names
+ Abc_NtkForEachLatch(pNtk, pNode, i)
+ if ( Nm_ManFindNameById(pNtk->pManName, Abc_ObjFanin0(pNode)->Id) == NULL )
+ Abc_ObjAssignName( Abc_ObjFanin0(pNode), Abc_ObjName(Abc_ObjFanin0(pNode)), NULL );
+}
+
+
+int Abc_CommandAbcLivenessToSafety( 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, *vAssertSafety, *vAssumeSafety;
+ int directive = -1;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ if( argc == 1 )
+ {
+ assert( directive == -1 );
+ directive = FULL_BIERE_MODE;
+ }
+ else
+ {
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "1slh" ) ) != EOF )
+ {
+ switch( c )
+ {
+ case '1':
+ if( directive == -1 )
+ directive = FULL_BIERE_ONE_LOOP_MODE;
+ else
+ {
+ assert( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE || directive == IGNORE_SAFETY_KEEP_LIVENESS_MODE );
+ if( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE )
+ directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE;
+ else
+ directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE;
+ }
+ break;
+ case 's':
+ if( directive == -1 )
+ directive = IGNORE_SAFETY_KEEP_LIVENESS_MODE;
+ else
+ {
+ if( directive != FULL_BIERE_ONE_LOOP_MODE )
+ goto usage;
+ assert(directive == FULL_BIERE_ONE_LOOP_MODE);
+ directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE;
+ }
+ break;
+ case 'l':
+ if( directive == -1 )
+ directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE;
+ else
+ {
+ if( directive != FULL_BIERE_ONE_LOOP_MODE )
+ goto usage;
+ assert(directive == FULL_BIERE_ONE_LOOP_MODE);
+ directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE;
+ }
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if( !Abc_NtkIsStrash( pNtk ) )
+ {
+ printf("The 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 );
+ vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+ vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+ }
+ else
+ {
+ pAig = Abc_NtkToDar( pNtk, 0, 1 );
+ pNtkOld = pNtk;
+ vLive = populateLivenessVector( pNtk, pAig );
+ vFair = populateFairnessVector( pNtk, pAig );
+ vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+ vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+ }
+
+ switch( directive )
+ {
+ case FULL_BIERE_MODE:
+ //if( Vec_PtrSize(vLive) == 0 && Vec_PtrSize(vAssertSafety) == 0 )
+ //{
+ // printf("Input circuit has NO safety and NO liveness property, original network is not disturbed\n");
+ // return 1;
+ //}
+ //else
+ //{
+ pAigNew = LivenessToSafetyTransformation( FULL_BIERE_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+ if( Aig_ManRegNum(pAigNew) != 0 )
+ printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n");
+ break;
+ //}
+ case FULL_BIERE_ONE_LOOP_MODE:
+ //if( Vec_PtrSize(vLive) == 0 && Vec_PtrSize(vAssertSafety) == 0 )
+ //{
+ // printf("Input circuit has NO safety and NO liveness property, original network is not disturbed\n");
+ // return 1;
+ //}
+ //else
+ //{
+ pAigNew = LivenessToSafetyTransformationOneStepLoop( FULL_BIERE_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+ if( Aig_ManRegNum(pAigNew) != 0 )
+ printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n");
+ break;
+ //}
+ case IGNORE_LIVENESS_KEEP_SAFETY_MODE:
+ //if( Vec_PtrSize(vAssertSafety) == 0 )
+ //{
+ // printf("Input circuit has NO safety property, original network is not disturbed\n");
+ // return 1;
+ //}
+ //else
+ //{
+ pAigNew = LivenessToSafetyTransformation( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+ if( Aig_ManRegNum(pAigNew) != 0 )
+ printf("A new circuit is produced with\n\t1 PO - only for safety property; liveness properties are ignored, if any.\n\tno additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n");
+ break;
+ //}
+ case IGNORE_SAFETY_KEEP_LIVENESS_MODE:
+ //if( Vec_PtrSize(vLive) == 0 )
+ //{
+ // printf("Input circuit has NO liveness property, original network is not disturbed\n");
+ // return 1;
+ //}
+ //else
+ //{
+ pAigNew = LivenessToSafetyTransformation( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+ if( Aig_ManRegNum(pAigNew) != 0 )
+ printf("A new circuit is produced with\n\t1 PO - only for liveness property; safety properties are ignored, if any.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n");
+ break;
+ //}
+ case IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE:
+ //if( Vec_PtrSize(vLive) == 0 )
+ //{
+ // printf("Input circuit has NO liveness property, original network is not disturbed\n");
+ // return 1;
+ //}
+ //else
+ //{
+ pAigNew = LivenessToSafetyTransformationOneStepLoop( IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+ if( Aig_ManRegNum(pAigNew) != 0 )
+ printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nShadow registers are not created\n");
+ break;
+ //}
+ }
+
+#if 0
+ if( argc == 1 )
+ {
+ pAigNew = LivenessToSafetyTransformation( FULL_BIERE_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+ if( Aig_ManRegNum(pAigNew) != 0 )
+ printf("New circuit is produced considering all safety, liveness and fairness outputs.\nBiere's logic is created\n");
+ }
+ else
+ {
+ Extra_UtilGetoptReset();
+ c = Extra_UtilGetopt( argc, argv, "1lsh" );
+ if( c == '1' )
+ {
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if( !Abc_NtkIsStrash( pNtk ) )
+ {
+ printf("The 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 );
+ vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+ vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+ }
+ else
+ {
+ pAig = Abc_NtkToDar( pNtk, 0, 1 );
+ pNtkOld = pNtk;
+ vLive = populateLivenessVector( pNtk, pAig );
+ vFair = populateFairnessVector( pNtk, pAig );
+ vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+ vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+ }
+ pAigNew = LivenessToSafetyTransformationOneStepLoop( pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+ }
+ else if( c == 'l' )
+ {
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if( !Abc_NtkIsStrash( pNtk ) )
+ {
+ printf("The 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 );
+ vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+ vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+ }
+ else
+ {
+ pAig = Abc_NtkToDar( pNtk, 0, 1 );
+ pNtkOld = pNtk;
+ vLive = populateLivenessVector( pNtk, pAig );
+ vFair = populateFairnessVector( pNtk, pAig );
+ vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+ vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+ }
+ pAigNew = LivenessToSafetyTransformation( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+ if( Aig_ManRegNum(pAigNew) != 0 )
+ printf("New circuit is produced ignoring liveness outputs!\nOnly safety outputs are kept.\nBiere's logic is not created\n");
+ }
+ else if( c == 's' )
+ {
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if( !Abc_NtkIsStrash( pNtk ) )
+ {
+ printf("The 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 );
+ vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+ vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+ }
+ else
+ {
+ pAig = Abc_NtkToDar( pNtk, 0, 1 );
+ pNtkOld = pNtk;
+ vLive = populateLivenessVector( pNtk, pAig );
+ vFair = populateFairnessVector( pNtk, pAig );
+ vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+ vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+ }
+ pAigNew = LivenessToSafetyTransformation( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+ if( Aig_ManRegNum(pAigNew) != 0 )
+ printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nBiere's logic is created\n");
+ }
+ else if( c == 'h' )
+ goto usage;
+ else
+ goto usage;
+ }
+#endif
+
+#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 );
+ pNtkNew->pName = Abc_UtilStrsav( pAigNew->pName );
+
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" );
+
+ updateNewNetworkNameManager( pNtkNew, pAigNew, vecPiNames, vecLoNames );
+ Abc_FrameSetCurrentNetwork( pAbc, pNtkNew );
+
+#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;
+
+usage:
+ fprintf( stdout, "usage: l2s [-1lsh]\n" );
+ fprintf( stdout, "\t performs Armin Biere's live-to-safe transformation\n" );
+ fprintf( stdout, "\t-1 : no shadow logic, presume all loops are self loops\n");
+ fprintf( stdout, "\t-l : ignore liveness and fairness outputs\n");
+ fprintf( stdout, "\t-s : ignore safety assertions and assumptions\n");
+ fprintf( stdout, "\t-h : print command usage\n");
+ return 1;
+}
+
+Vec_Int_t * prepareFlopVector( Aig_Man_t * pAig, int vectorLength )
+{
+ Vec_Int_t *vFlops;
+ int i;
+
+ vFlops = Vec_IntAlloc( vectorLength );
+
+ for( i=0; i<vectorLength; i++ )
+ Vec_IntPush( vFlops, i );
+
+#if 0
+ Vec_IntPush( vFlops, 19 );
+ Vec_IntPush( vFlops, 20 );
+ Vec_IntPush( vFlops, 23 );
+ Vec_IntPush( vFlops, 24 );
+ //Vec_IntPush( vFlops, 2 );
+ //Vec_IntPush( vFlops, 3 );
+ //Vec_IntPush( vFlops, 4 );
+ //Vec_IntPush( vFlops, 5 );
+ //Vec_IntPush( vFlops, 8 );
+ //Vec_IntPush( vFlops, 9 );
+ //Vec_IntPush( vFlops, 10 );
+ //Vec_IntPush( vFlops, 11 );
+ //Vec_IntPush( vFlops, 0 );
+ //Vec_IntPush( vFlops, 0 );
+#endif
+
+ return vFlops;
+}
+
+int Abc_CommandAbcLivenessToSafetyAbstraction( 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, *vAssertSafety, *vAssumeSafety;
+ int directive = -1;
+ Vec_Int_t * vFlops;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ if( argc == 1 )
+ {
+ assert( directive == -1 );
+ directive = FULL_BIERE_MODE;
+ }
+ else
+ {
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "1slh" ) ) != EOF )
+ {
+ switch( c )
+ {
+ case '1':
+ if( directive == -1 )
+ directive = FULL_BIERE_ONE_LOOP_MODE;
+ else
+ {
+ assert( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE || directive == IGNORE_SAFETY_KEEP_LIVENESS_MODE );
+ if( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE )
+ directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE;
+ else
+ directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE;
+ }
+ break;
+ case 's':
+ if( directive == -1 )
+ directive = IGNORE_SAFETY_KEEP_LIVENESS_MODE;
+ else
+ {
+ if( directive != FULL_BIERE_ONE_LOOP_MODE )
+ goto usage;
+ assert(directive == FULL_BIERE_ONE_LOOP_MODE);
+ directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE;
+ }
+ break;
+ case 'l':
+ if( directive == -1 )
+ directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE;
+ else
+ {
+ if( directive != FULL_BIERE_ONE_LOOP_MODE )
+ goto usage;
+ assert(directive == FULL_BIERE_ONE_LOOP_MODE);
+ directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE;
+ }
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if( !Abc_NtkIsStrash( pNtk ) )
+ {
+ printf("The 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 );
+ vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+ vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+ }
+ else
+ {
+ pAig = Abc_NtkToDar( pNtk, 0, 1 );
+ pNtkOld = pNtk;
+ vLive = populateLivenessVector( pNtk, pAig );
+ vFair = populateFairnessVector( pNtk, pAig );
+ vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+ vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+ }
+
+ vFlops = prepareFlopVector( pAig, Aig_ManRegNum(pAig)%2 == 0? Aig_ManRegNum(pAig)/2 : (Aig_ManRegNum(pAig)-1)/2);
+
+ //vFlops = prepareFlopVector( pAig, 100 );
+
+ switch( directive )
+ {
+ case FULL_BIERE_MODE:
+ //if( Vec_PtrSize(vLive) == 0 && Vec_PtrSize(vAssertSafety) == 0 )
+ //{
+ // printf("Input circuit has NO safety and NO liveness property, original network is not disturbed\n");
+ // return 1;
+ //}
+ //else
+ //{
+ pAigNew = LivenessToSafetyTransformationAbs( FULL_BIERE_MODE, pNtk, pAig, vFlops, vLive, vFair, vAssertSafety, vAssumeSafety );
+ if( Aig_ManRegNum(pAigNew) != 0 )
+ printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n");
+ break;
+ //}
+ case FULL_BIERE_ONE_LOOP_MODE:
+ //if( Vec_PtrSize(vLive) == 0 && Vec_PtrSize(vAssertSafety) == 0 )
+ //{
+ // printf("Input circuit has NO safety and NO liveness property, original network is not disturbed\n");
+ // return 1;
+ //}
+ //else
+ //{
+ pAigNew = LivenessToSafetyTransformationOneStepLoop( FULL_BIERE_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+ if( Aig_ManRegNum(pAigNew) != 0 )
+ printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n");
+ break;
+ //}
+ case IGNORE_LIVENESS_KEEP_SAFETY_MODE:
+ //if( Vec_PtrSize(vAssertSafety) == 0 )
+ //{
+ // printf("Input circuit has NO safety property, original network is not disturbed\n");
+ // return 1;
+ //}
+ //else
+ //{
+ pAigNew = LivenessToSafetyTransformationAbs( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vFlops, vLive, vFair, vAssertSafety, vAssumeSafety );
+ if( Aig_ManRegNum(pAigNew) != 0 )
+ printf("A new circuit is produced with\n\t1 PO - only for safety property; liveness properties are ignored, if any.\n\tno additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n");
+ break;
+ //}
+ case IGNORE_SAFETY_KEEP_LIVENESS_MODE:
+ //if( Vec_PtrSize(vLive) == 0 )
+ //{
+ // printf("Input circuit has NO liveness property, original network is not disturbed\n");
+ // return 1;
+ //}
+ //else
+ //{
+ pAigNew = LivenessToSafetyTransformationAbs( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vFlops, vLive, vFair, vAssertSafety, vAssumeSafety );
+ if( Aig_ManRegNum(pAigNew) != 0 )
+ printf("A new circuit is produced with\n\t1 PO - only for liveness property; safety properties are ignored, if any.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n");
+ break;
+ //}
+ case IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE:
+ //if( Vec_PtrSize(vLive) == 0 )
+ //{
+ // printf("Input circuit has NO liveness property, original network is not disturbed\n");
+ // return 1;
+ //}
+ //else
+ //{
+ pAigNew = LivenessToSafetyTransformationOneStepLoop( IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+ if( Aig_ManRegNum(pAigNew) != 0 )
+ printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nShadow registers are not created\n");
+ break;
+ //}
+ }
+
+ pNtkNew = Abc_NtkFromAigPhase( pAigNew );
+ pNtkNew->pName = Abc_UtilStrsav( pAigNew->pName );
+
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" );
+
+ updateNewNetworkNameManager( pNtkNew, pAigNew, vecPiNames,vecLoNames );
+ Abc_FrameSetCurrentNetwork( pAbc, pNtkNew );
+
+#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;
+
+usage:
+ fprintf( stdout, "usage: l2s [-1lsh]\n" );
+ fprintf( stdout, "\t performs Armin Biere's live-to-safe transformation\n" );
+ fprintf( stdout, "\t-1 : no shadow logic, presume all loops are self loops\n");
+ fprintf( stdout, "\t-l : ignore liveness and fairness outputs\n");
+ fprintf( stdout, "\t-s : ignore safety assertions and assumptions\n");
+ fprintf( stdout, "\t-h : print command usage\n");
+ return 1;
+}
+
+Aig_Man_t * LivenessToSafetyTransformationWithLTL( int mode, Abc_Ntk_t * pNtk, Aig_Man_t * p,
+ Vec_Ptr_t *vLive, Vec_Ptr_t *vFair, Vec_Ptr_t *vAssertSafety, Vec_Ptr_t *vAssumeSafety,
+ int *numLtlProcessed, Vec_Ptr_t *ltlBuffer )
+{
+ Aig_Man_t * pNew;
+ int i, ii, iii, nRegCount;
+ Aig_Obj_t * pObjSavePi;
+ Aig_Obj_t *pObjSavedLo, *pObjSavedLi;
+ Aig_Obj_t *pObj, *pMatch;
+ Aig_Obj_t *pObjSaveOrSaved, *pObjSaveAndNotSaved, *pObjSavedLoAndEquality;
+ Aig_Obj_t *pObjShadowLo, *pObjShadowLi, *pObjShadowLiDriver;
+ Aig_Obj_t *pObjXor, *pObjXnor, *pObjAndAcc;
+ Aig_Obj_t *pObjLive, *pObjSafetyGate;
+ Aig_Obj_t *pObjSafetyPropertyOutput;
+ Aig_Obj_t *pObjOriginalSafetyPropertyOutput;
+ Aig_Obj_t *pDriverImage, *pArgument, *collectiveAssertSafety, *collectiveAssumeSafety;
+ Aig_Obj_t *pNegatedSafetyConjunction = NULL;
+ Aig_Obj_t *pObjSafetyAndLiveToSafety;
+ char *nodeName, *pFormula;
+ int piCopied = 0, liCopied = 0, loCopied = 0, liCreated = 0, loCreated = 0, piVecIndex = 0, liveLatch = 0, fairLatch = 0;
+ Vec_Ptr_t *vSignal, *vTopASTNodeArray;
+ ltlNode *pEnrtyGLOBALLY;
+ ltlNode *topNodeOfAST, *tempTopASTNode;
+ Vec_Vec_t *vAigGFMap;
+ Vec_Ptr_t *vSignalMemory, *vGFFlopMemory, *vPoForLtlProps;
+ Vec_Ptr_t *vecInputLtlFormulae;
+
+ 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 ) );
+
+ //****************************************************************
+ //step0: Parsing the LTL formula
+ //****************************************************************
+ //Vec_PtrForEachEntry( char *, pNtk->vLtlProperties, pFormula, i )
+ // printf("\ninput LTL formula [%d] = %s\n", i, pFormula );
+
+
+#ifdef MULTIPLE_LTL_FORMULA
+
+
+ //***************************************************************************
+ //Reading input LTL formulae from Ntk data-structure and creating
+ //AST for them, Steps involved:
+ // parsing -> AST creation -> well-formedness check -> signal name check
+ //***************************************************************************
+
+ //resetting numLtlProcessed
+ *numLtlProcessed = 0;
+
+ if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+ {
+ //if( ltlBuffer )
+ vecInputLtlFormulae = ltlBuffer;
+ //vecInputLtlFormulae = pNtk->vLtlProperties;
+ if( vecInputLtlFormulae )
+ {
+ vTopASTNodeArray = Vec_PtrAlloc( Vec_PtrSize( vecInputLtlFormulae ) );
+ printf("\n");
+ Vec_PtrForEachEntry( char *, vecInputLtlFormulae, pFormula, i )
+ {
+ tempTopASTNode = parseFormulaCreateAST( pFormula );
+ //traverseAbstractSyntaxTree_postFix( tempTopASTNode );
+ if( tempTopASTNode )
+ {
+ printf("Formula %d: AST is created, ", i+1);
+ if( isWellFormed( tempTopASTNode ) )
+ printf("Well-formedness check PASSED, ");
+ else
+ {
+ printf("Well-formedness check FAILED!!\n");
+ printf("AST will be ignored for formula %d, no extra logic will be added for this formula\n", i+1 );
+ //do memory management to free the created AST
+ continue;
+ }
+ if( checkSignalNameExistence( pNtk, tempTopASTNode ) )
+ printf("Signal check PASSED\n");
+ else
+ {
+ printf("Signal check FAILED!!");
+ printf("AST will be ignored for formula %d, no extra logic will be added for this formula\n", i+1 );
+ //do memory management to free the created AST
+ continue;
+ }
+ Vec_PtrPush( vTopASTNodeArray, tempTopASTNode );
+ (*numLtlProcessed)++;
+ }
+ else
+ printf("\nNo AST has been created for formula %d, no extra logic will be added\n", i+1 );
+ }
+ }
+ printf("\n");
+ if( Vec_PtrSize( vTopASTNodeArray ) == 0 )
+ {
+ //printf("\nNo AST has been created for any formula; hence the circuit is left untouched\n");
+ printf("\nCurrently aborting, need to take care when Vec_PtrSize( vTopASTNodeArray ) == 0\n");
+ exit(0);
+ }
+ }
+
+ //****************************************************************
+ // 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 = (char *)malloc( strlen( pNtk->pName ) + strlen("_l3s") + 1 );
+ sprintf(pNew->pName, "%s_%s", pNtk->pName, "l3s");
+ 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_ObjCreatePi(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
+ //****************************************************************
+ if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+ {
+ pObjSavePi = Aig_ObjCreatePi( pNew );
+ nodeName = "SAVE_BIERE",
+ Vec_PtrPush( vecPiNames, nodeName );
+ }
+
+ //****************************************************************
+ // Step 5: create register outputs
+ //****************************************************************
+ Saig_ManForEachLo( p, pObj, i )
+ {
+ loCopied++;
+ pObj->pData = Aig_ObjCreatePi(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( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+ {
+ loCreated++;
+ pObjSavedLo = Aig_ObjCreatePi( pNew );
+ Vec_PtrPush( vecLos, pObjSavedLo );
+ nodeName = "SAVED_LO";
+ Vec_PtrPush( vecLoNames, nodeName );
+ }
+
+ //****************************************************************
+ // Step 7: create the OR gate and the AND gate directly fed by "SAVE" Pi
+ //****************************************************************
+ if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+ {
+ pObjSaveOrSaved = Aig_Or( pNew, pObjSavePi, pObjSavedLo );
+ pObjSaveAndNotSaved = Aig_And( pNew, pObjSavePi, Aig_Not(pObjSavedLo) );
+ }
+
+ //********************************************************************
+ // Step 8: create internal nodes
+ //********************************************************************
+ Aig_ManForEachNode( p, pObj, i )
+ {
+ pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+ }
+
+
+ //********************************************************************
+ // Step 8.x : create PO for each safety assertions
+ // NOTE : Here the output is purposely inverted as it will be thrown to
+ // dprove
+ //********************************************************************
+ assert( pNegatedSafetyConjunction == NULL );
+ if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE)
+ {
+ if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) == 0 )
+ {
+ pObjAndAcc = Aig_ManConst1( pNew );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i )
+ {
+ pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
+ pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc );
+ }
+ pNegatedSafetyConjunction = Aig_Not(pObjAndAcc);
+ if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE )
+ pObjOriginalSafetyPropertyOutput = Aig_ObjCreatePo( pNew, Aig_Not(pObjAndAcc) );
+ }
+ else if( Vec_PtrSize( vAssertSafety ) != 0 && Vec_PtrSize( vAssumeSafety ) != 0 )
+ {
+ pObjAndAcc = Aig_ManConst1( pNew );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vAssertSafety, pObj, i )
+ {
+ pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
+ pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc );
+ }
+ collectiveAssertSafety = pObjAndAcc;
+
+ pObjAndAcc = Aig_ManConst1( pNew );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vAssumeSafety, pObj, i )
+ {
+ pArgument = Aig_NotCond( (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0( pObj ) );
+ pObjAndAcc = Aig_And( pNew, pArgument, pObjAndAcc );
+ }
+ collectiveAssumeSafety = pObjAndAcc;
+ pNegatedSafetyConjunction = Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety );
+ if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE )
+ pObjOriginalSafetyPropertyOutput = Aig_ObjCreatePo( pNew, Aig_And( pNew, Aig_Not(collectiveAssertSafety), collectiveAssumeSafety ) );
+ }
+ else
+ {
+ printf("WARNING!! No safety property is found, a new (negated) constant 1 output is created\n");
+ pNegatedSafetyConjunction = Aig_Not( Aig_ManConst1(pNew) );
+ if( mode == FULL_BIERE_MODE || mode == IGNORE_LIVENESS_KEEP_SAFETY_MODE )
+ pObjOriginalSafetyPropertyOutput = Aig_ObjCreatePo( pNew, Aig_Not( Aig_ManConst1(pNew) ) );
+ }
+ }
+ assert( pNegatedSafetyConjunction != NULL );
+
+ //********************************************************************
+ // Step 9: create the safety property output gate for the liveness properties
+ // discuss with Sat/Alan for an alternative implementation
+ //********************************************************************
+ if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+ {
+ vPoForLtlProps = Vec_PtrAlloc( Vec_PtrSize( vTopASTNodeArray ) );
+ if( Vec_PtrSize( vTopASTNodeArray ) )
+ {
+ //no effective AST for any input LTL property
+ //must do something graceful
+ }
+ for( i=0; i<Vec_PtrSize( vTopASTNodeArray ); i++ )
+ {
+ pObjSafetyPropertyOutput = Aig_ObjCreatePo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData );
+ Vec_PtrPush( vPoForLtlProps, pObjSafetyPropertyOutput );
+ }
+ }
+
+ //*************************************************************************************
+ // Step 10: Placeholder PO's were created for Liveness property outputs in the
+ // last step. FYI, # of new liveness property outputs = # of LTL properties in the circuit
+ // It is time for creation of loop LI's and other stuff
+ // Now creating register inputs for the original flops
+ //*************************************************************************************
+ nRegCount = 0;
+
+ Saig_ManForEachLo( p, pObj, i )
+ {
+ pMatch = Saig_ObjLoToLi( p, pObj );
+ Aig_ObjCreatePo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pMatch)->pData, Aig_ObjFaninC0( pMatch ) ) );
+ nRegCount++;
+ liCopied++;
+ }
+
+ //*************************************************************************************
+ // Step 11: create register input corresponding to the register "saved"
+ //*************************************************************************************
+ if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+ {
+ #ifndef DUPLICATE_CKT_DEBUG
+ pObjSavedLi = Aig_ObjCreatePo( pNew, pObjSaveOrSaved );
+ nRegCount++;
+ liCreated++;
+
+ pObjAndAcc = Aig_ManConst1( pNew );
+
+ //*************************************************************************************
+ // Step 11: create the family of shadow registers, then create the cascade of Xnor
+ // and And gates for the comparator
+ //*************************************************************************************
+ Saig_ManForEachLo( p, pObj, i )
+ {
+ //printf("\nKEMON RENDY = %s", Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i )) );
+ //top|route0_target0_queue_with_credit0_queue0
+ //top|route0_master0_queue2
+ // if( strcmp( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "top|route0_queue1_num[0]" ) == 0
+ // || strcmp( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "top|route0_queue1_num[1]" ) == 0 || strcmp( Abc_ObjName( Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ) ), "top|route0_queue1_num[2]" ) == 0 )
+ {
+ pObjShadowLo = Aig_ObjCreatePi( 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, pObjSaveAndNotSaved, (Aig_Obj_t *)pObj->pData, pObjShadowLo );
+ pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver );
+ nRegCount++;
+ loCreated++; liCreated++;
+
+ pObjXor = Aig_Exor( pNew, (Aig_Obj_t *)pObj->pData, pObjShadowLo );
+ pObjXnor = Aig_Not( pObjXor );
+
+ pObjAndAcc = Aig_And( pNew, pObjXnor, pObjAndAcc );
+ }
+ }
+
+ // 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
+
+ //*************************************************************************************
+ // Step 11: logic for LTL properties:- (looped & ~theta) where theta is the input ltl
+ // property
+ // Description of some data-structure:
+ //-------------------------------------------------------------------------------------
+ // Name | Type | Purpose
+ //-------------------------------------------------------------------------------------
+ // vSignalMemory | Vec_Ptr_t * | A vector across all ASTs of the LTL properties
+ // | | It remembers if OR+Latch for GF node has already been
+ // | | created for a particular signal.
+ // | |
+ // vGFFlopMemory | Vec_Ptr_t * | A vector across all ASTs of the LTL properties
+ // | | remembers if OR+Latch of a GF node has already been created
+ // | |
+ // vSignal | Vec_Ptr_t * | vector for each AST; contains pointers from GF nodes
+ // | | to AIG signals
+ // | |
+ // vAigGFMap | Vec_Vec_t * | vAigGFMap[ index ] = vector of GF nodes pointing to
+ // | | the same AIG node; "index" is the index of that
+ // | | AIG node in the vector vSignal
+ //*************************************************************************************
+
+ vSignalMemory = Vec_PtrAlloc(10);
+ vGFFlopMemory = Vec_PtrAlloc(10);
+
+ Vec_PtrForEachEntry( ltlNode *, vTopASTNodeArray, topNodeOfAST, iii )
+ {
+ vSignal = Vec_PtrAlloc( 10 );
+ vAigGFMap = Vec_VecAlloc( 10 );
+
+ //*************************************************************************************
+ //Step 11a: for the current AST, find out the leaf level Boolean signal pointers from
+ // the NEW aig.
+ //*************************************************************************************
+ populateBoolWithAigNodePtr( pNtk, p, pNew, topNodeOfAST );
+ assert( checkAllBoolHaveAIGPointer( topNodeOfAST ) );
+
+ //*************************************************************************************
+ //Step 11b: for each GF node, compute the pointer in AIG that it should point to
+ // In particular, if the subtree below GF is some Boolean crown (including the case
+ // of simple negation, create new logic and populate the AIG pointer in GF node
+ // accordingly
+ //*************************************************************************************
+ populateAigPointerUnitGF( pNew, topNodeOfAST, vSignal, vAigGFMap );
+
+ //*************************************************************************************
+ //Step 11c: everything below GF are computed. Now, it is time to create logic for individual
+ // GF nodes (i.e. the OR gate and the latch and the Boolean crown of the AST
+ //*************************************************************************************
+ Vec_PtrForEachEntry( Aig_Obj_t *, vSignal, pObj, i )
+ {
+ //*********************************************************
+ // Step 11c.1: if the OR+Latch of the particular signal is
+ // not already created, create it. It may have already been
+ // created from another property, so check it before creation
+ //*********************************************************
+ if( Vec_PtrFind( vSignalMemory, pObj ) == -1 )
+ {
+ liveLatch++;
+
+ pDriverImage = pObj;
+ pObjShadowLo = Aig_ObjCreatePi( pNew );
+ pObjShadowLiDriver = Aig_Or( pNew, pObjShadowLo, Aig_And( pNew, pDriverImage, pObjSaveOrSaved ) );
+ pObjShadowLi = Aig_ObjCreatePo( pNew, pObjShadowLiDriver );
+
+ nRegCount++;
+ loCreated++; liCreated++;
+
+ Vec_PtrPush( vSignalMemory, pObj );
+ Vec_PtrPush( vGFFlopMemory, pObjShadowLo );
+
+ #if 1
+ #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" );
+ nodeName = (char *)malloc( 20 );
+ sprintf( nodeName, "n%d__%s", Aig_ObjId(pObjShadowLo), "GF_flop" );
+ Vec_PtrPush( vecLoNames, nodeName );
+ #endif
+ #endif
+ }
+ else
+ pObjShadowLo = (Aig_Obj_t *)Vec_PtrEntry( vGFFlopMemory, Vec_PtrFind( vSignalMemory, pObj ) );
+
+ Vec_VecForEachEntryLevel( ltlNode *, vAigGFMap, pEnrtyGLOBALLY, ii, i )
+ setAIGNodePtrOfGloballyNode( pEnrtyGLOBALLY, pObjShadowLo);
+
+
+ //#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
+
+ }
+
+ //*********************************************************
+ //Step 11c.2: creating the Boolean crown
+ //*********************************************************
+ buildLogicFromLTLNode( pNew, topNodeOfAST );
+
+ //*********************************************************
+ //Step 11c.3: creating logic for (looped & ~theta) and patching
+ // it with the proper PO
+ //Note: if ALLOW_SAFETY_PROPERTIES is defined then the final AND
+ //gate is a conjunction of safety & liveness, i.e. SAFETY & (looped => theta)
+ //since ABC convention demands a NOT gate at the end, the property logic
+ //becomes !( SAFETY & (looped => theta) ) = !SAFETY + (looped & !theta)
+ //*********************************************************
+ pObjLive = retriveAIGPointerFromLTLNode( topNodeOfAST );
+ pObjSafetyGate = Aig_And( pNew, pObjSavedLoAndEquality, Aig_Not(pObjLive) );
+ #ifdef ALLOW_SAFETY_PROPERTIES
+ printf("liveness output is conjoined with safety assertions\n");
+ pObjSafetyAndLiveToSafety = Aig_Or( pNew, pObjSafetyGate, pNegatedSafetyConjunction );
+ pObjSafetyPropertyOutput = (Aig_Obj_t *)Vec_PtrEntry( vPoForLtlProps, iii );
+ Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyAndLiveToSafety );
+ #else
+ pObjSafetyPropertyOutput = Vec_PtrEntry( vPoForLtlProps, iii );
+ Aig_ObjPatchFanin0( pNew, pObjSafetyPropertyOutput, pObjSafetyGate );
+ #endif
+ //refreshing vSignal and vAigGFMap arrays
+ Vec_PtrFree( vSignal );
+ Vec_VecFree( vAigGFMap );
+ }
+
+ #endif
+ }
+#endif
+
+ Aig_ManSetRegNum( pNew, nRegCount );
+
+ Aig_ManPiCleanupBiere( pNew );
+ Aig_ManPoCleanupBiere( pNew );
+
+ Aig_ManCleanup( pNew );
+
+ assert( Aig_ManCheck( pNew ) );
+
+ if( mode == FULL_BIERE_MODE || mode == IGNORE_SAFETY_KEEP_LIVENESS_MODE )
+ {
+ assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vPos, Saig_ManPoNum(pNew)+Aig_ObjPioNum(pObjSavedLo)-Saig_ManPiNum(p)-1) == pObjSavedLi);
+ assert( Saig_ManPiNum( p ) + 1 == Saig_ManPiNum( pNew ) );
+ //assert( Saig_ManRegNum( pNew ) == Saig_ManRegNum( p ) * 2 + 1 + liveLatch + fairLatch );
+ }
+
+
+ return pNew;
+}
+
+int Abc_CommandAbcLivenessToSafetyWithLTL( 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, *vAssertSafety, *vAssumeSafety;
+ int directive = -1;
+ char *ltfFormulaString = NULL;
+ int LTL_FLAG = 0, numOfLtlPropOutput;
+ Vec_Ptr_t *ltlBuffer;
+
+ pNtk = Abc_FrameReadNtk(pAbc);
+ pOut = Abc_FrameReadOut(pAbc);
+ pErr = Abc_FrameReadErr(pAbc);
+
+ if( argc == 1 )
+ {
+ assert( directive == -1 );
+ directive = FULL_BIERE_MODE;
+ }
+ else
+ {
+ Extra_UtilGetoptReset();
+ while ( ( c = Extra_UtilGetopt( argc, argv, "1slhf" ) ) != EOF )
+ {
+ switch( c )
+ {
+ case '1':
+ if( directive == -1 )
+ directive = FULL_BIERE_ONE_LOOP_MODE;
+ else
+ {
+ assert( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE || directive == IGNORE_SAFETY_KEEP_LIVENESS_MODE );
+ if( directive == IGNORE_LIVENESS_KEEP_SAFETY_MODE )
+ directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE;
+ else
+ directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE;
+ }
+ break;
+ case 's':
+ if( directive == -1 )
+ directive = IGNORE_SAFETY_KEEP_LIVENESS_MODE;
+ else
+ {
+ if( directive != FULL_BIERE_ONE_LOOP_MODE )
+ goto usage;
+ assert(directive == FULL_BIERE_ONE_LOOP_MODE);
+ directive = IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE;
+ }
+ break;
+ case 'l':
+ if( directive == -1 )
+ directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE;
+ else
+ {
+ if( directive != FULL_BIERE_ONE_LOOP_MODE )
+ goto usage;
+ assert(directive == FULL_BIERE_ONE_LOOP_MODE);
+ directive = IGNORE_LIVENESS_KEEP_SAFETY_MODE;
+ }
+ break;
+ case 'f':
+ //assert( argc >= 3 );
+ //vecLtlFormula = Vec_PtrAlloc( argc - 2 );
+ //if( argc >= 3 )
+ //{
+ // for( t=3; t<=argc; t++ )
+ // {
+ // printf("argv[%d] = %s\n", t-1, argv[t-1]);
+ // Vec_PtrPush( vecLtlFormula, argv[t-1] );
+ // }
+ //}
+ //printf("argv[argc] = %s\n", argv[argc-1]);
+ //ltfFormulaString = argv[2];
+
+ //LTL_FLAG = 1;
+ printf("\nILLEGAL FLAG: aborting....\n");
+ exit(0);
+ break;
+ case 'h':
+ goto usage;
+ default:
+ goto usage;
+ }
+ }
+ }
+
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if( !Abc_NtkIsStrash( pNtk ) )
+ {
+ printf("The 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 );
+ vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+ vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+ }
+ else
+ {
+ pAig = Abc_NtkToDar( pNtk, 0, 1 );
+ pNtkOld = pNtk;
+ vLive = populateLivenessVector( pNtk, pAig );
+ vFair = populateFairnessVector( pNtk, pAig );
+ vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+ vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+ }
+
+ if( pAbc->vLTLProperties_global != NULL )
+ ltlBuffer = pAbc->vLTLProperties_global;
+ else
+ ltlBuffer = NULL;
+
+ switch( directive )
+ {
+ case FULL_BIERE_MODE:
+ pAigNew = LivenessToSafetyTransformationWithLTL( FULL_BIERE_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety, &numOfLtlPropOutput, ltlBuffer );
+ if( Aig_ManRegNum(pAigNew) != 0 )
+ printf("A new circuit is produced with\n\t%d POs - one for safety and %d for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n", numOfLtlPropOutput+1, numOfLtlPropOutput);
+ break;
+
+ case FULL_BIERE_ONE_LOOP_MODE:
+ pAigNew = LivenessToSafetyTransformationOneStepLoop( FULL_BIERE_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+ if( Aig_ManRegNum(pAigNew) != 0 )
+ printf("A new circuit is produced with\n\t2 POs - one for safety and one for liveness.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n");
+ break;
+
+ case IGNORE_LIVENESS_KEEP_SAFETY_MODE:
+ pAigNew = LivenessToSafetyTransformationWithLTL( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety, &numOfLtlPropOutput, ltlBuffer );
+ assert( numOfLtlPropOutput == 0 );
+ if( Aig_ManRegNum(pAigNew) != 0 )
+ printf("A new circuit is produced with\n\t1 PO - only for safety property; liveness properties are ignored, if any.\n\tno additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created\n\tnon-property POs are suppressed\n");
+ break;
+
+ case IGNORE_SAFETY_KEEP_LIVENESS_MODE:
+ pAigNew = LivenessToSafetyTransformationWithLTL( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety, &numOfLtlPropOutput, ltlBuffer );
+ if( Aig_ManRegNum(pAigNew) != 0 )
+ printf("A new circuit is produced with\n\t%d PO - only for liveness property; safety properties are ignored, if any.\n\tone additional input is added (due to Biere's nondeterminism)\n\tshadow flops are not created if the original circuit is combinational\n\tnon-property POs are suppressed\n", numOfLtlPropOutput);
+ break;
+
+ case IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE:
+ pAigNew = LivenessToSafetyTransformationOneStepLoop( IGNORE_SAFETY_KEEP_LIVENESS_ONE_LOOP_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+ if( Aig_ManRegNum(pAigNew) != 0 )
+ printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nShadow registers are not created\n");
+ break;
+ }
+
+#if 0
+ if( argc == 1 )
+ {
+ pAigNew = LivenessToSafetyTransformation( FULL_BIERE_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+ if( Aig_ManRegNum(pAigNew) != 0 )
+ printf("New circuit is produced considering all safety, liveness and fairness outputs.\nBiere's logic is created\n");
+ }
+ else
+ {
+ Extra_UtilGetoptReset();
+ c = Extra_UtilGetopt( argc, argv, "1lsh" );
+ if( c == '1' )
+ {
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if( !Abc_NtkIsStrash( pNtk ) )
+ {
+ printf("The 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 );
+ vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+ vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+ }
+ else
+ {
+ pAig = Abc_NtkToDar( pNtk, 0, 1 );
+ pNtkOld = pNtk;
+ vLive = populateLivenessVector( pNtk, pAig );
+ vFair = populateFairnessVector( pNtk, pAig );
+ vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+ vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+ }
+ pAigNew = LivenessToSafetyTransformationOneStepLoop( pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+ }
+ else if( c == 'l' )
+ {
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+ if( !Abc_NtkIsStrash( pNtk ) )
+ {
+ printf("The 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 );
+ vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+ vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+ }
+ else
+ {
+ pAig = Abc_NtkToDar( pNtk, 0, 1 );
+ pNtkOld = pNtk;
+ vLive = populateLivenessVector( pNtk, pAig );
+ vFair = populateFairnessVector( pNtk, pAig );
+ vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+ vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+ }
+ pAigNew = LivenessToSafetyTransformation( IGNORE_LIVENESS_KEEP_SAFETY_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+ if( Aig_ManRegNum(pAigNew) != 0 )
+ printf("New circuit is produced ignoring liveness outputs!\nOnly safety outputs are kept.\nBiere's logic is not created\n");
+ }
+ else if( c == 's' )
+ {
+ if ( pNtk == NULL )
+ {
+ fprintf( pErr, "Empty network.\n" );
+ return 1;
+ }
+
+ if( !Abc_NtkIsStrash( pNtk ) )
+ {
+ printf("The 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 );
+ vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+ vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+ }
+ else
+ {
+ pAig = Abc_NtkToDar( pNtk, 0, 1 );
+ pNtkOld = pNtk;
+ vLive = populateLivenessVector( pNtk, pAig );
+ vFair = populateFairnessVector( pNtk, pAig );
+ vAssertSafety = populateSafetyAssertionVector( pNtk, pAig );
+ vAssumeSafety = populateSafetyAssumptionVector( pNtk, pAig );
+ }
+ pAigNew = LivenessToSafetyTransformation( IGNORE_SAFETY_KEEP_LIVENESS_MODE, pNtk, pAig, vLive, vFair, vAssertSafety, vAssumeSafety );
+ if( Aig_ManRegNum(pAigNew) != 0 )
+ printf("New circuit is produced ignoring safety outputs!\nOnly liveness and fairness outputs are considered.\nBiere's logic is created\n");
+ }
+ else if( c == 'h' )
+ goto usage;
+ else
+ goto usage;
+ }
+#endif
+
+#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 );
+ pNtkNew->pName = Abc_UtilStrsav( pAigNew->pName );
+
+ if ( !Abc_NtkCheck( pNtkNew ) )
+ fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" );
+
+ updateNewNetworkNameManager( pNtkNew, pAigNew, vecPiNames, vecLoNames );
+ Abc_FrameSetCurrentNetwork( pAbc, pNtkNew );
+
+#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;
+
+usage:
+ fprintf( stdout, "usage: l3s [-1lsh]\n" );
+ fprintf( stdout, "\t performs Armin Biere's live-to-safe transformation\n" );
+ fprintf( stdout, "\t-1 : no shadow logic, presume all loops are self loops\n");
+ fprintf( stdout, "\t-l : ignore liveness and fairness outputs\n");
+ fprintf( stdout, "\t-s : ignore safety assertions and assumptions\n");
+ fprintf( stdout, "\t-h : print command usage\n");
+ return 1;
+}
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/src/proof/live/liveness_sim.c b/src/proof/live/liveness_sim.c
new file mode 100644
index 00000000..50153e50
--- /dev/null
+++ b/src/proof/live/liveness_sim.c
@@ -0,0 +1,848 @@
+/**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 "src/base/main/main.h"
+#include "src/aig/aig/aig.h"
+#include "src/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_ManForEachPi( pAigNew, pObj, index )
+ if( pObj == pObjPivot )
+ break;
+ assert( index < Aig_ManPiNum( pAigNew ) - Aig_ManRegNum( pAigNew ) );
+ if( index == Saig_ManPiNum( pAigNew ) - 1 )
+ return "SAVE_BIERE";
+ else
+ {
+ pObjOld = Aig_ManPi( 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_ManPi( 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_ManPi( 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";
+}
+
+extern Vec_Ptr_t *vecPis, *vecPiNames;
+extern Vec_Ptr_t *vecLos, *vecLoNames;
+
+
+static int Aig_ManPiCleanupBiere( Aig_Man_t * p )
+{
+ int k = 0, nPisOld = Aig_ManPiNum(p);
+
+ p->nObjs[AIG_OBJ_PI] = Vec_PtrSize( p->vPis );
+ if ( Aig_ManRegNum(p) )
+ p->nTruePis = Aig_ManPiNum(p) - Aig_ManRegNum(p);
+
+ return nPisOld - Aig_ManPiNum(p);
+}
+
+
+static int Aig_ManPoCleanupBiere( Aig_Man_t * p )
+{
+ int k = 0, nPosOld = Aig_ManPoNum(p);
+
+ p->nObjs[AIG_OBJ_PO] = Vec_PtrSize( p->vPos );
+ if ( Aig_ManRegNum(p) )
+ p->nTruePos = Aig_ManPoNum(p) - Aig_ManRegNum(p);
+ return nPosOld - Aig_ManPoNum(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, piVecIndex = 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_ObjCreatePi(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_ObjCreatePi( 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_ObjCreatePi(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_ObjCreatePi( 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_ObjCreatePo( 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_ObjCreatePo( 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_ObjCreatePo( pNew, Aig_ObjChild0Copy(pMatch) );
+ Aig_ObjCreatePo( 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_ObjCreatePo( 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_ObjCreatePi( 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_ObjCreatePo( 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_ObjCreatePi( 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_ObjCreatePo( 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_ObjCreatePi( 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_ObjCreatePo( 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_ManPiCleanupBiere( pNew );
+ Aig_ManPoCleanupBiere( pNew );
+
+ Aig_ManCleanup( pNew );
+ assert( Aig_ManCheck( pNew ) );
+
+#ifndef DUPLICATE_CKT_DEBUG
+ assert((Aig_Obj_t *)Vec_PtrEntry(pNew->vPos, Saig_ManPoNum(pNew)+Aig_ObjPioNum(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_ObjCreatePi(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_ObjCreatePi( pNew );
+ nodeName = "SAVE_BIERE",
+ Vec_PtrPush( vecPiNames, nodeName );
+
+ //****************************************************************
+ // Step 5: create register outputs
+ //****************************************************************
+ Saig_ManForEachLo( p, pObj, i )
+ {
+ loCopied++;
+ pObj->pData = Aig_ObjCreatePi(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_ObjCreatePi( 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_ObjCreatePo( 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_ObjCreatePo( pNew, Aig_ObjChild0Copy(pMatch) );
+ Aig_ObjCreatePo( 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_ObjCreatePo( 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->vPis ), pNew->nRegs );
+
+ Aig_ManPiCleanupBiere( pNew );
+ Aig_ManPoCleanupBiere( 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_ManPo( 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_ManPo( 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
+
diff --git a/src/proof/live/ltl_parser.c b/src/proof/live/ltl_parser.c
new file mode 100644
index 00000000..5572611f
--- /dev/null
+++ b/src/proof/live/ltl_parser.c
@@ -0,0 +1,839 @@
+/**CFile****************************************************************
+
+ FileName [ltl_parser.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Liveness property checking.]
+
+ Synopsis [LTL checker.]
+
+ Author [Sayak Ray]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - January 1, 2009.]
+
+ Revision [$Id: ltl_parser.c,v 1.00 2009/01/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include "src/aig/aig/aig.h"
+#include "src/base/abc/abc.h"
+#include "src/base/main/mainInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+enum ltlToken { AND, OR, NOT, IMPLY, GLOBALLY, EVENTUALLY, NEXT, UNTIL, BOOL };
+enum ltlGrammerToken { OPERAND, LTL, BINOP, UOP };
+typedef enum ltlToken tokenType;
+typedef enum ltlGrammerToken ltlGrammerTokenType;
+
+struct ltlNode_t
+{
+ tokenType type;
+ char *name;
+ Aig_Obj_t *pObj;
+ struct ltlNode_t *left;
+ struct ltlNode_t *right;
+};
+
+typedef struct ltlNode_t ltlNode;
+
+ltlNode *generateTypedNode( tokenType new_type )
+//void generateTypedNode( ltlNode *new_node, tokenType new_type )
+{
+ ltlNode *new_node;
+
+ new_node = (ltlNode *)malloc( sizeof(ltlNode) );
+ if( new_node )
+ {
+ new_node->type = new_type;
+ new_node->pObj = NULL;
+ new_node->name = NULL;
+ new_node->left = NULL;
+ new_node->right = NULL;
+ }
+
+ return new_node;
+}
+
+Aig_Obj_t *buildLogicFromLTLNode_combinationalOnly( Aig_Man_t *pAig, ltlNode *pLtlNode );
+
+static inline int isNotVarNameSymbol( char c )
+{
+ return ( c == ' ' || c == '\t' || c == '\n' || c == ':' || c == '\0' );
+}
+
+void Abc_FrameCopyLTLDataBase( Abc_Frame_t *pAbc, Abc_Ntk_t * pNtk )
+{
+ char *pLtlFormula, *tempFormula;
+ int i;
+
+ if( pAbc->vLTLProperties_global != NULL )
+ {
+// printf("Deleting exisitng LTL database from the frame\n");
+ Vec_PtrFree( pAbc->vLTLProperties_global );
+ pAbc->vLTLProperties_global = NULL;
+ }
+ pAbc->vLTLProperties_global = Vec_PtrAlloc(Vec_PtrSize(pNtk->vLtlProperties));
+ Vec_PtrForEachEntry( char *, pNtk->vLtlProperties, pLtlFormula, i )
+ {
+ tempFormula = (char *)malloc( sizeof(char)*(strlen(pLtlFormula)+1) );
+ sprintf( tempFormula, "%s", pLtlFormula );
+ Vec_PtrPush( pAbc->vLTLProperties_global, tempFormula );
+ }
+}
+
+char *getVarName( char *suffixFormula, int startLoc, int *endLocation )
+{
+ int i = startLoc, length;
+ char *name;
+
+ if( isNotVarNameSymbol( suffixFormula[startLoc] ) )
+ return NULL;
+
+ while( !isNotVarNameSymbol( suffixFormula[i] ) )
+ i++;
+ *endLocation = i;
+ length = i - startLoc;
+ name = (char *)malloc( sizeof(char) * (length + 1));
+ for( i=0; i<length; i++ )
+ name[i] = suffixFormula[i+startLoc];
+ name[i] = '\0';
+
+ return name;
+}
+
+
+int startOfSuffixString = 0;
+
+int isUnexpectedEOS( char *formula, int index )
+{
+ assert( formula );
+ if( index >= (int)strlen( formula ) )
+ {
+ printf("\nInvalid LTL formula: unexpected end of string..." );
+ return 1;
+ }
+ return 0;
+}
+
+int isTemporalOperator( char *formula, int index )
+{
+ if( !(isUnexpectedEOS( formula, index ) || formula[ index ] == 'G' || formula[ index ] == 'F' || formula[ index ] == 'U' || formula[ index ] == 'X') )
+ {
+ printf("\nInvalid LTL formula: expecting temporal operator at the position %d....\n", index);
+ return 0;
+ }
+ return 1;
+}
+
+ltlNode *readLtlFormula( char *formula )
+{
+ char ch;
+ char *varName;
+ int formulaLength, rememberEnd;
+ int i = startOfSuffixString;
+ ltlNode *curr_node, *temp_node_left, *temp_node_right;
+ char prevChar;
+
+ formulaLength = strlen( formula );
+ if( isUnexpectedEOS( formula, startOfSuffixString ) )
+ {
+ printf("\nFAULTING POINT: formula = %s\nstartOfSuffixString = %d, formula[%d] = %c\n\n", formula, startOfSuffixString, startOfSuffixString - 1, formula[startOfSuffixString-1]);
+ return NULL;
+ }
+
+ while( i < formulaLength )
+ {
+ ch = formula[i];
+
+ switch(ch){
+ case ' ':
+ case '\n':
+ case '\r':
+ case '\t':
+ case '\v':
+ case '\f':
+ i++;
+ startOfSuffixString = i;
+ break;
+ case ':':
+ i++;
+ if( !isTemporalOperator( formula, i ) )
+ return NULL;
+ startOfSuffixString = i;
+ break;
+ case 'G':
+ prevChar = formula[i-1];
+ if( prevChar == ':' ) //i.e. 'G' is a temporal operator
+ {
+ i++;
+ startOfSuffixString = i;
+ temp_node_left = readLtlFormula( formula );
+ if( temp_node_left == NULL )
+ return NULL;
+ else
+ {
+ curr_node = generateTypedNode(GLOBALLY);
+ curr_node->left = temp_node_left;
+ return curr_node;
+ }
+ }
+ else //i.e. 'G' must be starting a variable name
+ {
+ varName = getVarName( formula, i, &rememberEnd );
+ if( !varName )
+ {
+ printf("\nInvalid LTL formula: expecting valid variable name token...aborting" );
+ return NULL;
+ }
+ curr_node = generateTypedNode(BOOL);
+ curr_node->name = varName;
+ i = rememberEnd;
+ startOfSuffixString = i;
+ return curr_node;
+ }
+ case 'F':
+ prevChar = formula[i-1];
+ if( prevChar == ':' ) //i.e. 'F' is a temporal operator
+ {
+ i++;
+ startOfSuffixString = i;
+ temp_node_left = readLtlFormula( formula );
+ if( temp_node_left == NULL )
+ return NULL;
+ else
+ {
+ curr_node = generateTypedNode(EVENTUALLY);
+ curr_node->left = temp_node_left;
+ return curr_node;
+ }
+ }
+ else //i.e. 'F' must be starting a variable name
+ {
+ varName = getVarName( formula, i, &rememberEnd );
+ if( !varName )
+ {
+ printf("\nInvalid LTL formula: expecting valid variable name token...aborting" );
+ return NULL;
+ }
+ curr_node = generateTypedNode(BOOL);
+ curr_node->name = varName;
+ i = rememberEnd;
+ startOfSuffixString = i;
+ return curr_node;
+ }
+ case 'X':
+ prevChar = formula[i-1];
+ if( prevChar == ':' ) //i.e. 'X' is a temporal operator
+ {
+ i++;
+ startOfSuffixString = i;
+ temp_node_left = readLtlFormula( formula );
+ if( temp_node_left == NULL )
+ return NULL;
+ else
+ {
+ curr_node = generateTypedNode(NEXT);
+ curr_node->left = temp_node_left;
+ return curr_node;
+ }
+ }
+ else //i.e. 'X' must be starting a variable name
+ {
+ varName = getVarName( formula, i, &rememberEnd );
+ if( !varName )
+ {
+ printf("\nInvalid LTL formula: expecting valid variable name token...aborting" );
+ return NULL;
+ }
+ curr_node = generateTypedNode(BOOL);
+ curr_node->name = varName;
+ i = rememberEnd;
+ startOfSuffixString = i;
+ return curr_node;
+ }
+ case 'U':
+ prevChar = formula[i-1];
+ if( prevChar == ':' ) //i.e. 'X' is a temporal operator
+ {
+ i++;
+ startOfSuffixString = i;
+ temp_node_left = readLtlFormula( formula );
+ if( temp_node_left == NULL )
+ return NULL;
+ temp_node_right = readLtlFormula( formula );
+ if( temp_node_right == NULL )
+ {
+ //need to do memory management: if right subtree is NULL then left
+ //subtree must be freed.
+ return NULL;
+ }
+ curr_node = generateTypedNode(UNTIL);
+ curr_node->left = temp_node_left;
+ curr_node->right = temp_node_right;
+ return curr_node;
+ }
+ else //i.e. 'U' must be starting a variable name
+ {
+ varName = getVarName( formula, i, &rememberEnd );
+ if( !varName )
+ {
+ printf("\nInvalid LTL formula: expecting valid variable name token...aborting" );
+ return NULL;
+ }
+ curr_node = generateTypedNode(BOOL);
+ curr_node->name = varName;
+ i = rememberEnd;
+ startOfSuffixString = i;
+ return curr_node;
+ }
+ case '+':
+ i++;
+ startOfSuffixString = i;
+ temp_node_left = readLtlFormula( formula );
+ if( temp_node_left == NULL )
+ return NULL;
+ temp_node_right = readLtlFormula( formula );
+ if( temp_node_right == NULL )
+ {
+ //need to do memory management: if right subtree is NULL then left
+ //subtree must be freed.
+ return NULL;
+ }
+ curr_node = generateTypedNode(OR);
+ curr_node->left = temp_node_left;
+ curr_node->right = temp_node_right;
+ return curr_node;
+ case '&':
+ i++;
+ startOfSuffixString = i;
+ temp_node_left = readLtlFormula( formula );
+ if( temp_node_left == NULL )
+ return NULL;
+ temp_node_right = readLtlFormula( formula );
+ if( temp_node_right == NULL )
+ {
+ //need to do memory management: if right subtree is NULL then left
+ //subtree must be freed.
+ return NULL;
+ }
+ curr_node = generateTypedNode(AND);
+ curr_node->left = temp_node_left;
+ curr_node->right = temp_node_right;
+ return curr_node;
+ case '!':
+ i++;
+ startOfSuffixString = i;
+ temp_node_left = readLtlFormula( formula );
+ if( temp_node_left == NULL )
+ return NULL;
+ else
+ {
+ curr_node = generateTypedNode(NOT);
+ curr_node->left = temp_node_left;
+ return curr_node;
+ }
+ default:
+ varName = getVarName( formula, i, &rememberEnd );
+ if( !varName )
+ {
+ printf("\nInvalid LTL formula: expecting valid variable name token...aborting" );
+ return NULL;
+ }
+ curr_node = generateTypedNode(BOOL);
+ curr_node->name = varName;
+ i = rememberEnd;
+ startOfSuffixString = i;
+ return curr_node;
+ }
+ }
+ return NULL;
+}
+
+void resetGlobalVar()
+{
+ startOfSuffixString = 0;
+}
+
+ltlNode *parseFormulaCreateAST( char *inputFormula )
+{
+ ltlNode *temp;
+
+ temp = readLtlFormula( inputFormula );
+ //if( temp == NULL )
+ // printf("\nAST creation failed for formula %s", inputFormula );
+ resetGlobalVar();
+ return temp;
+}
+
+void traverseAbstractSyntaxTree( ltlNode *node )
+{
+ switch(node->type){
+ case( AND ):
+ printf("& ");
+ assert( node->left != NULL );
+ assert( node->right != NULL );
+ traverseAbstractSyntaxTree( node->left );
+ traverseAbstractSyntaxTree( node->right );
+ return;
+ case( OR ):
+ printf("+ ");
+ assert( node->left != NULL );
+ assert( node->right != NULL );
+ traverseAbstractSyntaxTree( node->left );
+ traverseAbstractSyntaxTree( node->right );
+ return;
+ case( NOT ):
+ printf("~ ");
+ assert( node->left != NULL );
+ traverseAbstractSyntaxTree( node->left );
+ assert( node->right == NULL );
+ return;
+ case( GLOBALLY ):
+ printf("G ");
+ assert( node->left != NULL );
+ traverseAbstractSyntaxTree( node->left );
+ assert( node->right == NULL );
+ return;
+ case( EVENTUALLY ):
+ printf("F ");
+ assert( node->left != NULL );
+ traverseAbstractSyntaxTree( node->left );
+ assert( node->right == NULL );
+ return;
+ case( NEXT ):
+ printf("X ");
+ assert( node->left != NULL );
+ traverseAbstractSyntaxTree( node->left );
+ assert( node->right == NULL );
+ return;
+ case( UNTIL ):
+ printf("U ");
+ assert( node->left != NULL );
+ assert( node->right != NULL );
+ traverseAbstractSyntaxTree( node->left );
+ traverseAbstractSyntaxTree( node->right );
+ return;
+ case( BOOL ):
+ printf("%s ", node->name);
+ assert( node->left == NULL );
+ assert( node->right == NULL );
+ return;
+ default:
+ printf("\nUnsupported token type: Exiting execution\n");
+ exit(0);
+ }
+}
+
+void traverseAbstractSyntaxTree_postFix( ltlNode *node )
+{
+ switch(node->type){
+ case( AND ):
+ printf("( ");
+ assert( node->left != NULL );
+ assert( node->right != NULL );
+ traverseAbstractSyntaxTree_postFix( node->left );
+ printf("& ");
+ traverseAbstractSyntaxTree_postFix( node->right );
+ printf(") ");
+ return;
+ case( OR ):
+ printf("( ");
+ assert( node->left != NULL );
+ assert( node->right != NULL );
+ traverseAbstractSyntaxTree_postFix( node->left );
+ printf("+ ");
+ traverseAbstractSyntaxTree_postFix( node->right );
+ printf(") ");
+ return;
+ case( NOT ):
+ printf("~ ");
+ assert( node->left != NULL );
+ traverseAbstractSyntaxTree_postFix( node->left );
+ assert( node->right == NULL );
+ return;
+ case( GLOBALLY ):
+ printf("G ");
+ //printf("( ");
+ assert( node->left != NULL );
+ traverseAbstractSyntaxTree_postFix( node->left );
+ assert( node->right == NULL );
+ //printf(") ");
+ return;
+ case( EVENTUALLY ):
+ printf("F ");
+ //printf("( ");
+ assert( node->left != NULL );
+ traverseAbstractSyntaxTree_postFix( node->left );
+ assert( node->right == NULL );
+ //printf(") ");
+ return;
+ case( NEXT ):
+ printf("X ");
+ assert( node->left != NULL );
+ traverseAbstractSyntaxTree_postFix( node->left );
+ assert( node->right == NULL );
+ return;
+ case( UNTIL ):
+ printf("( ");
+ assert( node->left != NULL );
+ assert( node->right != NULL );
+ traverseAbstractSyntaxTree_postFix( node->left );
+ printf("U ");
+ traverseAbstractSyntaxTree_postFix( node->right );
+ printf(") ");
+ return;
+ case( BOOL ):
+ printf("%s ", node->name);
+ assert( node->left == NULL );
+ assert( node->right == NULL );
+ return;
+ default:
+ printf("\nUnsupported token type: Exiting execution\n");
+ exit(0);
+ }
+}
+
+void populateAigPointerUnitGF( Aig_Man_t *pAigNew, ltlNode *topASTNode, Vec_Ptr_t *vSignal, Vec_Vec_t *vAigGFMap )
+{
+ ltlNode *nextNode, *nextToNextNode;
+ int serialNumSignal;
+
+ switch( topASTNode->type ){
+ case AND:
+ case OR:
+ case IMPLY:
+ populateAigPointerUnitGF( pAigNew, topASTNode->left, vSignal, vAigGFMap );
+ populateAigPointerUnitGF( pAigNew, topASTNode->right, vSignal, vAigGFMap );
+ return;
+ case NOT:
+ populateAigPointerUnitGF( pAigNew, topASTNode->left, vSignal, vAigGFMap );
+ return;
+ case GLOBALLY:
+ nextNode = topASTNode->left;
+ assert( nextNode->type = EVENTUALLY );
+ nextToNextNode = nextNode->left;
+ if( nextToNextNode->type == BOOL )
+ {
+ assert( nextToNextNode->pObj );
+ serialNumSignal = Vec_PtrFind( vSignal, nextToNextNode->pObj );
+ if( serialNumSignal == -1 )
+ {
+ Vec_PtrPush( vSignal, nextToNextNode->pObj );
+ serialNumSignal = Vec_PtrFind( vSignal, nextToNextNode->pObj );
+ }
+ //Vec_PtrPush( vGLOBALLY, topASTNode );
+ Vec_VecPush( vAigGFMap, serialNumSignal, topASTNode );
+ }
+ else
+ {
+ assert( nextToNextNode->pObj == NULL );
+ buildLogicFromLTLNode_combinationalOnly( pAigNew, nextToNextNode );
+ serialNumSignal = Vec_PtrFind( vSignal, nextToNextNode->pObj );
+ if( serialNumSignal == -1 )
+ {
+ Vec_PtrPush( vSignal, nextToNextNode->pObj );
+ serialNumSignal = Vec_PtrFind( vSignal, nextToNextNode->pObj );
+ }
+ //Vec_PtrPush( vGLOBALLY, topASTNode );
+ Vec_VecPush( vAigGFMap, serialNumSignal, topASTNode );
+ }
+ return;
+ case BOOL:
+ return;
+ default:
+ printf("\nINVALID situation: aborting...\n");
+ exit(0);
+ }
+}
+
+Aig_Obj_t *buildLogicFromLTLNode_combinationalOnly( Aig_Man_t *pAigNew, ltlNode *pLtlNode )
+{
+ Aig_Obj_t *leftAigObj, *rightAigObj;
+
+ if( pLtlNode->pObj != NULL )
+ return pLtlNode->pObj;
+ else
+ {
+ assert( pLtlNode->type != BOOL );
+ switch( pLtlNode->type ){
+ case AND:
+ assert( pLtlNode->left ); assert( pLtlNode->right );
+ leftAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->left );
+ rightAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->right );
+ assert( leftAigObj ); assert( rightAigObj );
+ pLtlNode->pObj = Aig_And( pAigNew, leftAigObj, rightAigObj );
+ return pLtlNode->pObj;
+ case OR:
+ assert( pLtlNode->left ); assert( pLtlNode->right );
+ leftAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->left );
+ rightAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->right );
+ assert( leftAigObj ); assert( rightAigObj );
+ pLtlNode->pObj = Aig_Or( pAigNew, leftAigObj, rightAigObj );
+ return pLtlNode->pObj;
+ case NOT:
+ assert( pLtlNode->left ); assert( pLtlNode->right == NULL );
+ leftAigObj = buildLogicFromLTLNode_combinationalOnly( pAigNew, pLtlNode->left );
+ assert( leftAigObj );
+ pLtlNode->pObj = Aig_Not( leftAigObj );
+ return pLtlNode->pObj;
+ case GLOBALLY:
+ case EVENTUALLY:
+ case NEXT:
+ case UNTIL:
+ printf("FORBIDDEN node: ABORTING!!\n");
+ exit(0);
+ default:
+ printf("\nSerious ERROR: attempting to create AIG node from a temporal node\n");
+ exit(0);
+ }
+ }
+}
+
+Aig_Obj_t *buildLogicFromLTLNode( Aig_Man_t *pAig, ltlNode *pLtlNode )
+{
+ Aig_Obj_t *leftAigObj, *rightAigObj;
+
+ if( pLtlNode->pObj != NULL )
+ return pLtlNode->pObj;
+ else
+ {
+ assert( pLtlNode->type != BOOL );
+ switch( pLtlNode->type ){
+ case AND:
+ assert( pLtlNode->left ); assert( pLtlNode->right );
+ leftAigObj = buildLogicFromLTLNode( pAig, pLtlNode->left );
+ rightAigObj = buildLogicFromLTLNode( pAig, pLtlNode->right );
+ assert( leftAigObj ); assert( rightAigObj );
+ pLtlNode->pObj = Aig_And( pAig, leftAigObj, rightAigObj );
+ return pLtlNode->pObj;
+ case OR:
+ assert( pLtlNode->left ); assert( pLtlNode->right );
+ leftAigObj = buildLogicFromLTLNode( pAig, pLtlNode->left );
+ rightAigObj = buildLogicFromLTLNode( pAig, pLtlNode->right );
+ assert( leftAigObj ); assert( rightAigObj );
+ pLtlNode->pObj = Aig_Or( pAig, leftAigObj, rightAigObj );
+ return pLtlNode->pObj;
+ case NOT:
+ assert( pLtlNode->left ); assert( pLtlNode->right == NULL );
+ leftAigObj = buildLogicFromLTLNode( pAig, pLtlNode->left );
+ assert( leftAigObj );
+ pLtlNode->pObj = Aig_Not( leftAigObj );
+ return pLtlNode->pObj;
+ case GLOBALLY:
+ case EVENTUALLY:
+ case NEXT:
+ case UNTIL:
+ printf("\nAttempting to create circuit with missing AIG pointer in a TEMPORAL node: ABORTING!!\n");
+ exit(0);
+ default:
+ printf("\nSerious ERROR: attempting to create AIG node from a temporal node\n");
+ exit(0);
+ }
+ }
+}
+
+int isNonTemporalSubformula( ltlNode *topNode )
+{
+ switch( topNode->type ){
+ case AND:
+ case OR:
+ case IMPLY:
+ return isNonTemporalSubformula( topNode->left) && isNonTemporalSubformula( topNode->right ) ;
+ case NOT:
+ assert( topNode->right == NULL );
+ return isNonTemporalSubformula( topNode->left );
+ case BOOL:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+int isWellFormed( ltlNode *topNode )
+{
+ ltlNode *nextNode;
+
+ switch( topNode->type ){
+ case AND:
+ case OR:
+ case IMPLY:
+ return isWellFormed( topNode->left) && isWellFormed( topNode->right ) ;
+ case NOT:
+ assert( topNode->right == NULL );
+ return isWellFormed( topNode->left );
+ case BOOL:
+ return 1;
+ case GLOBALLY:
+ nextNode = topNode->left;
+ assert( topNode->right == NULL );
+ if( nextNode->type != EVENTUALLY )
+ return 0;
+ else
+ {
+ assert( nextNode->right == NULL );
+ return isNonTemporalSubformula( nextNode->left );
+ }
+ default:
+ return 0;
+ }
+}
+
+int checkBooleanConstant( char *targetName )
+{
+ if( strcmp( targetName, "true" ) == 0 )
+ return 1;
+ if( strcmp( targetName, "false" ) == 0 )
+ return 0;
+ return -1;
+}
+
+int checkSignalNameExistence( Abc_Ntk_t *pNtk, ltlNode *topASTNode )
+{
+ char *targetName;
+ Abc_Obj_t * pNode;
+ int i;
+
+ switch( topASTNode->type ){
+ case BOOL:
+ targetName = topASTNode->name;
+ //printf("\nTrying to match name %s\n", targetName);
+ if( checkBooleanConstant( targetName ) != -1 )
+ return 1;
+ Abc_NtkForEachPo( pNtk, pNode, i )
+ {
+ if( strcmp( Abc_ObjName( pNode ), targetName ) == 0 )
+ {
+ //printf("\nVariable name \"%s\" MATCHED\n", targetName);
+ return 1;
+ }
+ }
+ printf("\nVariable name \"%s\" not found in the PO name list\n", targetName);
+ return 0;
+ case AND:
+ case OR:
+ case IMPLY:
+ case UNTIL:
+ assert( topASTNode->left != NULL );
+ assert( topASTNode->right != NULL );
+ return checkSignalNameExistence( pNtk, topASTNode->left ) && checkSignalNameExistence( pNtk, topASTNode->right );
+
+ case NOT:
+ case NEXT:
+ case GLOBALLY:
+ case EVENTUALLY:
+ assert( topASTNode->left != NULL );
+ assert( topASTNode->right == NULL );
+ return checkSignalNameExistence( pNtk, topASTNode->left );
+ default:
+ printf("\nUNSUPPORTED LTL NODE TYPE:: Aborting execution\n");
+ exit(0);
+ }
+}
+
+void populateBoolWithAigNodePtr( Abc_Ntk_t *pNtk, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, ltlNode *topASTNode )
+{
+ char *targetName;
+ Abc_Obj_t * pNode;
+ int i;
+ Aig_Obj_t *pObj, *pDriverImage;
+
+ switch( topASTNode->type ){
+ case BOOL:
+ targetName = topASTNode->name;
+ if( checkBooleanConstant( targetName ) == 1 )
+ {
+ topASTNode->pObj = Aig_ManConst1( pAigNew );
+ return;
+ }
+ if( checkBooleanConstant( targetName ) == 0 )
+ {
+ topASTNode->pObj = Aig_Not(topASTNode->pObj = Aig_ManConst1( pAigNew ));
+ return;
+ }
+ Abc_NtkForEachPo( pNtk, pNode, i )
+ if( strcmp( Abc_ObjName( pNode ), targetName ) == 0 )
+ {
+ pObj = Aig_ManPo( pAigOld, i );
+ assert( Aig_ObjIsPo( pObj ));
+ pDriverImage = Aig_NotCond((Aig_Obj_t *)Aig_Regular(Aig_ObjChild0( pObj ))->pData, Aig_ObjFaninC0(pObj));
+ topASTNode->pObj = pDriverImage;
+ return;
+ }
+ assert(0);
+ case AND:
+ case OR:
+ case IMPLY:
+ case UNTIL:
+ assert( topASTNode->left != NULL );
+ assert( topASTNode->right != NULL );
+ populateBoolWithAigNodePtr( pNtk, pAigOld, pAigNew, topASTNode->left );
+ populateBoolWithAigNodePtr( pNtk, pAigOld, pAigNew, topASTNode->right );
+ return;
+ case NOT:
+ case NEXT:
+ case GLOBALLY:
+ case EVENTUALLY:
+ assert( topASTNode->left != NULL );
+ assert( topASTNode->right == NULL );
+ populateBoolWithAigNodePtr( pNtk, pAigOld, pAigNew, topASTNode->left );
+ return;
+ default:
+ printf("\nUNSUPPORTED LTL NODE TYPE:: Aborting execution\n");
+ exit(0);
+ }
+}
+
+int checkAllBoolHaveAIGPointer( ltlNode *topASTNode )
+{
+
+ switch( topASTNode->type ){
+ case BOOL:
+ if( topASTNode->pObj != NULL )
+ return 1;
+ else
+ {
+ printf("\nfaulting PODMANDYO topASTNode->name = %s\n", topASTNode->name);
+ return 0;
+ }
+ case AND:
+ case OR:
+ case IMPLY:
+ case UNTIL:
+ assert( topASTNode->left != NULL );
+ assert( topASTNode->right != NULL );
+ return checkAllBoolHaveAIGPointer( topASTNode->left ) && checkAllBoolHaveAIGPointer( topASTNode->right );
+
+ case NOT:
+ case NEXT:
+ case GLOBALLY:
+ case EVENTUALLY:
+ assert( topASTNode->left != NULL );
+ assert( topASTNode->right == NULL );
+ return checkAllBoolHaveAIGPointer( topASTNode->left );
+ default:
+ printf("\nUNSUPPORTED LTL NODE TYPE:: Aborting execution\n");
+ exit(0);
+ }
+}
+
+void setAIGNodePtrOfGloballyNode( ltlNode *astNode, Aig_Obj_t *pObjLo )
+{
+ astNode->pObj = pObjLo;
+}
+
+Aig_Obj_t *retriveAIGPointerFromLTLNode( ltlNode *astNode )
+{
+ return astNode->pObj;
+}
+
+
+ABC_NAMESPACE_IMPL_END
diff --git a/src/proof/live/module.make b/src/proof/live/module.make
new file mode 100644
index 00000000..55c70fc8
--- /dev/null
+++ b/src/proof/live/module.make
@@ -0,0 +1,3 @@
+SRC += src/proof/live/liveness.c \
+ src/proof/live/liveness_sim.c \
+ src/proof/live/ltl_parser.c
diff --git a/src/proof/llb/llb.c b/src/proof/llb/llb.c
new file mode 100644
index 00000000..348c0622
--- /dev/null
+++ b/src/proof/llb/llb.c
@@ -0,0 +1,52 @@
+/**CFile****************************************************************
+
+ FileName [llb.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/llb/llb.h b/src/proof/llb/llb.h
new file mode 100644
index 00000000..a9bfd891
--- /dev/null
+++ b/src/proof/llb/llb.h
@@ -0,0 +1,96 @@
+/**CFile****************************************************************
+
+ FileName [llb.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD-based reachability.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 8, 2010.]
+
+ Revision [$Id: llb.h,v 1.00 2010/05/08 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__llb__llb_h
+#define ABC__aig__llb__llb_h
+
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Gia_ParLlb_t_ Gia_ParLlb_t;
+struct Gia_ParLlb_t_
+{
+ int nBddMax; // maximum BDD size
+ int nIterMax; // maximum iteration count
+ int nClusterMax; // maximum cluster size
+ int nHintDepth; // the number of times to cofactor
+ int HintFirst; // the number of first hint to use
+ int fUseFlow; // use flow computation
+ int nVolumeMax; // the largest volume
+ int nVolumeMin; // the smallest volume
+ int nPartValue; // partitioning value
+ int fBackward; // enable backward reachability
+ int fReorder; // enable dynamic variable reordering
+ int fIndConstr; // extract inductive constraints
+ int fUsePivots; // use internal pivot variables
+ int fCluster; // use partition clustering
+ int fSchedule; // use cluster scheduling
+ int fDumpReached; // dump reached states into a file
+ int fVerbose; // print verbose information
+ int fVeryVerbose; // print dependency matrices
+ int fSilent; // do not print any infomation
+ int fSkipReach; // skip reachability (preparation phase only)
+ int fSkipOutCheck; // does not check the property output
+ int TimeLimit; // time limit for one reachability run
+ int TimeLimitGlo; // time limit for all reachability runs
+ // internal parameters
+ int TimeTarget; // the time to stop
+ int iFrame; // explored up to this frame
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== llbCore.c ==========================================================*/
+extern void Llb_ManSetDefaultParams( Gia_ParLlb_t * pPars );
+/*=== llb4Nonlin.c ==========================================================*/
+extern int Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/proof/llb/llb1Cluster.c b/src/proof/llb/llb1Cluster.c
new file mode 100644
index 00000000..1356e484
--- /dev/null
+++ b/src/proof/llb/llb1Cluster.c
@@ -0,0 +1,356 @@
+/**CFile****************************************************************
+
+ FileName [llb1Cluster.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Clustering algorithm.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb1Cluster.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManComputeCommonQuant( Llb_Mtr_t * p, int iCol1, int iCol2 )
+{
+ int iVar, Weight = 0;
+ for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ )
+ {
+ // count each removed variable as 2
+ if ( p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 1 && p->pRowSums[iVar] == 2 )
+ Weight += 2;
+ // count each added variale as -1
+ else if ( (p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 0) ||
+ (p->pMatrix[iCol1][iVar] == 0 && p->pMatrix[iCol2][iVar] == 1) )
+ Weight--;
+ }
+ return Weight;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManComputeBestQuant( Llb_Mtr_t * p )
+{
+ int i, k, WeightBest = -100000, WeightCur, RetValue = -1;
+ for ( i = 1; i < p->nCols-1; i++ )
+ for ( k = i+1; k < p->nCols-1; k++ )
+ {
+ if ( p->pColSums[i] == 0 || p->pColSums[i] > p->pMan->pPars->nClusterMax )
+ continue;
+ if ( p->pColSums[k] == 0 || p->pColSums[k] > p->pMan->pPars->nClusterMax )
+ continue;
+
+ WeightCur = Llb_ManComputeCommonQuant( p, i, k );
+ if ( WeightCur <= 0 )
+ continue;
+ if ( WeightBest < WeightCur )
+ {
+ WeightBest = WeightCur;
+ RetValue = (i << 16) | k;
+ }
+ }
+// printf( "Choosing best quant Weight %4d\n", WeightCur );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float ** Llb_ManComputeQuant( Llb_Mtr_t * p )
+{
+ float ** pCosts;
+ int i, k;
+ // alloc and clean
+ pCosts = (float **)Extra_ArrayAlloc( p->nCols, p->nCols, sizeof(float) );
+ for ( i = 0; i < p->nCols; i++ )
+ for ( k = 0; k < p->nCols; k++ )
+ pCosts[i][i] = 0.0;
+ // fill up
+ for ( i = 1; i < p->nCols-1; i++ )
+ for ( k = i+1; k < p->nCols-1; k++ )
+ pCosts[i][k] = pCosts[k][i] = Llb_ManComputeCommonQuant( p, i, k );
+ return pCosts;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float Llb_ManComputeCommonAttr( Llb_Mtr_t * p, int iCol1, int iCol2 )
+{
+ int iVar, CountComm = 0, CountDiff = 0;
+ for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ )
+ {
+ if ( p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 1 )
+ CountComm++;
+ else if ( p->pMatrix[iCol1][iVar] == 1 || p->pMatrix[iCol2][iVar] == 1 )
+ CountDiff++;
+ }
+/*
+ printf( "Attr cost for %4d and %4d: %4d %4d (%5.2f)\n",
+ iCol1, iCol2,
+ CountDiff, CountComm,
+ -1.0 * CountDiff / ( CountComm + CountDiff ) );
+*/
+ return -1.0 * CountDiff / ( CountComm + CountDiff );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManComputeBestAttr( Llb_Mtr_t * p )
+{
+ float WeightBest = -100000, WeightCur;
+ int i, k, RetValue = -1;
+ for ( i = 1; i < p->nCols-1; i++ )
+ for ( k = i+1; k < p->nCols-1; k++ )
+ {
+ if ( p->pColSums[i] == 0 || p->pColSums[i] > p->pMan->pPars->nClusterMax )
+ continue;
+ if ( p->pColSums[k] == 0 || p->pColSums[k] > p->pMan->pPars->nClusterMax )
+ continue;
+ WeightCur = Llb_ManComputeCommonAttr( p, i, k );
+ if ( WeightBest < WeightCur )
+ {
+ WeightBest = WeightCur;
+ RetValue = (i << 16) | k;
+ }
+ }
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+float ** Llb_ManComputeAttr( Llb_Mtr_t * p )
+{
+ float ** pCosts;
+ int i, k;
+ // alloc and clean
+ pCosts = (float **)Extra_ArrayAlloc( p->nCols, p->nCols, sizeof(float) );
+ for ( i = 0; i < p->nCols; i++ )
+ for ( k = 0; k < p->nCols; k++ )
+ pCosts[i][i] = 0.0;
+ // fill up
+ for ( i = 1; i < p->nCols-1; i++ )
+ for ( k = i+1; k < p->nCols-1; k++ )
+ pCosts[i][k] = pCosts[k][i] = Llb_ManComputeCommonAttr( p, i, k );
+ return pCosts;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of variables that will be saved.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MtrCombineSelectedColumns( Llb_Mtr_t * p, int iGrp1, int iGrp2 )
+{
+ int iVar;
+ assert( iGrp1 >= 1 && iGrp1 < p->nCols - 1 );
+ assert( iGrp2 >= 1 && iGrp2 < p->nCols - 1 );
+ assert( p->pColGrps[iGrp1] != NULL );
+ assert( p->pColGrps[iGrp2] != NULL );
+ for ( iVar = 0; iVar < p->nRows; iVar++ )
+ {
+ if ( p->pMatrix[iGrp1][iVar] == 1 && p->pMatrix[iGrp2][iVar] == 1 )
+ p->pRowSums[iVar]--;
+ if ( p->pMatrix[iGrp1][iVar] == 0 && p->pMatrix[iGrp2][iVar] == 1 )
+ {
+ p->pMatrix[iGrp1][iVar] = 1;
+ p->pColSums[iGrp1]++;
+ }
+ if ( p->pMatrix[iGrp2][iVar] == 1 )
+ p->pMatrix[iGrp2][iVar] = 0;
+ }
+ p->pColSums[iGrp2] = 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Combines one pair of columns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManClusterOne( Llb_Mtr_t * p, int iCol1, int iCol2 )
+{
+ int fVerbose = 0;
+ Llb_Grp_t * pGrp;
+ int iVar;
+
+ if ( fVerbose )
+ {
+ printf( "Combining %d and %d\n", iCol1, iCol2 );
+ for ( iVar = 0; iVar < p->nRows; iVar++ )
+ {
+ if ( p->pMatrix[iCol1][iVar] == 0 && p->pMatrix[iCol2][iVar] == 0 )
+ continue;
+ printf( "%3d : %c%c\n", iVar,
+ p->pMatrix[iCol1][iVar]? '*':' ',
+ p->pMatrix[iCol2][iVar]? '*':' ' );
+ }
+ }
+ pGrp = Llb_ManGroupsCombine( p->pColGrps[iCol1], p->pColGrps[iCol2] );
+ Llb_MtrCombineSelectedColumns( p, iCol1, iCol2 );
+ p->pColGrps[iCol1] = pGrp;
+ p->pColGrps[iCol2] = NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes empty columns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManClusterCompress( Llb_Mtr_t * p )
+{
+ int i, k = 0;
+ for ( i = 0; i < p->nCols; i++ )
+ {
+ if ( p->pColGrps[i] == NULL )
+ {
+ assert( p->pColSums[i] == 0 );
+ assert( p->pMatrix[i] != NULL );
+ ABC_FREE( p->pMatrix[i] );
+ continue;
+ }
+ p->pMatrix[k] = p->pMatrix[i];
+ p->pColGrps[k] = p->pColGrps[i];
+ p->pColSums[k] = p->pColSums[i];
+ k++;
+ }
+ p->nCols = k;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Combines one pair of columns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManCluster( Llb_Mtr_t * p )
+{
+ int RetValue;
+ do
+ {
+ do {
+ RetValue = Llb_ManComputeBestQuant( p );
+ if ( RetValue > 0 )
+ Llb_ManClusterOne( p, RetValue >> 16, RetValue & 0xffff );
+ }
+ while ( RetValue > 0 );
+
+ RetValue = Llb_ManComputeBestAttr( p );
+ if ( RetValue > 0 )
+ Llb_ManClusterOne( p, RetValue >> 16, RetValue & 0xffff );
+
+ Llb_MtrVerifyMatrix( p );
+ }
+ while ( RetValue > 0 );
+
+ Llb_ManClusterCompress( p );
+
+ Llb_MtrVerifyMatrix( p );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/llb/llb1Constr.c b/src/proof/llb/llb1Constr.c
new file mode 100644
index 00000000..67fb30ba
--- /dev/null
+++ b/src/proof/llb/llb1Constr.c
@@ -0,0 +1,313 @@
+/**CFile****************************************************************
+
+ FileName [llb1Constr.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Computing inductive constraints.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb1Constr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of constraint candidates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManCountEntries( Vec_Int_t * vCands )
+{
+ int i, Entry, Counter = 0;
+ Vec_IntForEachEntry( vCands, Entry, i )
+ Counter += ((Entry == 0) || (Entry == 1));
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of constraint candidates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManPrintEntries( Aig_Man_t * p, Vec_Int_t * vCands )
+{
+ int i, Entry;
+ if ( vCands == NULL )
+ {
+ printf( "There is no hints.\n" );
+ return;
+ }
+ Entry = Llb_ManCountEntries(vCands);
+ printf( "\n*** Using %d hint%s:\n", Entry, (Entry != 1 ? "s":"") );
+ Vec_IntForEachEntry( vCands, Entry, i )
+ {
+ if ( Entry != 0 && Entry != 1 )
+ continue;
+ printf( "%c", Entry ? '+' : '-' );
+ printf( "%-6d : ", i );
+ Aig_ObjPrint( p, Aig_ManObj(p, i) );
+ printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Dereference BDD nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManDerefenceBdds( Aig_Man_t * p, DdManager * dd )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Aig_ManForEachObj( p, pObj, i )
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of constraint candidates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_ManComputeIndCase_rec( Aig_Man_t * p, Aig_Obj_t * pObj, DdManager * dd, Vec_Ptr_t * vBdds )
+{
+ DdNode * bBdd0, * bBdd1;
+ DdNode * bFunc = (DdNode *)Vec_PtrEntry( vBdds, Aig_ObjId(pObj) );
+ if ( bFunc != NULL )
+ return bFunc;
+ assert( Aig_ObjIsNode(pObj) );
+ bBdd0 = Llb_ManComputeIndCase_rec( p, Aig_ObjFanin0(pObj), dd, vBdds );
+ bBdd1 = Llb_ManComputeIndCase_rec( p, Aig_ObjFanin1(pObj), dd, vBdds );
+ bBdd0 = Cudd_NotCond( bBdd0, Aig_ObjFaninC0(pObj) );
+ bBdd1 = Cudd_NotCond( bBdd1, Aig_ObjFaninC1(pObj) );
+ bFunc = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bFunc );
+ Vec_PtrWriteEntry( vBdds, Aig_ObjId(pObj), bFunc );
+ return bFunc;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of constraint candidates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManComputeIndCase( Aig_Man_t * p, DdManager * dd, Vec_Int_t * vNodes )
+{
+ Vec_Ptr_t * vBdds;
+ Aig_Obj_t * pObj;
+ DdNode * bFunc;
+ int i, Entry;
+ vBdds = Vec_PtrStart( Aig_ManObjNumMax(p) );
+ bFunc = Cudd_ReadOne(dd); Cudd_Ref( bFunc );
+ Vec_PtrWriteEntry( vBdds, Aig_ObjId(Aig_ManConst1(p)), bFunc );
+ Saig_ManForEachPi( p, pObj, i )
+ {
+ bFunc = Cudd_bddIthVar( dd, Aig_ManPiNum(p) + i ); Cudd_Ref( bFunc );
+ Vec_PtrWriteEntry( vBdds, Aig_ObjId(pObj), bFunc );
+ }
+ Saig_ManForEachLi( p, pObj, i )
+ {
+ bFunc = (DdNode *)pObj->pData; Cudd_Ref( bFunc );
+ Vec_PtrWriteEntry( vBdds, Aig_ObjId(Saig_ObjLiToLo(p, pObj)), bFunc );
+ }
+ Vec_IntForEachEntry( vNodes, Entry, i )
+ {
+ if ( Entry != 0 && Entry != 1 )
+ continue;
+ pObj = Aig_ManObj( p, i );
+ bFunc = Llb_ManComputeIndCase_rec( p, pObj, dd, vBdds );
+ if ( Entry == 0 )
+ {
+// Extra_bddPrint( dd, Cudd_Not(pObj->pData) ); printf( "\n" );
+// Extra_bddPrint( dd, Cudd_Not(bFunc) ); printf( "\n" );
+ if ( !Cudd_bddLeq( dd, Cudd_Not(pObj->pData), Cudd_Not(bFunc) ) )
+ Vec_IntWriteEntry( vNodes, i, -1 );
+ }
+ else if ( Entry == 1 )
+ {
+// Extra_bddPrint( dd, pObj->pData ); printf( "\n" );
+// Extra_bddPrint( dd, bFunc ); printf( "\n" );
+ if ( !Cudd_bddLeq( dd, (DdNode *)pObj->pData, bFunc ) )
+ Vec_IntWriteEntry( vNodes, i, -1 );
+ }
+ }
+ Vec_PtrForEachEntry( DdNode *, vBdds, bFunc, i )
+ if ( bFunc )
+ Cudd_RecursiveDeref( dd, bFunc );
+ Vec_PtrFree( vBdds );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of constraint candidates.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_ManComputeBaseCase( Aig_Man_t * p, DdManager * dd )
+{
+ Vec_Int_t * vNodes;
+ Aig_Obj_t * pObj, * pRoot;
+ int i;
+ pRoot = Aig_ManPo( p, 0 );
+ vNodes = Vec_IntStartFull( Aig_ManObjNumMax(p) );
+ Aig_ManForEachObj( p, pObj, i )
+ {
+ if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) )
+ continue;
+ if ( Cudd_bddLeq( dd, (DdNode *)pObj->pData, Cudd_Not(pRoot->pData) ) )
+ Vec_IntWriteEntry( vNodes, i, 1 );
+ else if ( Cudd_bddLeq( dd, Cudd_Not((DdNode *)pObj->pData), Cudd_Not(pRoot->pData) ) )
+ Vec_IntWriteEntry( vNodes, i, 0 );
+ }
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Constructs global BDDs for each object in the AIG manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdManager * Llb_ManConstructGlobalBdds( Aig_Man_t * p )
+{
+ DdManager * dd;
+ DdNode * bBdd0, * bBdd1;
+ Aig_Obj_t * pObj;
+ int i;
+ dd = Cudd_Init( Aig_ManPiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+ pObj = Aig_ManConst1(p);
+ pObj->pData = Cudd_ReadOne(dd); Cudd_Ref( (DdNode *)pObj->pData );
+ Aig_ManForEachPi( p, pObj, i )
+ {
+ pObj->pData = Cudd_bddIthVar(dd, i); Cudd_Ref( (DdNode *)pObj->pData );
+ }
+ Aig_ManForEachNode( p, pObj, i )
+ {
+ bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+ pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData );
+ }
+ Aig_ManForEachPo( p, pObj, i )
+ {
+ pObj->pData = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); Cudd_Ref( (DdNode *)pObj->pData );
+ }
+ return dd;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives inductive constraints.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_ManDeriveConstraints( Aig_Man_t * p )
+{
+ DdManager * dd;
+ Vec_Int_t * vNodes;
+ if ( Saig_ManPoNum(p) != 1 )
+ {
+ printf( "The AIG has %d property outputs.\n", Saig_ManPoNum(p) );
+ return NULL;
+ }
+ assert( Saig_ManPoNum(p) == 1 );
+ dd = Llb_ManConstructGlobalBdds( p );
+ vNodes = Llb_ManComputeBaseCase( p, dd );
+ if ( Llb_ManCountEntries(vNodes) > 0 )
+ Llb_ManComputeIndCase( p, dd, vNodes );
+ if ( Llb_ManCountEntries(vNodes) == 0 )
+ Vec_IntFreeP( &vNodes );
+ Llb_ManDerefenceBdds( p, dd );
+ Extra_StopManager( dd );
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Tests derived constraints.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManConstrTest( Aig_Man_t * p )
+{
+ Vec_Int_t * vNodes;
+ vNodes = Llb_ManDeriveConstraints( p );
+ Llb_ManPrintEntries( p, vNodes );
+ Vec_IntFreeP( &vNodes );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/llb/llb1Core.c b/src/proof/llb/llb1Core.c
new file mode 100644
index 00000000..ee697748
--- /dev/null
+++ b/src/proof/llb/llb1Core.c
@@ -0,0 +1,222 @@
+/**CFile****************************************************************
+
+ FileName [llb1Core.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Top-level procedure.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb1Core.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+#include "src/aig/gia/gia.h"
+#include "src/aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManSetDefaultParams( Gia_ParLlb_t * p )
+{
+ memset( p, 0, sizeof(Gia_ParLlb_t) );
+ p->nBddMax = 10000000;
+ p->nIterMax = 10000000;
+ p->nClusterMax = 20;
+ p->nHintDepth = 0;
+ p->HintFirst = 0;
+ p->fUseFlow = 0; // use flow
+ p->nVolumeMax = 100; // max volume
+ p->nVolumeMin = 30; // min volume
+ p->nPartValue = 5; // partitioning value
+ p->fBackward = 0; // forward by default
+ p->fReorder = 1;
+ p->fIndConstr = 0;
+ p->fUsePivots = 0;
+ p->fCluster = 0;
+ p->fSchedule = 0;
+ p->fDumpReached = 0;
+ p->fVerbose = 0;
+ p->fVeryVerbose = 0;
+ p->fSilent = 0;
+ p->TimeLimit = 0;
+// p->TimeLimit = 0;
+ p->TimeLimitGlo = 0;
+ p->TimeTarget = 0;
+ p->iFrame = -1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints statistics about MFFCs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManPrintAig( Llb_Man_t * p )
+{
+ Abc_Print( 1, "pi =%3d ", Saig_ManPiNum(p->pAig) );
+ Abc_Print( 1, "po =%3d ", Saig_ManPoNum(p->pAig) );
+ Abc_Print( 1, "ff =%3d ", Saig_ManRegNum(p->pAig) );
+ Abc_Print( 1, "int =%5d ", Vec_IntSize(p->vVar2Obj)-Aig_ManPiNum(p->pAig)-Saig_ManRegNum(p->pAig) );
+ Abc_Print( 1, "var =%5d ", Vec_IntSize(p->vVar2Obj) );
+ Abc_Print( 1, "part =%5d ", Vec_PtrSize(p->vGroups)-2 );
+ Abc_Print( 1, "and =%5d ", Aig_ManNodeNum(p->pAig) );
+ Abc_Print( 1, "lev =%4d ", Aig_ManLevelNum(p->pAig) );
+// Abc_Print( 1, "cut =%4d ", Llb_ManCrossCut(p->pAig) );
+ Abc_Print( 1, "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManModelCheckAig( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars, Vec_Int_t * vHints, DdManager ** pddGlo )
+{
+ Llb_Man_t * p = NULL;
+ Aig_Man_t * pAig;
+ int RetValue = -1;
+ int clk = clock();
+
+ if ( pPars->fIndConstr )
+ {
+ assert( vHints == NULL );
+ vHints = Llb_ManDeriveConstraints( pAigGlo );
+ }
+
+ // derive AIG for hints
+ if ( vHints == NULL )
+ pAig = Aig_ManDupSimple( pAigGlo );
+ else
+ {
+ if ( pPars->fVerbose )
+ Llb_ManPrintEntries( pAigGlo, vHints );
+ pAig = Aig_ManDupSimpleWithHints( pAigGlo, vHints );
+ }
+
+
+ if ( pPars->fUseFlow )
+ {
+// p = Llb_ManStartFlow( pAigGlo, pAig, pPars );
+ }
+ else
+ {
+ p = Llb_ManStart( pAigGlo, pAig, pPars );
+ if ( pPars->fVerbose )
+ {
+ Llb_ManPrintAig( p );
+ printf( "Original matrix: " );
+ Llb_MtrPrintMatrixStats( p->pMatrix );
+ if ( pPars->fVeryVerbose )
+ Llb_MtrPrint( p->pMatrix, 1 );
+ }
+ if ( pPars->fCluster )
+ {
+ Llb_ManCluster( p->pMatrix );
+ if ( pPars->fVerbose )
+ {
+ printf( "Matrix after clustering: " );
+ Llb_MtrPrintMatrixStats( p->pMatrix );
+ if ( pPars->fVeryVerbose )
+ Llb_MtrPrint( p->pMatrix, 1 );
+ }
+ }
+ if ( pPars->fSchedule )
+ {
+ Llb_MtrSchedule( p->pMatrix );
+ if ( pPars->fVerbose )
+ {
+ printf( "Matrix after scheduling: " );
+ Llb_MtrPrintMatrixStats( p->pMatrix );
+ if ( pPars->fVeryVerbose )
+ Llb_MtrPrint( p->pMatrix, 1 );
+ }
+ }
+ }
+
+ if ( !p->pPars->fSkipReach )
+ RetValue = Llb_ManReachability( p, vHints, pddGlo );
+ Llb_ManStop( p );
+
+ Abc_PrintTime( 1, "Time", clock() - clk );
+
+ if ( pPars->fIndConstr )
+ Vec_IntFreeP( &vHints );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManModelCheckGia( Gia_Man_t * pGia, Gia_ParLlb_t * pPars )
+{
+ Gia_Man_t * pGia2;
+ Aig_Man_t * pAig;
+ int RetValue = -1;
+ pGia2 = Gia_ManDupDfs( pGia );
+ pAig = Gia_ManToAigSimple( pGia2 );
+ Gia_ManStop( pGia2 );
+//Aig_ManShow( pAig, 0, NULL );
+
+ if ( pPars->nHintDepth == 0 )
+ RetValue = Llb_ManModelCheckAig( pAig, pPars, NULL, NULL );
+ else
+ RetValue = Llb_ManModelCheckAigWithHints( pAig, pPars );
+ pGia->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL;
+ Aig_ManStop( pAig );
+ return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/llb/llb1Group.c b/src/proof/llb/llb1Group.c
new file mode 100644
index 00000000..c61f3a30
--- /dev/null
+++ b/src/proof/llb/llb1Group.c
@@ -0,0 +1,474 @@
+/**CFile****************************************************************
+
+ FileName [llb1Group.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Initial partition computation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb1Group.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Grp_t * Llb_ManGroupAlloc( Llb_Man_t * pMan )
+{
+ Llb_Grp_t * p;
+ p = ABC_CALLOC( Llb_Grp_t, 1 );
+ p->pMan = pMan;
+ p->vIns = Vec_PtrAlloc( 8 );
+ p->vOuts = Vec_PtrAlloc( 8 );
+ p->Id = Vec_PtrSize( pMan->vGroups );
+ Vec_PtrPush( pMan->vGroups, p );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManGroupStop( Llb_Grp_t * p )
+{
+ if ( p == NULL )
+ return;
+ Vec_PtrWriteEntry( p->pMan->vGroups, p->Id, NULL );
+ Vec_PtrFreeP( &p->vIns );
+ Vec_PtrFreeP( &p->vOuts );
+ Vec_PtrFreeP( &p->vNodes );
+ ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManGroupCollect_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+ if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+ return;
+ Aig_ObjSetTravIdCurrent(pAig, pObj);
+ if ( Aig_ObjIsConst1(pObj) )
+ return;
+ if ( Aig_ObjIsPo(pObj) )
+ {
+ Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin0(pObj), vNodes );
+ return;
+ }
+ assert( Aig_ObjIsAnd(pObj) );
+ Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin0(pObj), vNodes );
+ Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin1(pObj), vNodes );
+ Vec_PtrPush( vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the support of MFFC.]
+
+ Description [Returns the number of internal nodes in the MFFC.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManGroupCollect( Llb_Grp_t * pGroup )
+{
+ Vec_Ptr_t * vNodes;
+ Aig_Obj_t * pObj;
+ int i;
+ vNodes = Vec_PtrAlloc( 100 );
+ Aig_ManIncrementTravId( pGroup->pMan->pAig );
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i )
+ Aig_ObjSetTravIdCurrent( pGroup->pMan->pAig, pObj );
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i )
+ Aig_ObjSetTravIdPrevious( pGroup->pMan->pAig, pObj );
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i )
+ Llb_ManGroupCollect_rec( pGroup->pMan->pAig, pObj, vNodes );
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManGroupCreate_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vSupp )
+{
+ if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+ return;
+ Aig_ObjSetTravIdCurrent(pAig, pObj);
+ if ( Aig_ObjIsConst1(pObj) )
+ return;
+ if ( pObj->fMarkA )
+ {
+ Vec_PtrPush( vSupp, pObj );
+ return;
+ }
+ assert( Aig_ObjIsAnd(pObj) );
+ Llb_ManGroupCreate_rec( pAig, Aig_ObjFanin0(pObj), vSupp );
+ Llb_ManGroupCreate_rec( pAig, Aig_ObjFanin1(pObj), vSupp );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Grp_t * Llb_ManGroupCreate( Llb_Man_t * pMan, Aig_Obj_t * pObj )
+{
+ Llb_Grp_t * p;
+ assert( pObj->fMarkA == 1 );
+ // derive group
+ p = Llb_ManGroupAlloc( pMan );
+ Vec_PtrPush( p->vOuts, pObj );
+ Aig_ManIncrementTravId( pMan->pAig );
+ if ( Aig_ObjIsPo(pObj) )
+ Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin0(pObj), p->vIns );
+ else
+ {
+ Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin0(pObj), p->vIns );
+ Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin1(pObj), p->vIns );
+ }
+ // derive internal objects
+ assert( p->vNodes == NULL );
+ p->vNodes = Llb_ManGroupCollect( p );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Grp_t * Llb_ManGroupCreateFirst( Llb_Man_t * pMan )
+{
+ Llb_Grp_t * p;
+ Aig_Obj_t * pObj;
+ int i;
+ p = Llb_ManGroupAlloc( pMan );
+ Saig_ManForEachLo( pMan->pAig, pObj, i )
+ Vec_PtrPush( p->vOuts, pObj );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Grp_t * Llb_ManGroupCreateLast( Llb_Man_t * pMan )
+{
+ Llb_Grp_t * p;
+ Aig_Obj_t * pObj;
+ int i;
+ p = Llb_ManGroupAlloc( pMan );
+ Saig_ManForEachLi( pMan->pAig, pObj, i )
+ Vec_PtrPush( p->vIns, pObj );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Grp_t * Llb_ManGroupsCombine( Llb_Grp_t * p1, Llb_Grp_t * p2 )
+{
+ Llb_Grp_t * p;
+ Aig_Obj_t * pObj;
+ int i;
+ p = Llb_ManGroupAlloc( p1->pMan );
+ // create inputs
+ Vec_PtrForEachEntry( Aig_Obj_t *, p1->vIns, pObj, i )
+ Vec_PtrPush( p->vIns, pObj );
+ Vec_PtrForEachEntry( Aig_Obj_t *, p2->vIns, pObj, i )
+ Vec_PtrPushUnique( p->vIns, pObj );
+ // create outputs
+ Vec_PtrForEachEntry( Aig_Obj_t *, p1->vOuts, pObj, i )
+ Vec_PtrPush( p->vOuts, pObj );
+ Vec_PtrForEachEntry( Aig_Obj_t *, p2->vOuts, pObj, i )
+ Vec_PtrPushUnique( p->vOuts, pObj );
+
+ // derive internal objects
+ assert( p->vNodes == NULL );
+ p->vNodes = Llb_ManGroupCollect( p );
+ return p;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManGroupMarkNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ return;
+ if ( Aig_ObjIsTravIdPrevious(p, pObj) )
+ {
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ return;
+ }
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ assert( Aig_ObjIsNode(pObj) );
+ Llb_ManGroupMarkNodes_rec( p, Aig_ObjFanin0(pObj) );
+ Llb_ManGroupMarkNodes_rec( p, Aig_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates group from two cuts derived by the flow computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Grp_t * Llb_ManGroupCreateFromCuts( Llb_Man_t * pMan, Vec_Int_t * vCut1, Vec_Int_t * vCut2 )
+{
+ Llb_Grp_t * p;
+ Aig_Obj_t * pObj;
+ int i;
+ p = Llb_ManGroupAlloc( pMan );
+
+ // mark Cut1
+ Aig_ManIncrementTravId( pMan->pAig );
+ Aig_ManForEachObjVec( vCut1, pMan->pAig, pObj, i )
+ Aig_ObjSetTravIdCurrent( pMan->pAig, pObj );
+ // collect unmarked Cut2
+ Aig_ManForEachObjVec( vCut2, pMan->pAig, pObj, i )
+ if ( !Aig_ObjIsTravIdCurrent( pMan->pAig, pObj ) )
+ Vec_PtrPush( p->vOuts, pObj );
+
+ // mark nodes reachable from Cut2
+ Aig_ManIncrementTravId( pMan->pAig );
+ Aig_ManForEachObjVec( vCut2, pMan->pAig, pObj, i )
+ Llb_ManGroupMarkNodes_rec( pMan->pAig, pObj );
+ // collect marked Cut1
+ Aig_ManForEachObjVec( vCut1, pMan->pAig, pObj, i )
+ if ( Aig_ObjIsTravIdCurrent( pMan->pAig, pObj ) )
+ Vec_PtrPush( p->vIns, pObj );
+
+ // derive internal objects
+ assert( p->vNodes == NULL );
+ p->vNodes = Llb_ManGroupCollect( p );
+ return p;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManPrepareGroups( Llb_Man_t * pMan )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ assert( pMan->vGroups == NULL );
+ pMan->vGroups = Vec_PtrAlloc( 1000 );
+ Llb_ManGroupCreateFirst( pMan );
+ Aig_ManForEachNode( pMan->pAig, pObj, i )
+ {
+ if ( pObj->fMarkA )
+ Llb_ManGroupCreate( pMan, pObj );
+ }
+ Saig_ManForEachLi( pMan->pAig, pObj, i )
+ {
+ if ( pObj->fMarkA )
+ Llb_ManGroupCreate( pMan, pObj );
+ }
+ Llb_ManGroupCreateLast( pMan );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManPrintSpan( Llb_Man_t * p )
+{
+ Llb_Grp_t * pGroup;
+ Aig_Obj_t * pVar;
+ int i, k, Span = 0, SpanMax = 0;
+ Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGroup, i )
+ {
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k )
+ if ( Vec_IntEntry(p->vVarBegs, pVar->Id) == i )
+ Span++;
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k )
+ if ( Vec_IntEntry(p->vVarBegs, pVar->Id) == i )
+ Span++;
+
+ SpanMax = Abc_MaxInt( SpanMax, Span );
+printf( "%d ", Span );
+
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k )
+ if ( Vec_IntEntry(p->vVarEnds, pVar->Id) == i )
+ Span--;
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k )
+ if ( Vec_IntEntry(p->vVarEnds, pVar->Id) == i )
+ Span--;
+ }
+printf( "\n" );
+printf( "Max = %d\n", SpanMax );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManGroupHasVar( Llb_Man_t * p, int iGroup, int iVar )
+{
+ Llb_Grp_t * pGroup = (Llb_Grp_t *)Vec_PtrEntry( p->vGroups, iGroup );
+ Aig_Obj_t * pObj;
+ int i;
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i )
+ if ( pObj->Id == iVar )
+ return 1;
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i )
+ if ( pObj->Id == iVar )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManPrintHisto( Llb_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i, k;
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ {
+ if ( Vec_IntEntry(p->vObj2Var, i) < 0 )
+ continue;
+ printf( "%3d :", i );
+ for ( k = 0; k < Vec_IntEntry(p->vVarBegs, i); k++ )
+ printf( " " );
+ for ( ; k <= Vec_IntEntry(p->vVarEnds, i); k++ )
+ printf( "%c", Llb_ManGroupHasVar(p, k, i)? '*':'-' );
+ printf( "\n" );
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/llb/llb1Hint.c b/src/proof/llb/llb1Hint.c
new file mode 100644
index 00000000..f68030ff
--- /dev/null
+++ b/src/proof/llb/llb1Hint.c
@@ -0,0 +1,226 @@
+/**CFile****************************************************************
+
+ FileName [llb1Hint.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Cofactors the circuit w.r.t. the high-fanout variables.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb1Hint.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Returns CI index with the largest number of fanouts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManMaxFanoutCi( Aig_Man_t * pAig )
+{
+ Aig_Obj_t * pObj;
+ int i, WeightMax = -ABC_INFINITY, iInput = -1;
+ Aig_ManForEachPi( pAig, pObj, i )
+ if ( WeightMax < Aig_ObjRefs(pObj) )
+ {
+ WeightMax = Aig_ObjRefs(pObj);
+ iInput = i;
+ }
+ assert( iInput >= 0 );
+ return iInput;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives AIG whose PI is substituted by a constant.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Llb_ManPerformHints( Aig_Man_t * pAig, int nHintDepth )
+{
+ Aig_Man_t * pNew, * pTemp;
+ int i, iInput;
+ pNew = Aig_ManDupDfs( pAig );
+ for ( i = 0; i < nHintDepth; i++ )
+ {
+ iInput = Llb_ManMaxFanoutCi( pNew );
+ Abc_Print( 1, "%d %3d\n", i, iInput );
+ pNew = Aig_ManDupCof( pTemp = pNew, iInput, 1 );
+ Aig_ManStop( pTemp );
+ }
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns CI index with the largest number of fanouts.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_ManCollectHighFanoutObjects( Aig_Man_t * pAig, int nCandMax, int fCisOnly )
+{
+ Vec_Int_t * vFanouts, * vResult;
+ Aig_Obj_t * pObj;
+ int i, fChanges, PivotValue;
+// int Entry;
+ // collect fanout counts
+ vFanouts = Vec_IntAlloc( 100 );
+ Aig_ManForEachObj( pAig, pObj, i )
+ {
+// if ( !Aig_ObjIsPi(pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) )
+ if ( !Saig_ObjIsLo(pAig,pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) )
+ continue;
+ Vec_IntPush( vFanouts, Aig_ObjRefs(pObj) );
+ }
+ Vec_IntSort( vFanouts, 1 );
+ // pick the separator
+ nCandMax = Abc_MinInt( nCandMax, Vec_IntSize(vFanouts) - 1 );
+ PivotValue = Vec_IntEntry( vFanouts, nCandMax );
+ Vec_IntFree( vFanouts );
+ // collect obj satisfying the constraints
+ vResult = Vec_IntAlloc( 100 );
+ Aig_ManForEachObj( pAig, pObj, i )
+ {
+// if ( !Aig_ObjIsPi(pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) )
+ if ( !Saig_ObjIsLo(pAig,pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) )
+ continue;
+ if ( Aig_ObjRefs(pObj) < PivotValue )
+ continue;
+ Vec_IntPush( vResult, Aig_ObjId(pObj) );
+ }
+ assert( Vec_IntSize(vResult) >= nCandMax );
+ // order in the decreasing order of fanouts
+ do
+ {
+ fChanges = 0;
+ for ( i = 0; i < Vec_IntSize(vResult) - 1; i++ )
+ if ( Aig_ObjRefs(Aig_ManObj(pAig, Vec_IntEntry(vResult, i))) <
+ Aig_ObjRefs(Aig_ManObj(pAig, Vec_IntEntry(vResult, i+1))) )
+ {
+ int Temp = Vec_IntEntry( vResult, i );
+ Vec_IntWriteEntry( vResult, i, Vec_IntEntry(vResult, i+1) );
+ Vec_IntWriteEntry( vResult, i+1, Temp );
+ fChanges = 1;
+ }
+ }
+ while ( fChanges );
+/*
+ Vec_IntForEachEntry( vResult, Entry, i )
+ printf( "%d ", Aig_ObjRefs(Aig_ManObj(pAig, Entry)) );
+printf( "\n" );
+*/
+ return vResult;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives AIG whose PI is substituted by a constant.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManModelCheckAigWithHints( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars )
+{
+ DdManager * ddGlo = NULL;
+ Vec_Int_t * vHints;
+ Vec_Int_t * vHFCands;
+ int i, Entry, RetValue = -1;
+ int clk = clock();
+ assert( pPars->nHintDepth > 0 );
+/*
+ // perform reachability without hints
+ RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, NULL, NULL );
+ if ( RetValue >= 0 )
+ return RetValue;
+*/
+ // create hints representation
+ vHFCands = Llb_ManCollectHighFanoutObjects( pAigGlo, pPars->nHintDepth+pPars->HintFirst, 1 );
+ vHints = Vec_IntStartFull( Aig_ManObjNumMax(pAigGlo) );
+ // add one hint at a time till the problem is solved
+ Vec_IntForEachEntryStart( vHFCands, Entry, i, pPars->HintFirst )
+ {
+ Vec_IntWriteEntry( vHints, Entry, 1 ); // change to 1 to start from zero cof!!!
+ // solve under hints
+ RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, vHints, &ddGlo );
+ if ( RetValue == 0 )
+ goto Finish;
+ if ( RetValue == 1 )
+ break;
+ }
+ if ( RetValue == -1 )
+ goto Finish;
+ // undo the hints one at a time
+ for ( ; i >= pPars->HintFirst; i-- )
+ {
+ Entry = Vec_IntEntry( vHFCands, i );
+ Vec_IntWriteEntry( vHints, Entry, -1 );
+ // solve under relaxed hints
+ RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, vHints, &ddGlo );
+ if ( RetValue == 0 )
+ goto Finish;
+ if ( RetValue == 1 )
+ continue;
+ break;
+ }
+Finish:
+ if ( ddGlo )
+ {
+ if ( ddGlo->bFunc )
+ Cudd_RecursiveDeref( ddGlo, ddGlo->bFunc );
+ Extra_StopManager( ddGlo );
+ }
+ Vec_IntFreeP( &vHFCands );
+ Vec_IntFreeP( &vHints );
+ if ( pPars->fVerbose )
+ Abc_PrintTime( 1, "Total runtime", clock() - clk );
+ return RetValue;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/llb/llb1Man.c b/src/proof/llb/llb1Man.c
new file mode 100644
index 00000000..f5de25e0
--- /dev/null
+++ b/src/proof/llb/llb1Man.c
@@ -0,0 +1,218 @@
+/**CFile****************************************************************
+
+ FileName [llb1Man.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Reachability manager.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb1Man.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManPrepareVarMap( Llb_Man_t * p )
+{
+ Aig_Obj_t * pObjLi, * pObjLo;
+ int i, iVarLi, iVarLo;
+ assert( p->vNs2Glo == NULL );
+ assert( p->vCs2Glo == NULL );
+ assert( p->vGlo2Cs == NULL );
+ assert( p->vGlo2Ns == NULL );
+ p->vNs2Glo = Vec_IntStartFull( Vec_IntSize(p->vVar2Obj) );
+ p->vCs2Glo = Vec_IntStartFull( Vec_IntSize(p->vVar2Obj) );
+ p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) );
+ p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) );
+ Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+ {
+ iVarLi = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLi));
+ iVarLo = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLo));
+ assert( iVarLi >= 0 && iVarLi < Vec_IntSize(p->vVar2Obj) );
+ assert( iVarLo >= 0 && iVarLo < Vec_IntSize(p->vVar2Obj) );
+ Vec_IntWriteEntry( p->vNs2Glo, iVarLi, i );
+ Vec_IntWriteEntry( p->vCs2Glo, iVarLo, i );
+ Vec_IntWriteEntry( p->vGlo2Cs, i, iVarLo );
+ Vec_IntWriteEntry( p->vGlo2Ns, i, iVarLi );
+ }
+ // add mapping of the PIs
+ Saig_ManForEachPi( p->pAig, pObjLo, i )
+ {
+ iVarLo = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLo));
+ Vec_IntWriteEntry( p->vCs2Glo, iVarLo, Aig_ManRegNum(p->pAig)+i );
+ Vec_IntWriteEntry( p->vNs2Glo, iVarLo, Aig_ManRegNum(p->pAig)+i );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManPrepareVarLimits( Llb_Man_t * p )
+{
+ Llb_Grp_t * pGroup;
+ Aig_Obj_t * pVar;
+ int i, k;
+ assert( p->vVarBegs == NULL );
+ assert( p->vVarEnds == NULL );
+ p->vVarEnds = Vec_IntStart( Aig_ManObjNumMax(p->pAig) );
+ p->vVarBegs = Vec_IntStart( Aig_ManObjNumMax(p->pAig) );
+ Vec_IntFill( p->vVarBegs, Aig_ManObjNumMax(p->pAig), p->pMatrix->nCols );
+
+ for ( i = 0; i < p->pMatrix->nCols; i++ )
+ {
+ pGroup = p->pMatrix->pColGrps[i];
+
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k )
+ if ( Vec_IntEntry(p->vVarBegs, pVar->Id) > i )
+ Vec_IntWriteEntry( p->vVarBegs, pVar->Id, i );
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k )
+ if ( Vec_IntEntry(p->vVarBegs, pVar->Id) > i )
+ Vec_IntWriteEntry( p->vVarBegs, pVar->Id, i );
+
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k )
+ if ( Vec_IntEntry(p->vVarEnds, pVar->Id) < i )
+ Vec_IntWriteEntry( p->vVarEnds, pVar->Id, i );
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k )
+ if ( Vec_IntEntry(p->vVarEnds, pVar->Id) < i )
+ Vec_IntWriteEntry( p->vVarEnds, pVar->Id, i );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManStop( Llb_Man_t * p )
+{
+ Llb_Grp_t * pGrp;
+ DdNode * bTemp;
+ int i;
+
+// Vec_IntFreeP( &p->vMem );
+// Vec_PtrFreeP( &p->vTops );
+// Vec_PtrFreeP( &p->vBots );
+// Vec_VecFreeP( (Vec_Vec_t **)&p->vCuts );
+
+ if ( p->pMatrix )
+ Llb_MtrFree( p->pMatrix );
+ Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGrp, i )
+ Llb_ManGroupStop( pGrp );
+ if ( p->dd )
+ {
+// printf( "Manager dd\n" );
+ Extra_StopManager( p->dd );
+ }
+ if ( p->ddG )
+ {
+// printf( "Manager ddG\n" );
+ if ( p->ddG->bFunc )
+ Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc );
+ Extra_StopManager( p->ddG );
+ }
+ if ( p->ddR )
+ {
+// printf( "Manager ddR\n" );
+ if ( p->ddR->bFunc )
+ Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc );
+ Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i )
+ Cudd_RecursiveDeref( p->ddR, bTemp );
+ Extra_StopManager( p->ddR );
+ }
+ Aig_ManStop( p->pAig );
+ Vec_PtrFreeP( &p->vGroups );
+ Vec_IntFreeP( &p->vVar2Obj );
+ Vec_IntFreeP( &p->vObj2Var );
+ Vec_IntFreeP( &p->vVarBegs );
+ Vec_IntFreeP( &p->vVarEnds );
+ Vec_PtrFreeP( &p->vRings );
+ Vec_IntFreeP( &p->vNs2Glo );
+ Vec_IntFreeP( &p->vCs2Glo );
+ Vec_IntFreeP( &p->vGlo2Cs );
+ Vec_IntFreeP( &p->vGlo2Ns );
+// Vec_IntFreeP( &p->vHints );
+ ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Man_t * Llb_ManStart( Aig_Man_t * pAigGlo, Aig_Man_t * pAig, Gia_ParLlb_t * pPars )
+{
+ Llb_Man_t * p;
+ Aig_ManCleanMarkA( pAig );
+ p = ABC_CALLOC( Llb_Man_t, 1 );
+ p->pAigGlo = pAigGlo;
+ p->pPars = pPars;
+ p->pAig = pAig;
+ p->vVar2Obj = Llb_ManMarkPivotNodes( p->pAig, pPars->fUsePivots );
+ p->vObj2Var = Vec_IntInvert( p->vVar2Obj, -1 );
+ p->vRings = Vec_PtrAlloc( 100 );
+ Llb_ManPrepareVarMap( p );
+ Llb_ManPrepareGroups( p );
+ Aig_ManCleanMarkA( pAig );
+ p->pMatrix = Llb_MtrCreate( p );
+ p->pMatrix->pMan = p;
+ return p;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/llb/llb1Matrix.c b/src/proof/llb/llb1Matrix.c
new file mode 100644
index 00000000..7aa9c744
--- /dev/null
+++ b/src/proof/llb/llb1Matrix.c
@@ -0,0 +1,430 @@
+/**CFile****************************************************************
+
+ FileName [llb1Matrix.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Partition clustering as a matrix problem.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb1Matrix.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// 0123 nCols
+// +--------------------->
+// pi 0 | 111 row0 pRowSums[0]
+// pi 1 | 1 11 row1 pRowSums[1]
+// pi 2 | 1 11 row2 pRowSums[2]
+// CS |1 1
+// CS |1 111
+// CS |111 111
+// int | 11111
+// int | 111
+// int | 111
+// int | 111
+// NS | 11 11
+// NS | 11 1
+// NS | 111
+// nRows |
+// v
+// cccc pColSums[0]
+// oooo pColSums[1]
+// llll pColSums[2]
+// 0123 pColSums[3]
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Verify columns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MtrVerifyRowsAll( Llb_Mtr_t * p )
+{
+ int iRow, iCol, Counter;
+ for ( iCol = 0; iCol < p->nCols; iCol++ )
+ {
+ Counter = 0;
+ for ( iRow = 0; iRow < p->nRows; iRow++ )
+ if ( p->pMatrix[iCol][iRow] == 1 )
+ Counter++;
+ assert( Counter == p->pColSums[iCol] );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verify columns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MtrVerifyColumnsAll( Llb_Mtr_t * p )
+{
+ int iRow, iCol, Counter;
+ for ( iRow = 0; iRow < p->nRows; iRow++ )
+ {
+ Counter = 0;
+ for ( iCol = 0; iCol < p->nCols; iCol++ )
+ if ( p->pMatrix[iCol][iRow] == 1 )
+ Counter++;
+ assert( Counter == p->pRowSums[iRow] );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verify columns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MtrVerifyMatrix( Llb_Mtr_t * p )
+{
+ Llb_MtrVerifyRowsAll( p );
+ Llb_MtrVerifyColumnsAll( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sort variables in the order of removal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int * Llb_MtrFindVarOrder( Llb_Mtr_t * p )
+{
+ int * pOrder, * pLast;
+ int i, k, fChanges, Temp;
+ pOrder = ABC_CALLOC( int, p->nRows );
+ pLast = ABC_CALLOC( int, p->nRows );
+ for ( i = 0; i < p->nRows; i++ )
+ {
+ pOrder[i] = i;
+ for ( k = p->nCols - 1; k >= 0; k-- )
+ if ( p->pMatrix[k][i] )
+ {
+ pLast[i] = k;
+ break;
+ }
+ }
+ do
+ {
+ fChanges = 0;
+ for ( i = 0; i < p->nRows - 1; i++ )
+ if ( pLast[i] > pLast[i+1] )
+ {
+ Temp = pOrder[i];
+ pOrder[i] = pOrder[i+1];
+ pOrder[i+1] = Temp;
+
+ Temp = pLast[i];
+ pLast[i] = pLast[i+1];
+ pLast[i+1] = Temp;
+
+ fChanges = 1;
+ }
+ }
+ while ( fChanges );
+ ABC_FREE( pLast );
+ return pOrder;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns type of a variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Llb_MtrVarName( Llb_Mtr_t * p, int iVar )
+{
+ static char Buffer[10];
+ if ( iVar < p->nPis )
+ strcpy( Buffer, "pi" );
+ else if ( iVar < p->nPis + p->nFfs )
+ strcpy( Buffer, "CS" );
+ else if ( iVar >= p->nRows - p->nFfs )
+ strcpy( Buffer, "NS" );
+ else
+ strcpy( Buffer, "int" );
+ return Buffer;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates one column with vars in the array.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MtrPrint( Llb_Mtr_t * p, int fOrder )
+{
+ int * pOrder = NULL;
+ int i, iRow, iCol;
+ if ( fOrder )
+ pOrder = Llb_MtrFindVarOrder( p );
+ for ( i = 0; i < p->nRows; i++ )
+ {
+ iRow = pOrder ? pOrder[i] : i;
+ printf( "%3d : ", iRow );
+ printf( "%3d ", p->pRowSums[iRow] );
+ printf( "%3s ", Llb_MtrVarName(p, iRow) );
+ for ( iCol = 0; iCol < p->nCols; iCol++ )
+ printf( "%c", p->pMatrix[iCol][iRow] ? '*' : ' ' );
+ printf( "\n" );
+ }
+ ABC_FREE( pOrder );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verify columns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MtrPrintMatrixStats( Llb_Mtr_t * p )
+{
+ int iVar, iGrp, iGrp1, iGrp2, Span = 0, nCutSize = 0, nCutSizeMax = 0;
+ int * pGrp1 = ABC_CALLOC( int, p->nRows );
+ int * pGrp2 = ABC_CALLOC( int, p->nRows );
+ for ( iVar = 0; iVar < p->nRows; iVar++ )
+ {
+ if ( p->pRowSums[iVar] == 0 )
+ continue;
+ for ( iGrp1 = 0; iGrp1 < p->nCols; iGrp1++ )
+ if ( p->pMatrix[iGrp1][iVar] == 1 )
+ break;
+ for ( iGrp2 = p->nCols - 1; iGrp2 >= 0; iGrp2-- )
+ if ( p->pMatrix[iGrp2][iVar] == 1 )
+ break;
+ assert( iGrp1 <= iGrp2 );
+ pGrp1[iVar] = iGrp1;
+ pGrp2[iVar] = iGrp2;
+ Span += iGrp2 - iGrp1;
+ }
+ // compute span
+ for ( iGrp = 0; iGrp < p->nCols; iGrp++ )
+ {
+ for ( iVar = 0; iVar < p->nRows; iVar++ )
+ if ( pGrp1[iVar] == iGrp )
+ nCutSize++;
+ if ( nCutSizeMax < nCutSize )
+ nCutSizeMax = nCutSize;
+ for ( iVar = 0; iVar < p->nRows; iVar++ )
+ if ( pGrp2[iVar] == iGrp )
+ nCutSize--;
+ }
+ ABC_FREE( pGrp1 );
+ ABC_FREE( pGrp2 );
+ printf( "[%4d x %4d] Life-span =%6.2f Max-cut =%5d\n",
+ p->nCols, p->nRows, 1.0*Span/p->nRows, nCutSizeMax );
+ if ( nCutSize )
+ Abc_Print( -1, "Cut size is not zero (%d).\n", nCutSize );
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Starts the matrix representation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Mtr_t * Llb_MtrAlloc( int nPis, int nFfs, int nCols, int nRows )
+{
+ Llb_Mtr_t * p;
+ int i;
+ p = ABC_CALLOC( Llb_Mtr_t, 1 );
+ p->nPis = nPis;
+ p->nFfs = nFfs;
+ p->nRows = nRows;
+ p->nCols = nCols;
+ p->pRowSums = ABC_CALLOC( int, nRows );
+ p->pColSums = ABC_CALLOC( int, nCols );
+ p->pColGrps = ABC_CALLOC( Llb_Grp_t *, nCols );
+ p->pMatrix = ABC_CALLOC( char *, nCols );
+ for ( i = 0; i < nCols; i++ )
+ p->pMatrix[i] = ABC_CALLOC( char, nRows );
+ // partial product
+ p->pProdVars = ABC_CALLOC( char, nRows ); // variables in the partial product
+ p->pProdNums = ABC_CALLOC( int, nRows ); // var counts in the remaining partitions
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the matrix representation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MtrFree( Llb_Mtr_t * p )
+{
+ int i;
+ ABC_FREE( p->pProdVars );
+ ABC_FREE( p->pProdNums );
+ for ( i = 0; i < p->nCols; i++ )
+ ABC_FREE( p->pMatrix[i] );
+ ABC_FREE( p->pRowSums );
+ ABC_FREE( p->pColSums );
+ ABC_FREE( p->pMatrix );
+ ABC_FREE( p->pColGrps );
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates one column with vars in the array.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MtrAddColumn( Llb_Mtr_t * p, Llb_Grp_t * pGrp )
+{
+ Aig_Obj_t * pVar;
+ int i, iRow, iCol = pGrp->Id;
+ assert( iCol >= 0 && iCol < p->nCols );
+ p->pColGrps[iCol] = pGrp;
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGrp->vIns, pVar, i )
+ {
+ iRow = Vec_IntEntry( pGrp->pMan->vObj2Var, Aig_ObjId(pVar) );
+ assert( iRow >= 0 && iRow < p->nRows );
+ p->pMatrix[iCol][iRow] = 1;
+ p->pColSums[iCol]++;
+ p->pRowSums[iRow]++;
+ }
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGrp->vOuts, pVar, i )
+ {
+ iRow = Vec_IntEntry( pGrp->pMan->vObj2Var, Aig_ObjId(pVar) );
+ assert( iRow >= 0 && iRow < p->nRows );
+ p->pMatrix[iCol][iRow] = 1;
+ p->pColSums[iCol]++;
+ p->pRowSums[iRow]++;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Matrix reduce.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MtrRemoveSingletonRows( Llb_Mtr_t * p )
+{
+ int i, k;
+ for ( i = 0; i < p->nRows; i++ )
+ if ( p->pRowSums[i] < 2 )
+ {
+ p->pRowSums[i] = 0;
+ for ( k = 0; k < p->nCols; k++ )
+ {
+ if ( p->pMatrix[k][i] == 1 )
+ {
+ p->pMatrix[k][i] = 0;
+ p->pColSums[k]--;
+ }
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Matrix reduce.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Mtr_t * Llb_MtrCreate( Llb_Man_t * p )
+{
+ Llb_Mtr_t * pMatrix;
+ Llb_Grp_t * pGroup;
+ int i;
+ pMatrix = Llb_MtrAlloc( Saig_ManPiNum(p->pAig), Saig_ManRegNum(p->pAig),
+ Vec_PtrSize(p->vGroups), Vec_IntSize(p->vVar2Obj) );
+ Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGroup, i )
+ Llb_MtrAddColumn( pMatrix, pGroup );
+// Llb_MtrRemoveSingletonRows( pMatrix );
+ return pMatrix;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/llb/llb1Pivot.c b/src/proof/llb/llb1Pivot.c
new file mode 100644
index 00000000..d42bf659
--- /dev/null
+++ b/src/proof/llb/llb1Pivot.c
@@ -0,0 +1,254 @@
+/**CFile****************************************************************
+
+ FileName [llb1Pivot.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Determining pivot variables.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb1Pivot.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManTracePaths_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pPivot )
+{
+ Aig_Obj_t * pFanout;
+ int k, iFan;
+ if ( Aig_ObjIsTravIdPrevious(p, pObj) )
+ return 0;
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ return 1;
+ if ( Saig_ObjIsLi(p, pObj) )
+ return 0;
+ if ( Saig_ObjIsPo(p, pObj) )
+ return 0;
+ if ( pObj == pPivot )
+ return 1;
+ assert( Aig_ObjIsCand(pObj) );
+ Aig_ObjForEachFanout( p, pObj, pFanout, iFan, k )
+ if ( !Llb_ManTracePaths_rec( p, pFanout, pPivot ) )
+ {
+ Aig_ObjSetTravIdPrevious(p, pObj);
+ return 0;
+ }
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManTracePaths( Aig_Man_t * p, Aig_Obj_t * pPivot )
+{
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ Aig_ManIncrementTravId( p ); // prev = visited with path to LI (value 0)
+ Aig_ManIncrementTravId( p ); // cur = visited w/o path to LI (value 1)
+ Saig_ManForEachLo( p, pObj, i )
+ Counter += Llb_ManTracePaths_rec( p, pObj, pPivot );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManTestCuts( Aig_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i, Count;
+ Aig_ManFanoutStart( p );
+ Aig_ManForEachNode( p, pObj, i )
+ {
+ if ( Aig_ObjRefs(pObj) <= 1 )
+ continue;
+ Count = Llb_ManTracePaths( p, pObj );
+ printf( "Obj =%5d. Lev =%3d. Fanout =%5d. Count = %3d.\n",
+ i, Aig_ObjLevel(pObj), Aig_ObjRefs(pObj), Count );
+ }
+ Aig_ManFanoutStop( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManLabelLiCones_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+ if ( pObj->fMarkB )
+ return;
+ pObj->fMarkB = 1;
+ assert( Aig_ObjIsNode(pObj) );
+ Llb_ManLabelLiCones_rec( p, Aig_ObjFanin0(pObj) );
+ Llb_ManLabelLiCones_rec( p, Aig_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Determine starting cut-points.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManLabelLiCones( Aig_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ // mark const and PIs
+ Aig_ManConst1(p)->fMarkB = 1;
+ Aig_ManForEachPi( p, pObj, i )
+ pObj->fMarkB = 1;
+ // mark cones
+ Saig_ManForEachLi( p, pObj, i )
+ Llb_ManLabelLiCones_rec( p, Aig_ObjFanin0(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Determine starting cut-points.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManMarkInternalPivots( Aig_Man_t * p )
+{
+ Vec_Ptr_t * vMuxes;
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+
+ // remove refs due to MUXes
+ vMuxes = Aig_ManMuxesCollect( p );
+ Aig_ManMuxesDeref( p, vMuxes );
+
+ // mark nodes feeding into LIs
+ Aig_ManCleanMarkB( p );
+ Llb_ManLabelLiCones( p );
+
+ // mark internal nodes
+ Aig_ManFanoutStart( p );
+ Aig_ManForEachNode( p, pObj, i )
+ if ( pObj->fMarkB && pObj->nRefs > 1 )
+ {
+ if ( Llb_ManTracePaths(p, pObj) > 0 )
+ pObj->fMarkA = 1;
+ Counter++;
+ }
+ Aig_ManFanoutStop( p );
+// printf( "TracePath tried = %d.\n", Counter );
+
+ // mark nodes feeding into LIs
+ Aig_ManCleanMarkB( p );
+
+ // add refs due to MUXes
+ Aig_ManMuxesRef( p, vMuxes );
+ Vec_PtrFree( vMuxes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Determine starting cut-points.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_ManMarkPivotNodes( Aig_Man_t * p, int fUseInternal )
+{
+ Vec_Int_t * vVar2Obj;
+ Aig_Obj_t * pObj;
+ int i;
+ // mark inputs/outputs
+ Aig_ManForEachPi( p, pObj, i )
+ pObj->fMarkA = 1;
+ Saig_ManForEachLi( p, pObj, i )
+ pObj->fMarkA = 1;
+
+ // mark internal pivot nodes
+ if ( fUseInternal )
+ Llb_ManMarkInternalPivots( p );
+
+ // assign variable numbers
+ Aig_ManConst1(p)->fMarkA = 0;
+ vVar2Obj = Vec_IntAlloc( 100 );
+ Aig_ManForEachPi( p, pObj, i )
+ Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) );
+ Aig_ManForEachNode( p, pObj, i )
+ if ( pObj->fMarkA )
+ Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) );
+ Saig_ManForEachLi( p, pObj, i )
+ Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) );
+ return vVar2Obj;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/llb/llb1Reach.c b/src/proof/llb/llb1Reach.c
new file mode 100644
index 00000000..fbf91351
--- /dev/null
+++ b/src/proof/llb/llb1Reach.c
@@ -0,0 +1,898 @@
+/**CFile****************************************************************
+
+ FileName [llb1Reach.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Reachability analysis.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb1Reach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Derives global BDD for the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_ManConstructOutBdd( Aig_Man_t * pAig, Aig_Obj_t * pNode, DdManager * dd )
+{
+ DdNode * bBdd0, * bBdd1, * bFunc;
+ Vec_Ptr_t * vNodes;
+ Aig_Obj_t * pObj;
+ int i, TimeStop;
+ if ( Aig_ObjFanin0(pNode) == Aig_ManConst1(pAig) )
+ return Cudd_NotCond( Cudd_ReadOne(dd), Aig_ObjFaninC0(pNode) );
+ TimeStop = dd->TimeStop; dd->TimeStop = 0;
+ vNodes = Aig_ManDfsNodes( pAig, &pNode, 1 );
+ assert( Vec_PtrSize(vNodes) > 0 );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+ {
+ if ( !Aig_ObjIsNode(pObj) )
+ continue;
+ bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bBdd1 = Cudd_NotCond( Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+ pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData );
+ }
+ bFunc = (DdNode *)pObj->pData; Cudd_Ref( bFunc );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+ {
+ if ( !Aig_ObjIsNode(pObj) )
+ continue;
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+ }
+ Vec_PtrFree( vNodes );
+ if ( Aig_ObjIsPo(pNode) )
+ bFunc = Cudd_NotCond( bFunc, Aig_ObjFaninC0(pNode) );
+ Cudd_Deref( bFunc );
+ dd->TimeStop = TimeStop;
+ return bFunc;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives BDD for the group.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_ManConstructGroupBdd( Llb_Man_t * p, Llb_Grp_t * pGroup )
+{
+ Aig_Obj_t * pObj;
+ DdNode * bBdd0, * bBdd1, * bRes, * bXor, * bTemp;
+ int i, k;
+ Aig_ManConst1(p->pAig)->pData = Cudd_ReadOne( p->dd );
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i )
+ pObj->pData = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vNodes, pObj, i )
+ {
+ bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bBdd1 = Cudd_NotCond( Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+// pObj->pData = Extra_bddAndTime( p->dd, bBdd0, bBdd1, p->pPars->TimeTarget );
+ pObj->pData = Cudd_bddAnd( p->dd, bBdd0, bBdd1 );
+ if ( pObj->pData == NULL )
+ {
+ Vec_PtrForEachEntryStop( Aig_Obj_t *, pGroup->vNodes, pObj, k, i )
+ if ( pObj->pData )
+ Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData );
+ return NULL;
+ }
+ Cudd_Ref( (DdNode *)pObj->pData );
+ }
+ bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes );
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i )
+ {
+ if ( Aig_ObjIsPo(pObj) )
+ bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ else
+ bBdd0 = (DdNode *)pObj->pData;
+ bBdd1 = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
+ bXor = Cudd_bddXor( p->dd, bBdd0, bBdd1 ); Cudd_Ref( bXor );
+// bRes = Extra_bddAndTime( p->dd, bTemp = bRes, Cudd_Not(bXor), p->pPars->TimeTarget );
+ bRes = Cudd_bddAnd( p->dd, bTemp = bRes, Cudd_Not(bXor) );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->dd, bXor );
+ Vec_PtrForEachEntryStop( Aig_Obj_t *, pGroup->vNodes, pObj, k, i )
+ if ( pObj->pData )
+ Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData );
+ return NULL;
+ }
+ Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->dd, bXor );
+ }
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vNodes, pObj, i )
+ Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData );
+ Cudd_Deref( bRes );
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives quantification cube.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_ManConstructQuantCubeIntern( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace, int fBackward )
+{
+ Aig_Obj_t * pObj;
+ DdNode * bRes, * bTemp, * bVar;
+ int i, iGroupFirst, iGroupLast;
+ int TimeStop;
+ TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
+ bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes );
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i )
+ {
+ if ( fBackward && Saig_ObjIsPi(p->pAig, pObj) )
+ continue;
+ iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj));
+ iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj));
+ assert( iGroupFirst <= iGroupLast );
+ if ( iGroupFirst < iGroupLast )
+ continue;
+ bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
+ bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i )
+ {
+ if ( fBackward && Saig_ObjIsPi(p->pAig, pObj) )
+ continue;
+ iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj));
+ iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj));
+ assert( iGroupFirst <= iGroupLast );
+ if ( iGroupFirst < iGroupLast )
+ continue;
+ bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
+ bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ Cudd_Deref( bRes );
+ p->dd->TimeStop = TimeStop;
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives quantification cube.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_ManConstructQuantCubeFwd( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace )
+{
+ Aig_Obj_t * pObj;
+ DdNode * bRes, * bTemp, * bVar;
+ int i, iGroupLast, TimeStop;
+ TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
+ bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes );
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i )
+ {
+ iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj));
+ assert( iGroupLast >= iGrpPlace );
+ if ( iGroupLast > iGrpPlace )
+ continue;
+ bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
+ bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i )
+ {
+ iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj));
+ assert( iGroupLast >= iGrpPlace );
+ if ( iGroupLast > iGrpPlace )
+ continue;
+ bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
+ bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ Cudd_Deref( bRes );
+ p->dd->TimeStop = TimeStop;
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives quantification cube.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_ManConstructQuantCubeBwd( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace )
+{
+ Aig_Obj_t * pObj;
+ DdNode * bRes, * bTemp, * bVar;
+ int i, iGroupFirst, TimeStop;
+ TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
+ bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes );
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i )
+ {
+ if ( Saig_ObjIsPi(p->pAig, pObj) )
+ continue;
+ iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj));
+ assert( iGroupFirst <= iGrpPlace );
+ if ( iGroupFirst < iGrpPlace )
+ continue;
+ bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
+ bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i )
+ {
+ if ( Saig_ObjIsPi(p->pAig, pObj) )
+ continue;
+ iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj));
+ assert( iGroupFirst <= iGrpPlace );
+ if ( iGroupFirst < iGrpPlace )
+ continue;
+ bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) );
+ bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ Cudd_Deref( bRes );
+ p->dd->TimeStop = TimeStop;
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_ManComputeInitState( Llb_Man_t * p, DdManager * dd )
+{
+ Aig_Obj_t * pObj;
+ DdNode * bRes, * bVar, * bTemp;
+ int i, iVar, TimeStop;
+ TimeStop = dd->TimeStop; dd->TimeStop = 0;
+ bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes );
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ {
+ iVar = (dd == p->ddG) ? i : Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj));
+ bVar = Cudd_bddIthVar( dd, iVar );
+ bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bRes );
+ dd->TimeStop = TimeStop;
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_ManComputeImage( Llb_Man_t * p, DdNode * bInit, int fBackward )
+{
+ int fCheckSupport = 0;
+ Llb_Grp_t * pGroup;
+ DdNode * bImage, * bGroup, * bCube, * bTemp;
+ int k, Index;
+ bImage = bInit; Cudd_Ref( bImage );
+ for ( k = 1; k < p->pMatrix->nCols-1; k++ )
+ {
+ if ( fBackward )
+ Index = p->pMatrix->nCols - 1 - k;
+ else
+ Index = k;
+
+ // compute group BDD
+ pGroup = p->pMatrix->pColGrps[Index];
+ bGroup = Llb_ManConstructGroupBdd( p, pGroup );
+ if ( bGroup == NULL )
+ {
+ Cudd_RecursiveDeref( p->dd, bImage );
+ return NULL;
+ }
+ Cudd_Ref( bGroup );
+ // quantify variables appearing only in this group
+ bCube = Llb_ManConstructQuantCubeIntern( p, pGroup, Index, fBackward ); Cudd_Ref( bCube );
+ bGroup = Cudd_bddExistAbstract( p->dd, bTemp = bGroup, bCube );
+ if ( bGroup == NULL )
+ {
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->dd, bCube );
+ return NULL;
+ }
+ Cudd_Ref( bGroup );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->dd, bCube );
+ // perform partial product
+ if ( fBackward )
+ bCube = Llb_ManConstructQuantCubeBwd( p, pGroup, Index );
+ else
+ bCube = Llb_ManConstructQuantCubeFwd( p, pGroup, Index );
+ Cudd_Ref( bCube );
+// bImage = Extra_bddAndAbstractTime( p->dd, bTemp = bImage, bGroup, bCube, p->pPars->TimeTarget );
+ bImage = Cudd_bddAndAbstract( p->dd, bTemp = bImage, bGroup, bCube );
+ if ( bImage == NULL )
+ {
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->dd, bGroup );
+ Cudd_RecursiveDeref( p->dd, bCube );
+ return NULL;
+ }
+ Cudd_Ref( bImage );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->dd, bGroup );
+ Cudd_RecursiveDeref( p->dd, bCube );
+ }
+
+ // make sure image depends on next state vars
+ if ( fCheckSupport )
+ {
+ bCube = Cudd_Support( p->dd, bImage ); Cudd_Ref( bCube );
+ for ( bTemp = bCube; bTemp != p->dd->one; bTemp = cuddT(bTemp) )
+ {
+ int ObjId = Vec_IntEntry( p->vVar2Obj, bTemp->index );
+ Aig_Obj_t * pObj = Aig_ManObj( p->pAig, ObjId );
+ if ( !Saig_ObjIsLi(p->pAig, pObj) )
+ printf( "Var %d assigned to obj %d that is not LI\n", bTemp->index, ObjId );
+ }
+ Cudd_RecursiveDeref( p->dd, bCube );
+ }
+ Cudd_Deref( bImage );
+ return bImage;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_ManCreateConstraints( Llb_Man_t * p, Vec_Int_t * vHints, int fUseNsVars )
+{
+ DdNode * bConstr, * bFunc, * bTemp;
+ Aig_Obj_t * pObj;
+ int i, Entry, TimeStop;
+ if ( vHints == NULL )
+ return Cudd_ReadOne( p->dd );
+ TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
+ assert( Aig_ManPiNum(p->pAig) == Aig_ManPiNum(p->pAigGlo) );
+ // assign const and PI nodes to the original AIG
+ Aig_ManCleanData( p->pAig );
+ Aig_ManConst1( p->pAig )->pData = Cudd_ReadOne( p->dd );
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ pObj->pData = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var,Aig_ObjId(pObj)) );
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ {
+ if ( fUseNsVars )
+ Entry = Vec_IntEntry( p->vObj2Var, Aig_ObjId(Saig_ObjLoToLi(p->pAig, pObj)) );
+ else
+ Entry = Vec_IntEntry( p->vObj2Var, Aig_ObjId(pObj) );
+ pObj->pData = Cudd_bddIthVar( p->dd, Entry );
+ }
+ // transfer them to the global AIG
+ Aig_ManCleanData( p->pAigGlo );
+ Aig_ManConst1( p->pAigGlo )->pData = Cudd_ReadOne( p->dd );
+ Aig_ManForEachPi( p->pAigGlo, pObj, i )
+ pObj->pData = Aig_ManPi(p->pAig, i)->pData;
+ // derive consraints
+ bConstr = Cudd_ReadOne( p->dd ); Cudd_Ref( bConstr );
+ Vec_IntForEachEntry( vHints, Entry, i )
+ {
+ if ( Entry != 0 && Entry != 1 )
+ continue;
+ bFunc = Llb_ManConstructOutBdd( p->pAigGlo, Aig_ManObj(p->pAigGlo, i), p->dd ); Cudd_Ref( bFunc );
+ bFunc = Cudd_NotCond( bFunc, Entry ); // restrict to not constraint
+ // make the product
+ bConstr = Cudd_bddAnd( p->dd, bTemp = bConstr, bFunc ); Cudd_Ref( bConstr );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->dd, bFunc );
+ }
+ Cudd_Deref( bConstr );
+ p->dd->TimeStop = TimeStop;
+ return bConstr;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Perform reachability with hints and returns reached states in ppGlo.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Cex_t * Llb_ManReachDeriveCex( Llb_Man_t * p )
+{
+ Abc_Cex_t * pCex;
+ Aig_Obj_t * pObj;
+ DdNode * bState, * bImage, * bOneCube, * bTemp, * bRing;
+ int i, v, RetValue, nPiOffset;
+ char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) );
+ assert( Vec_PtrSize(p->vRings) > 0 );
+
+ p->dd->TimeStop = 0;
+ p->ddR->TimeStop = 0;
+
+/*
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ printf( "%d ", pObj->Id );
+ printf( "\n" );
+ Saig_ManForEachLi( p->pAig, pObj, i )
+ printf( "%d(%d) ", pObj->Id, Aig_ObjFaninId0(pObj) );
+ printf( "\n" );
+*/
+ // allocate room for the counter-example
+ pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) );
+ pCex->iFrame = Vec_PtrSize(p->vRings) - 1;
+ pCex->iPo = -1;
+
+ // get the last cube
+ bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc ); Cudd_Ref( bOneCube );
+ RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues );
+ Cudd_RecursiveDeref( p->ddR, bOneCube );
+ assert( RetValue );
+
+ // write PIs of counter-example
+ nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1);
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 )
+ Abc_InfoSetBit( pCex->pData, nPiOffset + i );
+
+ // write state in terms of NS variables
+ if ( Vec_PtrSize(p->vRings) > 1 )
+ {
+ bState = Llb_CoreComputeCube( p->dd, p->vGlo2Ns, 1, pValues ); Cudd_Ref( bState );
+ }
+ // perform backward analysis
+ Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v )
+ {
+ if ( v == Vec_PtrSize(p->vRings) - 1 )
+ continue;
+//Extra_bddPrintSupport( p->dd, bState ); printf( "\n" );
+//Extra_bddPrintSupport( p->dd, bRing ); printf( "\n" );
+ // compute the next states
+ bImage = Llb_ManComputeImage( p, bState, 1 );
+ assert( bImage != NULL );
+ Cudd_Ref( bImage );
+ Cudd_RecursiveDeref( p->dd, bState );
+//Extra_bddPrintSupport( p->dd, bImage ); printf( "\n" );
+
+ // move reached states into ring manager
+ bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) ); Cudd_Ref( bImage );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+//Extra_bddPrintSupport( p->ddR, bImage ); printf( "\n" );
+
+ // intersect with the previous set
+ bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing ); Cudd_Ref( bOneCube );
+ Cudd_RecursiveDeref( p->ddR, bImage );
+
+ // find any assignment of the BDD
+ RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues );
+ Cudd_RecursiveDeref( p->ddR, bOneCube );
+ assert( RetValue );
+/*
+ for ( i = 0; i < p->ddR->size; i++ )
+ printf( "%d ", pValues[i] );
+ printf( "\n" );
+*/
+ // write PIs of counter-example
+ nPiOffset -= Saig_ManPiNum(p->pAig);
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 )
+ Abc_InfoSetBit( pCex->pData, nPiOffset + i );
+
+ // check that we get the init state
+ if ( v == 0 )
+ {
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ assert( pValues[i] == 0 );
+ break;
+ }
+
+ // write state in terms of NS variables
+ bState = Llb_CoreComputeCube( p->dd, p->vGlo2Ns, 1, pValues ); Cudd_Ref( bState );
+ }
+ assert( nPiOffset == Saig_ManRegNum(p->pAig) );
+ // update the output number
+//Abc_CexPrint( pCex );
+ RetValue = Saig_ManFindFailedPoCex( p->pAigGlo, pCex );
+ assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pAigGlo) ); // invalid CEX!!!
+ pCex->iPo = RetValue;
+ // cleanup
+ ABC_FREE( pValues );
+ return pCex;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Perform reachability with hints and returns reached states in ppGlo.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManReachability( Llb_Man_t * p, Vec_Int_t * vHints, DdManager ** pddGlo )
+{
+ int * pNs2Glo = Vec_IntArray( p->vNs2Glo );
+ int * pCs2Glo = Vec_IntArray( p->vCs2Glo );
+ int * pGlo2Cs = Vec_IntArray( p->vGlo2Cs );
+ DdNode * bCurrent, * bReached, * bNext, * bTemp, * bCube;
+ DdNode * bConstrCs, * bConstrNs;
+ int clk2, clk = clock(), nIters, nBddSize = 0;
+ int nThreshold = 10000;
+
+ // compute time to stop
+ p->pPars->TimeTarget = p->pPars->TimeLimit ? time(NULL) + p->pPars->TimeLimit : 0;
+
+ // define variable limits
+ Llb_ManPrepareVarLimits( p );
+
+ // start the managers
+ assert( p->dd == NULL );
+ assert( p->ddG == NULL );
+ assert( p->ddR == NULL );
+ p->dd = Cudd_Init( Vec_IntSize(p->vVar2Obj), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ p->ddR = Cudd_Init( Aig_ManPiNum(p->pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ if ( pddGlo && *pddGlo )
+ p->ddG = *pddGlo, *pddGlo = NULL;
+ else
+ p->ddG = Cudd_Init( Aig_ManRegNum(p->pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+
+ if ( p->pPars->fReorder )
+ {
+ Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT );
+ Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT );
+ Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT );
+ }
+ else
+ {
+ Cudd_AutodynDisable( p->dd );
+ Cudd_AutodynDisable( p->ddG );
+ Cudd_AutodynDisable( p->ddR );
+ }
+
+ // set the stop time parameter
+ p->dd->TimeStop = p->pPars->TimeTarget;
+ p->ddG->TimeStop = p->pPars->TimeTarget;
+ p->ddR->TimeStop = p->pPars->TimeTarget;
+
+ // create bad state in the ring manager
+ p->ddR->bFunc = Llb_BddComputeBad( p->pAigGlo, p->ddR, p->pPars->TimeTarget );
+ if ( p->ddR->bFunc == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = -1;
+ return -1;
+ }
+ Cudd_Ref( p->ddR->bFunc );
+
+ // derive constraints
+ bConstrCs = Llb_ManCreateConstraints( p, vHints, 0 ); Cudd_Ref( bConstrCs );
+ bConstrNs = Llb_ManCreateConstraints( p, vHints, 1 ); Cudd_Ref( bConstrNs );
+//Extra_bddPrint( p->dd, bConstrCs ); printf( "\n" );
+//Extra_bddPrint( p->dd, bConstrNs ); printf( "\n" );
+
+ // perform reachability analysis
+ // compute the starting set of states
+ if ( p->ddG->bFunc )
+ {
+ bReached = p->ddG->bFunc; p->ddG->bFunc = NULL;
+ bCurrent = Extra_TransferPermute( p->ddG, p->dd, bReached, pGlo2Cs ); Cudd_Ref( bCurrent );
+ }
+ else
+ {
+ bReached = Llb_ManComputeInitState( p, p->ddG ); Cudd_Ref( bReached );
+ bCurrent = Llb_ManComputeInitState( p, p->dd ); Cudd_Ref( bCurrent );
+ }
+//Extra_bddPrintSupport( p->ddG, bReached ); printf( "\n" );
+//Extra_bddPrintSupport( p->dd, bCurrent ); printf( "\n" );
+
+//Extra_bddPrintSupport( p->dd, bCurrent ); printf( "\n" );
+ for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ )
+ {
+ clk2 = clock();
+ // check the runtime limit
+ if ( p->pPars->TimeLimit && time(NULL) > p->pPars->TimeTarget )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout during image computation (%d seconds).\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL;
+ Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL;
+ Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL;
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+
+ // save the onion ring
+ bTemp = Extra_TransferPermute( p->dd, p->ddR, bCurrent, pCs2Glo );
+ if ( bTemp == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during ring transfer.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL;
+ Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL;
+ Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL;
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+ Cudd_Ref( bTemp );
+ Vec_PtrPush( p->vRings, bTemp );
+
+ // check it for bad states
+ if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) )
+ {
+ assert( p->pAigGlo->pSeqModel == NULL );
+ if ( !p->pPars->fBackward )
+ p->pAigGlo->pSeqModel = Llb_ManReachDeriveCex( p );
+ if ( !p->pPars->fSilent )
+ {
+ if ( !p->pPars->fBackward )
+ printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump a witness). ", p->pAigGlo->pSeqModel->iPo, nIters );
+ else
+ printf( "Output ??? was asserted in frame %d (counter-example is not produced). ", nIters );
+ Abc_PrintTime( 1, "Time", clock() - clk );
+ }
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL;
+ Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL;
+ Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL;
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ return 0;
+ }
+
+ // restrict reachable states using constraints
+ if ( vHints )
+ {
+ bCurrent = Cudd_bddAnd( p->dd, bTemp = bCurrent, bConstrCs ); Cudd_Ref( bCurrent );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+
+ // quantify variables appearing only in the init state
+ bCube = Llb_ManConstructQuantCubeIntern( p, (Llb_Grp_t *)Vec_PtrEntry(p->vGroups,0), 0, 0 ); Cudd_Ref( bCube );
+ bCurrent = Cudd_bddExistAbstract( p->dd, bTemp = bCurrent, bCube ); Cudd_Ref( bCurrent );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->dd, bCube );
+
+ // compute the next states
+ bNext = Llb_ManComputeImage( p, bCurrent, 0 );
+ if ( bNext == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL;
+ Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL;
+ Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL;
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+ Cudd_Ref( bNext );
+ Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL;
+
+ // restrict reachable states using constraints
+ if ( vHints )
+ {
+ bNext = Cudd_bddAnd( p->dd, bTemp = bNext, bConstrNs ); Cudd_Ref( bNext );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+//Extra_bddPrintSupport( p->dd, bNext ); printf( "\n" );
+
+ // remap these states into the current state vars
+// bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pNs2Glo ); Cudd_Ref( bNext );
+// Cudd_RecursiveDeref( p->dd, bTemp );
+// bNext = Extra_TransferPermuteTime( p->dd, p->ddG, bTemp = bNext, pNs2Glo, p->pPars->TimeTarget );
+ bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pNs2Glo );
+ if ( bNext == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL;
+ Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL;
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+ Cudd_Ref( bNext );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+
+
+ // check if there are any new states
+ if ( Cudd_bddLeq( p->ddG, bNext, bReached ) ) // implication = no new states
+ {
+ Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL;
+ break;
+ }
+
+ // check the BDD size
+ nBddSize = Cudd_DagSize(bNext);
+ if ( nBddSize > p->pPars->nBddMax )
+ {
+ Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL;
+ break;
+ }
+
+ // get the new states
+ bCurrent = Cudd_bddAnd( p->ddG, bNext, Cudd_Not(bReached) );
+ if ( bCurrent == NULL )
+ {
+ Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL;
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ break;
+ }
+ Cudd_Ref( bCurrent );
+ // minimize the new states with the reached states
+// bCurrent = Cudd_bddConstrain( p->ddG, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent );
+// bCurrent = Cudd_bddRestrict( p->ddG, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent );
+// Cudd_RecursiveDeref( p->ddG, bTemp );
+//printf( "Initial BDD =%7d. Constrained BDD =%7d.\n", Cudd_DagSize(bTemp), Cudd_DagSize(bCurrent) );
+
+ // remap these states into the current state vars
+// bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs ); Cudd_Ref( bCurrent );
+// Cudd_RecursiveDeref( p->ddG, bTemp );
+// bCurrent = Extra_TransferPermuteTime( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs, p->pPars->TimeTarget );
+ bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs );
+ if ( bCurrent == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->ddG, bTemp );
+ Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL;
+ Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL;
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+ Cudd_Ref( bCurrent );
+ Cudd_RecursiveDeref( p->ddG, bTemp );
+
+
+ // add to the reached states
+ bReached = Cudd_bddOr( p->ddG, bTemp = bReached, bNext );
+ if ( bReached == NULL )
+ {
+ Cudd_RecursiveDeref( p->ddG, bTemp ); bTemp = NULL;
+ Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL;
+ break;
+ }
+ Cudd_Ref( bReached );
+ Cudd_RecursiveDeref( p->ddG, bTemp );
+ Cudd_RecursiveDeref( p->ddG, bNext );
+ bNext = NULL;
+
+ if ( p->pPars->fVerbose )
+ {
+ fprintf( stdout, "F =%5d : ", nIters );
+ fprintf( stdout, "Im =%6d ", nBddSize );
+ fprintf( stdout, "(%4d %3d) ", Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) );
+ fprintf( stdout, "Rea =%6d ", Cudd_DagSize(bReached) );
+ fprintf( stdout, "(%4d%4d) ", Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) );
+ Abc_PrintTime( 1, "Time", clock() - clk2 );
+ }
+/*
+ if ( p->pPars->fVerbose )
+ {
+ double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) );
+// Extra_bddPrint( p->ddG, bReached );printf( "\n" );
+ fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) );
+ fflush( stdout );
+ }
+*/
+ }
+ Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL;
+ Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL;
+ if ( bReached == NULL )
+ {
+ p->pPars->iFrame = nIters - 1;
+ return 0; // reachable
+ }
+// assert( bCurrent == NULL );
+ if ( bCurrent )
+ Cudd_RecursiveDeref( p->dd, bCurrent );
+ // report the stats
+ if ( p->pPars->fVerbose )
+ {
+ double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) );
+ if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax )
+ fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters );
+ else
+ fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters );
+ fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) );
+ fflush( stdout );
+ }
+ if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Verified only for states reachable in %d frames. ", nIters );
+ p->pPars->iFrame = p->pPars->nIterMax;
+ Cudd_RecursiveDeref( p->ddG, bReached );
+ return -1; // undecided
+ }
+ if ( pddGlo )
+ {
+ assert( p->ddG->bFunc == NULL );
+ p->ddG->bFunc = bReached; bReached = NULL;
+ assert( *pddGlo == NULL );
+ *pddGlo = p->ddG; p->ddG = NULL;
+ }
+ else
+ Cudd_RecursiveDeref( p->ddG, bReached );
+ if ( !p->pPars->fSilent )
+ printf( "The miter is proved unreachable after %d iterations. ", nIters );
+ p->pPars->iFrame = nIters - 1;
+ return 1; // unreachable
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/llb/llb1Sched.c b/src/proof/llb/llb1Sched.c
new file mode 100644
index 00000000..6bdae42e
--- /dev/null
+++ b/src/proof/llb/llb1Sched.c
@@ -0,0 +1,257 @@
+/**CFile****************************************************************
+
+ FileName [llb1Sched.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Partition scheduling algorithm.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb1Sched.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Swaps two rows.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MtrSwapColumns( Llb_Mtr_t * p, int iCol1, int iCol2 )
+{
+ Llb_Grp_t * pGemp;
+ char * pTemp;
+ int iTemp;
+ assert( iCol1 >= 0 && iCol1 < p->nCols );
+ assert( iCol2 >= 0 && iCol2 < p->nCols );
+ if ( iCol1 == iCol2 )
+ return;
+ assert( iCol1 != iCol2 );
+ // swap col groups
+ pGemp = p->pColGrps[iCol1];
+ p->pColGrps[iCol1] = p->pColGrps[iCol2];
+ p->pColGrps[iCol2] = pGemp;
+ // swap col vectors
+ pTemp = p->pMatrix[iCol1];
+ p->pMatrix[iCol1] = p->pMatrix[iCol2];
+ p->pMatrix[iCol2] = pTemp;
+ // swap col sums
+ iTemp = p->pColSums[iCol1];
+ p->pColSums[iCol1] = p->pColSums[iCol2];
+ p->pColSums[iCol2] = iTemp;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find columns which brings as few vars as possible.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_MtrFindBestColumn( Llb_Mtr_t * p, int iGrpStart )
+{
+ int Cost, Cost2, CostBest = ABC_INFINITY, Cost2Best = ABC_INFINITY;
+ int WeightCur, WeightBest = -ABC_INFINITY, iGrp, iGrpBest = -1;
+ int k, c, iVar, Counter;
+ // find partition that reduces partial product as much as possible
+ for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ )
+ {
+ if ( p->pRowSums[iVar] < 2 )
+ continue;
+ // look at present variables that can be quantified
+ if ( !(p->pProdVars[iVar] == 1 && p->pProdNums[iVar] == 1) )
+ continue;
+ // check that it appears in one partition only
+ Counter = 0;
+ for ( c = iGrpStart; c < p->nCols-1; c++ )
+ if ( p->pMatrix[c][iVar] == 1 )
+ {
+ iGrp = c;
+ Counter++;
+ }
+ assert( Counter == 1 );
+ if ( Counter != 1 )
+ Abc_Print( -1, "Llb_MtrFindBestColumn() Internal error!\n" );
+ // find weight of this column
+ WeightCur = 0;
+ for ( k = 0; k < p->nRows; k++ )
+ {
+ // increase weight if variable k will be quantified from partial product
+ if ( p->pProdVars[k] == 1 && p->pMatrix[iGrp][k] == 1 && p->pProdNums[k] == 1 )
+ WeightCur += 2;
+ // decrease weight if variable k will be added to partial product
+ if ( p->pProdVars[k] == 0 && p->pMatrix[iGrp][k] == 1 )
+ WeightCur--;
+ }
+ if ( WeightCur > 0 && WeightBest < WeightCur )
+ {
+ WeightBest = WeightCur;
+ iGrpBest = iGrp;
+ }
+ }
+ if ( iGrpBest >= 0 )
+ return iGrpBest;
+ // could not find the group with any vars to quantify
+ // select the group that contains as few extra variables as possible
+ // if there is a tie, select variables that appear in less groups than others
+ for ( iGrp = iGrpStart; iGrp < p->nCols-1; iGrp++ )
+ {
+ Cost = Cost2 = 0;
+ for ( k = 0; k < p->nRows; k++ )
+ if ( p->pProdVars[k] == 0 && p->pMatrix[iGrp][k] == 1 )
+ {
+ Cost++;
+ Cost2 += p->pProdNums[k];
+ }
+ if ( CostBest > Cost ||
+ (CostBest == Cost && Cost2 > Cost2Best) )
+ {
+ CostBest = Cost;
+ Cost2Best = Cost2;
+ iGrpBest = iGrp;
+ }
+ }
+ return iGrpBest;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of variables that will be saved.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MtrUseSelectedColumn( Llb_Mtr_t * p, int iCol )
+{
+ int iVar;
+ assert( iCol >= 1 && iCol < p->nCols - 1 );
+ for ( iVar = 0; iVar < p->nRows; iVar++ )
+ {
+ if ( p->pMatrix[iCol][iVar] == 0 )
+ continue;
+ if ( p->pProdVars[iVar] == 1 && p->pProdNums[iVar] == 1 )
+ {
+ p->pProdVars[iVar] = 0;
+ p->pProdNums[iVar] = 0;
+ continue;
+ }
+ if ( p->pProdVars[iVar] == 0 )
+ {
+ p->pProdVars[iVar] = 1;
+ p->pProdNums[iVar] = p->pRowSums[iVar];
+ }
+ p->pProdNums[iVar]--;
+ assert( p->pProdNums[iVar] >= 0 );
+ if ( p->pProdNums[iVar] < 0 )
+ Abc_Print( -1, "Llb_MtrUseSelectedColumn() Internal error!\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verify columns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MtrVerifyColumns( Llb_Mtr_t * p, int iGrpStart )
+{
+ int iVar, iGrp, Counter;
+ for ( iVar = 0; iVar < p->nRows; iVar++ )
+ {
+ if ( p->pProdVars[iVar] == 0 )
+ continue;
+ Counter = 0;
+ for ( iGrp = iGrpStart; iGrp < p->nCols; iGrp++ )
+ if ( p->pMatrix[iGrp][iVar] == 1 )
+ Counter++;
+ assert( Counter == p->pProdNums[iVar] );
+ if ( Counter != p->pProdNums[iVar] )
+ Abc_Print( -1, "Llb_MtrVerifyColumns(): Internal error.\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Matrix reduce.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MtrSchedule( Llb_Mtr_t * p )
+{
+ int iGrp, iGrpBest, i;
+ // start partial product
+ for ( i = 0; i < p->nRows; i++ )
+ {
+ if ( i >= p->nPis && i < p->nPis + p->nFfs )
+ {
+ p->pProdVars[i] = 1;
+ p->pProdNums[i] = p->pRowSums[i] - 1;
+ }
+ else
+ {
+ p->pProdVars[i] = 0;
+ p->pProdNums[i] = p->pRowSums[i];
+ }
+ }
+ // order the partitions
+ Llb_MtrVerifyMatrix( p );
+ for ( iGrp = 1; iGrp < p->nCols-1; iGrp++ )
+ {
+ Llb_MtrVerifyColumns( p, iGrp );
+ iGrpBest = Llb_MtrFindBestColumn( p, iGrp );
+ Llb_MtrUseSelectedColumn( p, iGrpBest );
+ Llb_MtrSwapColumns( p, iGrp, iGrpBest );
+ }
+ Llb_MtrVerifyMatrix( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/llb/llb2Bad.c b/src/proof/llb/llb2Bad.c
new file mode 100644
index 00000000..9aecb9ff
--- /dev/null
+++ b/src/proof/llb/llb2Bad.c
@@ -0,0 +1,137 @@
+/**CFile****************************************************************
+
+ FileName [llb2Bad.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Computing bad states.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb2Bad.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes bad in working manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_BddComputeBad( Aig_Man_t * pInit, DdManager * dd, int TimeOut )
+{
+ Vec_Ptr_t * vNodes;
+ DdNode * bBdd0, * bBdd1, * bTemp, * bResult;
+ Aig_Obj_t * pObj;
+ int i, k;
+ assert( Cudd_ReadSize(dd) == Aig_ManPiNum(pInit) );
+ // initialize elementary variables
+ Aig_ManConst1(pInit)->pData = Cudd_ReadOne( dd );
+ Saig_ManForEachLo( pInit, pObj, i )
+ pObj->pData = Cudd_bddIthVar( dd, i );
+ Saig_ManForEachPi( pInit, pObj, i )
+ pObj->pData = Cudd_bddIthVar( dd, Aig_ManRegNum(pInit) + i );
+ // compute internal nodes
+ vNodes = Aig_ManDfsNodes( pInit, (Aig_Obj_t **)Vec_PtrArray(pInit->vPos), Saig_ManPoNum(pInit) );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+ {
+ if ( !Aig_ObjIsNode(pObj) )
+ continue;
+ bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+// pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeOut );
+ pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 );
+ if ( pObj->pData == NULL )
+ {
+ Vec_PtrForEachEntryStop( Aig_Obj_t *, vNodes, pObj, k, i )
+ if ( pObj->pData )
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+ Vec_PtrFree( vNodes );
+ return NULL;
+ }
+ Cudd_Ref( (DdNode *)pObj->pData );
+ }
+ // quantify PIs of each PO
+ bResult = Cudd_ReadLogicZero( dd ); Cudd_Ref( bResult );
+ Saig_ManForEachPo( pInit, pObj, i )
+ {
+ bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bResult = Cudd_bddOr( dd, bTemp = bResult, bBdd0 ); Cudd_Ref( bResult );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ // deref
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+ {
+ if ( !Aig_ObjIsNode(pObj) )
+ continue;
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+ }
+ Vec_PtrFree( vNodes );
+ Cudd_Deref( bResult );
+ return bResult;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_BddQuantifyPis( Aig_Man_t * pInit, DdManager * dd, DdNode * bFunc )
+{
+ DdNode * bVar, * bCube, * bTemp;
+ Aig_Obj_t * pObj;
+ int i, TimeStop;
+ assert( Cudd_ReadSize(dd) == Aig_ManPiNum(pInit) );
+ TimeStop = dd->TimeStop; dd->TimeStop = 0;
+ // create PI cube
+ bCube = Cudd_ReadOne( dd ); Cudd_Ref( bCube );
+ Saig_ManForEachPi( pInit, pObj, i ) {
+ bVar = Cudd_bddIthVar( dd, Aig_ManRegNum(pInit) + i );
+ bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ // quantify PI cube
+ bFunc = Cudd_bddExistAbstract( dd, bFunc, bCube ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( dd, bCube );
+ Cudd_Deref( bFunc );
+ dd->TimeStop = TimeStop;
+ return bFunc;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/llb/llb2Core.c b/src/proof/llb/llb2Core.c
new file mode 100644
index 00000000..c15574c2
--- /dev/null
+++ b/src/proof/llb/llb2Core.c
@@ -0,0 +1,775 @@
+/**CFile****************************************************************
+
+ FileName [llb2Core.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Core procedure.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb2Core.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Llb_Img_t_ Llb_Img_t;
+struct Llb_Img_t_
+{
+ Aig_Man_t * pInit; // AIG manager
+ Aig_Man_t * pAig; // AIG manager
+ Gia_ParLlb_t * pPars; // parameters
+
+ DdManager * dd; // BDD manager
+ DdManager * ddG; // BDD manager
+ DdManager * ddR; // BDD manager
+ Vec_Ptr_t * vDdMans; // BDD managers for each partition
+ Vec_Ptr_t * vRings; // onion rings in ddR
+
+ Vec_Int_t * vDriRefs; // driver references
+ Vec_Int_t * vVarsCs; // cur state variables
+ Vec_Int_t * vVarsNs; // next state variables
+
+ Vec_Int_t * vCs2Glo; // cur state variables into global variables
+ Vec_Int_t * vNs2Glo; // next state variables into global variables
+ Vec_Int_t * vGlo2Cs; // global variables into cur state variables
+ Vec_Int_t * vGlo2Ns; // global variables into next state variables
+};
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes cube composed of given variables with given values.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_CoreComputeCube( DdManager * dd, Vec_Int_t * vVars, int fUseVarIndex, char * pValues )
+{
+ DdNode * bRes, * bVar, * bTemp;
+ int i, iVar, Index, TimeStop;
+ TimeStop = dd->TimeStop; dd->TimeStop = 0;
+ bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes );
+ Vec_IntForEachEntry( vVars, Index, i )
+ {
+ iVar = fUseVarIndex ? Index : i;
+ bVar = Cudd_NotCond( Cudd_bddIthVar(dd, iVar), (int)(pValues == NULL || pValues[i] != 1) );
+ bRes = Cudd_bddAnd( dd, bTemp = bRes, bVar ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bRes );
+ dd->TimeStop = TimeStop;
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives counter-example by backward reachability.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Cex_t * Llb_CoreDeriveCex( Llb_Img_t * p )
+{
+ Abc_Cex_t * pCex;
+ Aig_Obj_t * pObj;
+ Vec_Ptr_t * vSupps, * vQuant0, * vQuant1;
+ DdNode * bState, * bImage, * bOneCube, * bTemp, * bRing;
+ int i, v, RetValue, nPiOffset;
+ char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) );
+ assert( Vec_PtrSize(p->vRings) > 0 );
+
+ p->dd->TimeStop = 0;
+ p->ddR->TimeStop = 0;
+
+ // get supports and quantified variables
+ Vec_PtrReverseOrder( p->vDdMans );
+ vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsNs, p->vVarsCs, 1, 0 );
+ Llb_ImgSchedule( vSupps, &vQuant0, &vQuant1, 0 );
+ Vec_VecFree( (Vec_Vec_t *)vSupps );
+ Llb_ImgQuantifyReset( p->vDdMans );
+// Llb_ImgQuantifyFirst( p->pAig, p->vDdMans, vQuant0 );
+
+ // allocate room for the counter-example
+ pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) );
+ pCex->iFrame = Vec_PtrSize(p->vRings) - 1;
+ pCex->iPo = -1;
+
+ // get the last cube
+ bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc ); Cudd_Ref( bOneCube );
+ RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues );
+ Cudd_RecursiveDeref( p->ddR, bOneCube );
+ assert( RetValue );
+
+ // write PIs of counter-example
+ nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1);
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 )
+ Abc_InfoSetBit( pCex->pData, nPiOffset + i );
+
+ // write state in terms of NS variables
+ if ( Vec_PtrSize(p->vRings) > 1 )
+ {
+ bState = Llb_CoreComputeCube( p->dd, p->vVarsNs, 1, pValues ); Cudd_Ref( bState );
+ }
+ // perform backward analysis
+ Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v )
+ {
+ if ( v == Vec_PtrSize(p->vRings) - 1 )
+ continue;
+ // compute the next states
+ bImage = Llb_ImgComputeImage( p->pAig, p->vDdMans, p->dd, bState,
+ vQuant0, vQuant1, p->vDriRefs, p->pPars->TimeTarget, 1, 0, 0 );
+ assert( bImage != NULL );
+ Cudd_Ref( bImage );
+ Cudd_RecursiveDeref( p->dd, bState );
+//Extra_bddPrintSupport( p->dd, bImage ); printf( "\n" );
+
+ // move reached states into ring manager
+ bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) ); Cudd_Ref( bImage );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+
+ // intersect with the previous set
+ bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing ); Cudd_Ref( bOneCube );
+ Cudd_RecursiveDeref( p->ddR, bImage );
+
+ // find any assignment of the BDD
+ RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues );
+ Cudd_RecursiveDeref( p->ddR, bOneCube );
+ assert( RetValue );
+
+ // write PIs of counter-example
+ nPiOffset -= Saig_ManPiNum(p->pAig);
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 )
+ Abc_InfoSetBit( pCex->pData, nPiOffset + i );
+
+ // check that we get the init state
+ if ( v == 0 )
+ {
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ assert( pValues[i] == 0 );
+ break;
+ }
+
+ // write state in terms of NS variables
+ bState = Llb_CoreComputeCube( p->dd, p->vVarsNs, 1, pValues ); Cudd_Ref( bState );
+ }
+ assert( nPiOffset == Saig_ManRegNum(p->pAig) );
+ // update the output number
+ RetValue = Saig_ManFindFailedPoCex( p->pInit, pCex );
+ assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pInit) ); // invalid CEX!!!
+ pCex->iPo = RetValue;
+ // cleanup
+ ABC_FREE( pValues );
+ Vec_VecFree( (Vec_Vec_t *)vQuant0 );
+ Vec_VecFree( (Vec_Vec_t *)vQuant1 );
+ return pCex;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_CoreReachability_int( Llb_Img_t * p, Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1 )
+{
+ int * pLoc2Glo = p->pPars->fBackward? Vec_IntArray( p->vCs2Glo ) : Vec_IntArray( p->vNs2Glo );
+ int * pLoc2GloR = p->pPars->fBackward? Vec_IntArray( p->vNs2Glo ) : Vec_IntArray( p->vCs2Glo );
+ int * pGlo2Loc = p->pPars->fBackward? Vec_IntArray( p->vGlo2Ns ) : Vec_IntArray( p->vGlo2Cs );
+ DdNode * bCurrent, * bReached, * bNext, * bTemp;
+ int clk2, clk = clock(), nIters, nBddSize, iOutFail = -1;
+/*
+ // compute time to stop
+ if ( p->pPars->TimeLimit )
+ p->pPars->TimeTarget = clock() + p->pPars->TimeLimit * CLOCKS_PER_SEC;
+ else
+ p->pPars->TimeTarget = 0;
+*/
+
+ if ( time(NULL) > p->pPars->TimeTarget )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) before image computation.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = -1;
+ return -1;
+ }
+
+ // set the stop time parameter
+ p->dd->TimeStop = p->pPars->TimeTarget;
+ p->ddG->TimeStop = p->pPars->TimeTarget;
+ p->ddR->TimeStop = p->pPars->TimeTarget;
+
+ // compute initial states
+ if ( p->pPars->fBackward )
+ {
+ // create init state in the global manager
+ bTemp = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget );
+ if ( bTemp == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) while computing bad states.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = -1;
+ return -1;
+ }
+ Cudd_Ref( bTemp );
+ // create bad state in the ring manager
+ p->ddR->bFunc = Llb_CoreComputeCube( p->ddR, p->vVarsCs, 0, NULL ); Cudd_Ref( p->ddR->bFunc );
+ bCurrent = Llb_BddQuantifyPis( p->pInit, p->ddR, bTemp ); Cudd_Ref( bCurrent );
+ Cudd_RecursiveDeref( p->ddR, bTemp );
+ bReached = Cudd_bddTransfer( p->ddR, p->ddG, bCurrent ); Cudd_Ref( bReached );
+ Cudd_RecursiveDeref( p->ddR, bCurrent );
+ // move init state to the working manager
+ bCurrent = Extra_TransferPermute( p->ddG, p->dd, bReached, pGlo2Loc );
+ if ( bCurrent == NULL )
+ {
+ Cudd_RecursiveDeref( p->ddG, bReached );
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during transfer 0.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = -1;
+ return -1;
+ }
+ Cudd_Ref( bCurrent );
+ }
+ else
+ {
+ // create bad state in the ring manager
+ p->ddR->bFunc = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget );
+ if ( p->ddR->bFunc == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) while computing bad states.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = -1;
+ return -1;
+ }
+ Cudd_Ref( p->ddR->bFunc );
+ // create init state in the working and global manager
+ bCurrent = Llb_CoreComputeCube( p->dd, p->vVarsCs, 1, NULL ); Cudd_Ref( bCurrent );
+ bReached = Llb_CoreComputeCube( p->ddG, p->vVarsCs, 0, NULL ); Cudd_Ref( bReached );
+//Extra_bddPrint( p->dd, bCurrent ); printf( "\n" );
+//Extra_bddPrint( p->ddG, bReached ); printf( "\n" );
+ }
+
+ // compute onion rings
+ for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ )
+ {
+ clk2 = clock();
+ // check the runtime limit
+ if ( p->pPars->TimeLimit && time(NULL) > p->pPars->TimeTarget )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL;
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+
+ // save the onion ring
+ bTemp = Extra_TransferPermute( p->dd, p->ddR, bCurrent, pLoc2GloR );
+ if ( bTemp == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL;
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+ Cudd_Ref( bTemp );
+ Vec_PtrPush( p->vRings, bTemp );
+
+ // check it for bad states
+ if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) )
+ {
+ assert( p->pInit->pSeqModel == NULL );
+ if ( !p->pPars->fBackward )
+ p->pInit->pSeqModel = Llb_CoreDeriveCex( p );
+ Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL;
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ if ( !p->pPars->fSilent )
+ {
+ if ( !p->pPars->fBackward )
+ printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump a witness). ", p->pInit->pSeqModel->iPo, nIters );
+ else
+ printf( "Output ??? was asserted in frame %d (counter-example is not produced). ", nIters );
+ Abc_PrintTime( 1, "Time", clock() - clk );
+ }
+ p->pPars->iFrame = nIters - 1;
+ return 0;
+ }
+
+ // compute the next states
+ bNext = Llb_ImgComputeImage( p->pAig, p->vDdMans, p->dd, bCurrent,
+ vQuant0, vQuant1, p->vDriRefs, p->pPars->TimeTarget,
+ p->pPars->fBackward, p->pPars->fReorder, p->pPars->fVeryVerbose );
+ if ( bNext == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL;
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+ Cudd_Ref( bNext );
+ Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL;
+//Extra_bddPrintSupport( p->dd, bNext ); printf( "\n" );
+
+ // remap these states into the global manager
+// bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pLoc2Glo ); Cudd_Ref( bNext );
+// Cudd_RecursiveDeref( p->dd, bTemp );
+
+// bNext = Extra_TransferPermuteTime( p->dd, p->ddG, bTemp = bNext, pLoc2Glo, p->pPars->TimeTarget );
+ bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pLoc2Glo );
+ if ( bNext == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+ Cudd_Ref( bNext );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+
+ nBddSize = Cudd_DagSize(bNext);
+ // check if there are any new states
+ if ( Cudd_bddLeq( p->ddG, bNext, bReached ) ) // implication = no new states
+ {
+ Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL;
+ break;
+ }
+
+ // get the new states
+ bCurrent = Cudd_bddAnd( p->ddG, bNext, Cudd_Not(bReached) );
+ if ( bCurrent == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->ddG, bNext );
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+ Cudd_Ref( bCurrent );
+
+ // remap these states into the current state vars
+// bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc ); Cudd_Ref( bCurrent );
+// Cudd_RecursiveDeref( p->ddG, bTemp );
+
+// bCurrent = Extra_TransferPermuteTime( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc, p->pPars->TimeTarget );
+ bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc );
+ if ( bCurrent == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->ddG, bTemp );
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+ Cudd_Ref( bCurrent );
+ Cudd_RecursiveDeref( p->ddG, bTemp );
+
+ // add to the reached states
+ bReached = Cudd_bddOr( p->ddG, bTemp = bReached, bNext ); Cudd_Ref( bReached );
+ Cudd_RecursiveDeref( p->ddG, bTemp );
+ Cudd_RecursiveDeref( p->ddG, bNext );
+ bNext = NULL;
+
+ if ( p->pPars->fVeryVerbose )
+ {
+ double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) );
+// Extra_bddPrint( p->ddG, bReached );printf( "\n" );
+ fprintf( stdout, " Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) );
+ fflush( stdout );
+ }
+ if ( p->pPars->fVerbose )
+ {
+ fprintf( stdout, "F =%3d : ", nIters );
+ fprintf( stdout, "Image =%6d ", nBddSize );
+ fprintf( stdout, "(%4d%4d) ",
+ Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) );
+ fprintf( stdout, "Reach =%6d ", Cudd_DagSize(bReached) );
+ fprintf( stdout, "(%4d%4d) ",
+ Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) );
+ Abc_PrintTime( 1, "Time", clock() - clk2 );
+ }
+
+ // check timeframe limit
+ if ( nIters == p->pPars->nIterMax - 1 )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nIterMax );
+ p->pPars->iFrame = nIters;
+ Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL;
+ Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL;
+ return -1;
+ }
+ }
+ if ( bReached == NULL )
+ {
+ p->pPars->iFrame = nIters - 1;
+ return 0; // reachable
+ }
+ if ( bCurrent )
+ Cudd_RecursiveDeref( p->dd, bCurrent );
+ // report the stats
+ if ( p->pPars->fVerbose )
+ {
+ double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) );
+ if ( nIters >= p->pPars->nIterMax )
+ fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters );
+ else
+ fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters );
+ fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) );
+ fflush( stdout );
+ }
+ if ( p->pPars->fDumpReached )
+ {
+ Llb_ManDumpReached( p->ddG, bReached, p->pAig->pName, "reached.blif" );
+ printf( "Reached states with %d BDD nodes are dumpted into file \"reached.blif\".\n", Cudd_DagSize(bReached) );
+ }
+ Cudd_RecursiveDeref( p->ddG, bReached );
+ if ( nIters >= p->pPars->nIterMax )
+ {
+ if ( !p->pPars->fSilent )
+ {
+ printf( "Verified only for states reachable in %d frames. ", nIters );
+ Abc_PrintTime( 1, "Time", clock() - clk );
+ }
+ p->pPars->iFrame = p->pPars->nIterMax;
+ return -1; // undecided
+ }
+ if ( !p->pPars->fSilent )
+ {
+ printf( "The miter is proved unreachable after %d iterations. ", nIters );
+ Abc_PrintTime( 1, "Time", clock() - clk );
+ }
+ p->pPars->iFrame = nIters - 1;
+ return 1; // unreachable
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_CoreReachability( Llb_Img_t * p )
+{
+ Vec_Ptr_t * vSupps, * vQuant0, * vQuant1;
+ int RetValue;
+ // get supports and quantified variables
+ if ( p->pPars->fBackward )
+ {
+ Vec_PtrReverseOrder( p->vDdMans );
+ vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsNs, p->vVarsCs, 0, p->pPars->fVeryVerbose );
+ }
+ else
+ vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsCs, p->vVarsNs, 0, p->pPars->fVeryVerbose );
+ Llb_ImgSchedule( vSupps, &vQuant0, &vQuant1, p->pPars->fVeryVerbose );
+ Vec_VecFree( (Vec_Vec_t *)vSupps );
+ // remove variables
+ Llb_ImgQuantifyFirst( p->pAig, p->vDdMans, vQuant0, p->pPars->fVeryVerbose );
+ // perform reachability
+ RetValue = Llb_CoreReachability_int( p, vQuant0, vQuant1 );
+ Vec_VecFree( (Vec_Vec_t *)vQuant0 );
+ Vec_VecFree( (Vec_Vec_t *)vQuant1 );
+ return RetValue;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_CoreConstructAll( Aig_Man_t * p, Vec_Ptr_t * vResult, Vec_Int_t * vVarsNs, int TimeTarget )
+{
+ DdManager * dd;
+ Vec_Ptr_t * vDdMans;
+ Vec_Ptr_t * vLower, * vUpper;
+ int i;
+ vDdMans = Vec_PtrStart( Vec_PtrSize(vResult) );
+ Vec_PtrForEachEntryReverse( Vec_Ptr_t *, vResult, vLower, i )
+ {
+ if ( i < Vec_PtrSize(vResult) - 1 )
+ dd = Llb_ImgPartition( p, vLower, vUpper, TimeTarget );
+ else
+ dd = Llb_DriverLastPartition( p, vVarsNs, TimeTarget );
+ if ( dd == NULL )
+ {
+ Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i )
+ {
+ if ( dd == NULL )
+ continue;
+ if ( dd->bFunc )
+ Cudd_RecursiveDeref( dd, dd->bFunc );
+ Extra_StopManager( dd );
+ }
+ Vec_PtrFree( vDdMans );
+ return NULL;
+ }
+ Vec_PtrWriteEntry( vDdMans, i, dd );
+ vUpper = vLower;
+ }
+ return vDdMans;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_CoreSetVarMaps( Llb_Img_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i, iVarCs, iVarNs;
+ assert( p->vVarsCs != NULL );
+ assert( p->vVarsNs != NULL );
+ assert( p->vCs2Glo == NULL );
+ assert( p->vNs2Glo == NULL );
+ assert( p->vGlo2Cs == NULL );
+ assert( p->vGlo2Ns == NULL );
+ p->vCs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) );
+ p->vNs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) );
+ p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) );
+ p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) );
+ for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ )
+ {
+ iVarCs = Vec_IntEntry( p->vVarsCs, i );
+ iVarNs = Vec_IntEntry( p->vVarsNs, i );
+ assert( iVarCs >= 0 && iVarCs < Aig_ManObjNumMax(p->pAig) );
+ assert( iVarNs >= 0 && iVarNs < Aig_ManObjNumMax(p->pAig) );
+ Vec_IntWriteEntry( p->vCs2Glo, iVarCs, i );
+ Vec_IntWriteEntry( p->vNs2Glo, iVarNs, i );
+ Vec_IntWriteEntry( p->vGlo2Cs, i, iVarCs );
+ Vec_IntWriteEntry( p->vGlo2Ns, i, iVarNs );
+ }
+ // add mapping of the PIs
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ Vec_IntWriteEntry( p->vCs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Img_t * Llb_CoreStart( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars )
+{
+ Llb_Img_t * p;
+ p = ABC_CALLOC( Llb_Img_t, 1 );
+ p->pInit = pInit;
+ p->pAig = pAig;
+ p->pPars = pPars;
+ p->dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ p->ddG = Cudd_Init( Aig_ManRegNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ p->ddR = Cudd_Init( Aig_ManPiNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT );
+ Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT );
+ Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT );
+ p->vRings = Vec_PtrAlloc( 100 );
+ p->vDriRefs = Llb_DriverCountRefs( pAig );
+ p->vVarsCs = Llb_DriverCollectCs( pAig );
+ p->vVarsNs = Llb_DriverCollectNs( pAig, p->vDriRefs );
+ Llb_CoreSetVarMaps( p );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_CoreStop( Llb_Img_t * p )
+{
+ DdManager * dd;
+ DdNode * bTemp;
+ int i;
+ if ( p->vDdMans )
+ Vec_PtrForEachEntry( DdManager *, p->vDdMans, dd, i )
+ {
+ if ( dd->bFunc )
+ Cudd_RecursiveDeref( dd, dd->bFunc );
+ if ( dd->bFunc2 )
+ Cudd_RecursiveDeref( dd, dd->bFunc2 );
+ Extra_StopManager( dd );
+ }
+ Vec_PtrFreeP( &p->vDdMans );
+ if ( p->ddR->bFunc )
+ Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc );
+ Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i )
+ Cudd_RecursiveDeref( p->ddR, bTemp );
+ Vec_PtrFree( p->vRings );
+ Extra_StopManager( p->dd );
+ Extra_StopManager( p->ddG );
+ Extra_StopManager( p->ddR );
+ Vec_IntFreeP( &p->vDriRefs );
+ Vec_IntFreeP( &p->vVarsCs );
+ Vec_IntFreeP( &p->vVarsNs );
+ Vec_IntFreeP( &p->vCs2Glo );
+ Vec_IntFreeP( &p->vNs2Glo );
+ Vec_IntFreeP( &p->vGlo2Cs );
+ Vec_IntFreeP( &p->vGlo2Ns );
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_CoreExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, int TimeTarget )
+{
+ int RetValue;
+ Llb_Img_t * p;
+// printf( "\n" );
+// pPars->fVerbose = 1;
+ p = Llb_CoreStart( pInit, pAig, pPars );
+ p->vDdMans = Llb_CoreConstructAll( pAig, vResult, p->vVarsNs, TimeTarget );
+ if ( p->vDdMans == NULL )
+ {
+ if ( !pPars->fSilent )
+ printf( "Reached timeout (%d seconds) while deriving the partitions.\n", pPars->TimeLimit );
+ Llb_CoreStop( p );
+ return -1;
+ }
+ RetValue = Llb_CoreReachability( p );
+ Llb_CoreStop( p );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds balanced cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManReachMinCut( Aig_Man_t * pAig, Gia_ParLlb_t * pPars )
+{
+ extern Vec_Ptr_t * Llb_ManComputeCuts( Aig_Man_t * p, int Num, int fVerbose, int fVeryVerbose );
+ Vec_Ptr_t * vResult;
+ Aig_Man_t * p;
+ int RetValue = -1;
+ int clk = clock();
+
+ // compute time to stop
+ pPars->TimeTarget = pPars->TimeLimit ? time(NULL) + pPars->TimeLimit : 0;
+
+ p = Aig_ManDupFlopsOnly( pAig );
+//Aig_ManShow( p, 0, NULL );
+ if ( pPars->fVerbose )
+ Aig_ManPrintStats( pAig );
+ if ( pPars->fVerbose )
+ Aig_ManPrintStats( p );
+ Aig_ManFanoutStart( p );
+
+ vResult = Llb_ManComputeCuts( p, pPars->nPartValue, pPars->fVerbose, pPars->fVeryVerbose );
+
+ if ( pPars->TimeLimit && time(NULL) > pPars->TimeTarget )
+ {
+ if ( !pPars->fSilent )
+ printf( "Reached timeout (%d seconds) after partitioning.\n", pPars->TimeLimit );
+
+ Vec_VecFree( (Vec_Vec_t *)vResult );
+ Aig_ManFanoutStop( p );
+ Aig_ManCleanMarkAB( p );
+ Aig_ManStop( p );
+ return RetValue;
+ }
+
+ if ( !pPars->fSkipReach )
+ RetValue = Llb_CoreExperiment( pAig, p, pPars, vResult, pPars->TimeTarget );
+
+ Vec_VecFree( (Vec_Vec_t *)vResult );
+ Aig_ManFanoutStop( p );
+ Aig_ManCleanMarkAB( p );
+ Aig_ManStop( p );
+
+ if ( RetValue == -1 )
+ Abc_PrintTime( 1, "Total runtime of the min-cut-based reachability engine", clock() - clk );
+ return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/llb/llb2Driver.c b/src/proof/llb/llb2Driver.c
new file mode 100644
index 00000000..041a39d5
--- /dev/null
+++ b/src/proof/llb/llb2Driver.c
@@ -0,0 +1,221 @@
+/**CFile****************************************************************
+
+ FileName [llb2Driver.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Procedures working with flop drivers.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb2Driver.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// driver issue:arises when creating
+// - driver ref-counter array
+// - Ns2Glo maps
+// - final partition
+// - change-phase cube
+
+// LI variable is used when
+// - driver drives more than one LI
+// - driver is a PI
+// - driver is a constant
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Returns the array of times each flop driver is referenced.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_DriverCountRefs( Aig_Man_t * p )
+{
+ Vec_Int_t * vCounts;
+ Aig_Obj_t * pObj;
+ int i;
+ vCounts = Vec_IntStart( Aig_ManObjNumMax(p) );
+ Saig_ManForEachLi( p, pObj, i )
+ Vec_IntAddToEntry( vCounts, Aig_ObjFaninId0(pObj), 1 );
+ return vCounts;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns array of NS variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_DriverCollectNs( Aig_Man_t * pAig, Vec_Int_t * vDriRefs )
+{
+ Vec_Int_t * vVars;
+ Aig_Obj_t * pObj, * pDri;
+ int i;
+ vVars = Vec_IntAlloc( Aig_ManRegNum(pAig) );
+ Saig_ManForEachLi( pAig, pObj, i )
+ {
+ pDri = Aig_ObjFanin0(pObj);
+ if ( Vec_IntEntry( vDriRefs, Aig_ObjId(pDri) ) != 1 || Saig_ObjIsPi(pAig, pDri) || Aig_ObjIsConst1(pDri) )
+ Vec_IntPush( vVars, Aig_ObjId(pObj) );
+ else
+ Vec_IntPush( vVars, Aig_ObjId(pDri) );
+ }
+ return vVars;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns array of CS variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_DriverCollectCs( Aig_Man_t * pAig )
+{
+ Vec_Int_t * vVars;
+ Aig_Obj_t * pObj;
+ int i;
+ vVars = Vec_IntAlloc( Aig_ManRegNum(pAig) );
+ Saig_ManForEachLo( pAig, pObj, i )
+ Vec_IntPush( vVars, Aig_ObjId(pObj) );
+ return vVars;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create cube for phase swapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_DriverPhaseCube( Aig_Man_t * pAig, Vec_Int_t * vDriRefs, DdManager * dd )
+{
+ DdNode * bCube, * bVar, * bTemp;
+ Aig_Obj_t * pObj;
+ int i, TimeStop;
+ TimeStop = dd->TimeStop; dd->TimeStop = 0;
+ bCube = Cudd_ReadOne( dd ); Cudd_Ref( bCube );
+ Saig_ManForEachLi( pAig, pObj, i )
+ {
+ assert( Vec_IntEntry( vDriRefs, Aig_ObjFaninId0(pObj) ) >= 1 );
+ if ( Vec_IntEntry( vDriRefs, Aig_ObjFaninId0(pObj) ) != 1 )
+ continue;
+ if ( !Aig_ObjFaninC0(pObj) )
+ continue;
+ bVar = Cudd_bddIthVar( dd, Aig_ObjFaninId0(pObj) );
+ bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bCube );
+ dd->TimeStop = TimeStop;
+ return bCube;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute the last partition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdManager * Llb_DriverLastPartition( Aig_Man_t * p, Vec_Int_t * vVarsNs, int TimeTarget )
+{
+ int fVerbose = 1;
+ DdManager * dd;
+ DdNode * bVar1, * bVar2, * bProd, * bRes, * bTemp;
+ Aig_Obj_t * pObj;
+ int i;
+ dd = Cudd_Init( Aig_ManObjNumMax(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+ dd->TimeStop = TimeTarget;
+ bRes = Cudd_ReadOne(dd); Cudd_Ref( bRes );
+
+ // mark the duplicated flop inputs
+ Aig_ManForEachObjVec( vVarsNs, p, pObj, i )
+ {
+ if ( !Saig_ObjIsLi(p, pObj) )
+ continue;
+ bVar1 = Cudd_bddIthVar( dd, Aig_ObjId(pObj) );
+ bVar2 = Cudd_bddIthVar( dd, Aig_ObjFaninId0(pObj) );
+ if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) )
+ bVar2 = Cudd_ReadOne(dd);
+ bVar2 = Cudd_NotCond( bVar2, Aig_ObjFaninC0(pObj) );
+ bProd = Cudd_bddXnor( dd, bVar1, bVar2 ); Cudd_Ref( bProd );
+// bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); Cudd_Ref( bRes );
+// bRes = Extra_bddAndTime( dd, bTemp = bRes, bProd, TimeTarget );
+ bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd );
+ if ( bRes == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bProd );
+ return NULL;
+ }
+ Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bProd );
+ }
+
+/*
+ Saig_ManForEachLi( p, pObj, i )
+ printf( "%d ", Aig_ObjId(pObj) );
+ printf( "\n" );
+ Saig_ManForEachLi( p, pObj, i )
+ printf( "%c%d ", Aig_ObjFaninC0(pObj)? '-':'+', Aig_ObjFaninId0(pObj) );
+ printf( "\n" );
+*/
+ Cudd_AutodynDisable( dd );
+// Cudd_RecursiveDeref( dd, bRes );
+// Extra_StopManager( dd );
+ dd->bFunc = bRes;
+ dd->TimeStop = 0;
+ return dd;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/llb/llb2Dump.c b/src/proof/llb/llb2Dump.c
new file mode 100644
index 00000000..74f07922
--- /dev/null
+++ b/src/proof/llb/llb2Dump.c
@@ -0,0 +1,104 @@
+/**CFile****************************************************************
+
+ FileName [llb2Dump.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Dumps the BDD of reached states into a file.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb2Dump.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Returns a dummy name.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Llb_ManGetDummyName( char * pPrefix, int Num, int nDigits )
+{
+ static char Buffer[2000];
+ sprintf( Buffer, "%s%0*d", pPrefix, nDigits, Num );
+ return Buffer;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Writes reached state BDD into a BLIF file.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManDumpReached( DdManager * ddG, DdNode * bReached, char * pModel, char * pFileName )
+{
+ FILE * pFile;
+ Vec_Ptr_t * vNamesIn, * vNamesOut;
+ char * pName;
+ int i, nDigits;
+ // reorder the BDD
+ Cudd_ReduceHeap( ddG, CUDD_REORDER_SYMM_SIFT, 1 );
+
+ // create input names
+ nDigits = Abc_Base10Log( Cudd_ReadSize(ddG) );
+ vNamesIn = Vec_PtrAlloc( Cudd_ReadSize(ddG) );
+ for ( i = 0; i < Cudd_ReadSize(ddG); i++ )
+ {
+ pName = Llb_ManGetDummyName( "ff", i, nDigits );
+ Vec_PtrPush( vNamesIn, Extra_UtilStrsav(pName) );
+ }
+ // create output names
+ vNamesOut = Vec_PtrAlloc( 1 );
+ Vec_PtrPush( vNamesOut, Extra_UtilStrsav("Reached") );
+
+ // write the file
+ pFile = fopen( pFileName, "wb" );
+ Cudd_DumpBlif( ddG, 1, &bReached, (char **)Vec_PtrArray(vNamesIn), (char **)Vec_PtrArray(vNamesOut), pModel, pFile, 0 );
+ fclose( pFile );
+
+ // cleanup
+ Vec_PtrForEachEntry( char *, vNamesIn, pName, i )
+ ABC_FREE( pName );
+ Vec_PtrForEachEntry( char *, vNamesOut, pName, i )
+ ABC_FREE( pName );
+ Vec_PtrFree( vNamesIn );
+ Vec_PtrFree( vNamesOut );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/llb/llb2Flow.c b/src/proof/llb/llb2Flow.c
new file mode 100644
index 00000000..ebb4e038
--- /dev/null
+++ b/src/proof/llb/llb2Flow.c
@@ -0,0 +1,1374 @@
+/**CFile****************************************************************
+
+ FileName [llb2Flow.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Flow computation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb2Flow.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int Llb_ObjSetPath( Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { pObj->pData = (void *)pNext; return 1; }
+static inline Aig_Obj_t * Llb_ObjGetPath( Aig_Obj_t * pObj ) { return (Aig_Obj_t *)pObj->pData; }
+static inline Aig_Obj_t * Llb_ObjGetFanoutPath( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+ Aig_Obj_t * pFanout;
+ int i, iFanout;
+ assert( Llb_ObjGetPath(pObj) );
+ Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i )
+ if ( Llb_ObjGetPath(pFanout) == pObj )
+ return pFanout;
+ return NULL;
+}
+
+extern Vec_Ptr_t * Llb_ManCutSupp( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+
+/**Function*************************************************************
+
+ Synopsis [For each cut, returns PIs that can be quantified.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManCutSupps( Aig_Man_t * p, Vec_Ptr_t * vResult )
+{
+ Vec_Ptr_t * vSupps, * vOne, * vLower, * vUpper;
+ int i;
+ vSupps = Vec_PtrAlloc( 100 );
+ Vec_PtrPush( vSupps, Vec_PtrAlloc(0) );
+ vLower = (Vec_Ptr_t *)Vec_PtrEntry( vResult, 0 );
+ Vec_PtrForEachEntryStart( Vec_Ptr_t *, vResult, vUpper, i, 1 )
+ {
+ vOne = Llb_ManCutSupp( p, vLower, vUpper );
+ Vec_PtrPush( vSupps, vOne );
+ vLower = vUpper;
+ }
+ assert( Vec_PtrSize(vSupps) == Vec_PtrSize(vResult) );
+ return vSupps;
+}
+
+/**Function*************************************************************
+
+ Synopsis [For each cut, returns PIs that can be quantified.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManCutMap( Aig_Man_t * p, Vec_Ptr_t * vResult, Vec_Ptr_t * vSupps )
+{
+ int fShowMatrix = 1;
+ Vec_Ptr_t * vMaps, * vOne;
+ Vec_Int_t * vMap, * vPrev, * vNext;
+ Aig_Obj_t * pObj;
+ int * piFirst, * piLast;
+ int i, k, CounterPlus, CounterMinus, Counter;
+
+ vMaps = Vec_PtrAlloc( 100 );
+ Vec_PtrForEachEntry( Vec_Ptr_t *, vResult, vOne, i )
+ {
+ vMap = Vec_IntStart( Aig_ManObjNumMax(p) );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vOne, pObj, k )
+ {
+ if ( !Saig_ObjIsPi(p, pObj) )
+ Vec_IntWriteEntry( vMap, pObj->Id, 1 );
+// else
+//printf( "*" );
+//printf( "%d ", pObj->Id );
+ }
+ Vec_PtrPush( vMaps, vMap );
+//printf( "\n" );
+ }
+ Vec_PtrPush( vMaps, Vec_IntStart( Aig_ManObjNumMax(p) ) );
+ assert( Vec_PtrSize(vMaps) == Vec_PtrSize(vResult)+1 );
+
+ // collect the first and last PIs
+ piFirst = ABC_ALLOC( int, Saig_ManPiNum(p) );
+ piLast = ABC_ALLOC( int, Saig_ManPiNum(p) );
+ Saig_ManForEachPi( p, pObj, i )
+ piFirst[i] = piLast[i] = -1;
+ Vec_PtrForEachEntry( Vec_Ptr_t *, vSupps, vOne, i )
+ {
+ Vec_PtrForEachEntry( Aig_Obj_t *, vOne, pObj, k )
+ {
+ if ( !Saig_ObjIsPi(p, pObj) )
+ continue;
+ if ( piFirst[Aig_ObjPioNum(pObj)] == -1 )
+ piFirst[Aig_ObjPioNum(pObj)] = i;
+ piLast[Aig_ObjPioNum(pObj)] = i;
+ }
+ }
+ // PIs feeding into the flops should be extended to the last frame
+ Saig_ManForEachLi( p, pObj, i )
+ {
+ if ( !Saig_ObjIsPi(p, Aig_ObjFanin0(pObj)) )
+ continue;
+ piLast[Aig_ObjPioNum(Aig_ObjFanin0(pObj))] = Vec_PtrSize(vMaps)-1;
+ }
+
+ // set the PI map
+ Saig_ManForEachPi( p, pObj, i )
+ {
+ if ( piFirst[i] == -1 )
+ continue;
+ if ( piFirst[i] == piLast[i] )
+ {
+ vMap = (Vec_Int_t *)Vec_PtrEntry( vMaps, piFirst[i] );
+ Vec_IntWriteEntry( vMap, pObj->Id, 2 );
+ continue;
+ }
+
+ // set support for all in between
+ for ( k = piFirst[i]; k <= piLast[i]; k++ )
+ {
+ vMap = (Vec_Int_t *)Vec_PtrEntry( vMaps, k );
+ Vec_IntWriteEntry( vMap, pObj->Id, 1 );
+ }
+ }
+ ABC_FREE( piFirst );
+ ABC_FREE( piLast );
+
+
+ // find all that will appear here
+ Counter = Aig_ManRegNum(p);
+ printf( "%d ", Counter );
+ Vec_PtrForEachEntryStart( Vec_Int_t *, vMaps, vMap, i, 1 )
+ {
+ vPrev = (Vec_Int_t *)Vec_PtrEntry( vMaps, i-1 );
+ vNext = (i == Vec_PtrSize(vMaps)-1)? NULL: (Vec_Int_t *)Vec_PtrEntry( vMaps, i+1 );
+
+ CounterPlus = CounterMinus = 0;
+ Aig_ManForEachObj( p, pObj, k )
+ {
+ if ( Saig_ObjIsPi(p, pObj) )
+ {
+ if ( Vec_IntEntry(vPrev, k) == 0 && Vec_IntEntry(vMap, k) == 1 )
+ CounterPlus++;
+ if ( Vec_IntEntry(vMap, k) == 1 && (vNext == NULL || Vec_IntEntry(vNext, k) == 0) )
+ CounterMinus++;
+ }
+ else
+ {
+ if ( Vec_IntEntry(vPrev, k) == 0 && Vec_IntEntry(vMap, k) == 1 )
+ CounterPlus++;
+ if ( Vec_IntEntry(vPrev, k) == 1 && Vec_IntEntry(vMap, k) == 0 )
+ CounterMinus++;
+ }
+ }
+ Counter = Counter + CounterPlus - CounterMinus;
+ printf( "%d=%d ", i, Counter );
+ }
+ printf( "\n" );
+
+ if ( fShowMatrix )
+ Aig_ManForEachObj( p, pObj, i )
+ {
+ if ( !Aig_ObjIsPi(pObj) && !Aig_ObjIsNode(pObj) )
+ continue;
+ Vec_PtrForEachEntry( Vec_Int_t *, vMaps, vMap, k )
+ if ( Vec_IntEntry(vMap, i) )
+ break;
+ if ( k == Vec_PtrSize(vMaps) )
+ continue;
+ printf( "Obj = %4d : ", i );
+ if ( Saig_ObjIsPi(p,pObj) )
+ printf( "pi " );
+ else if ( Saig_ObjIsLo(p,pObj) )
+ printf( "lo " );
+ else if ( Aig_ObjIsNode(pObj) )
+ printf( "and " );
+
+ Vec_PtrForEachEntry( Vec_Int_t *, vMaps, vMap, k )
+ printf( "%d", Vec_IntEntry(vMap, i) );
+ printf( "\n" );
+ }
+ return vMaps;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of PIs in the cut]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManCutPiNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut )
+{
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i )
+ if ( Saig_ObjIsPi(p,pObj) )
+ Counter++;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of LOs in the cut]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManCutLoNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut )
+{
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i )
+ if ( Saig_ObjIsLo(p,pObj) )
+ Counter++;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of LIs in the cut]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManCutLiNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut )
+{
+ Aig_Obj_t * pFanout;
+ Aig_Obj_t * pObj;
+ int i, k, iFanout, Counter = 0;
+ Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i )
+ {
+ if ( Aig_ObjIsPi(pObj) )
+ continue;
+ Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, k )
+ {
+ if ( Saig_ObjIsLi(p, pFanout) )
+ {
+ Counter++;
+ break;
+ }
+ }
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes volume of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManCutVolume_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ return 0;
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ assert( Aig_ObjIsNode(pObj) );
+ return 1 + Llb_ManCutVolume_rec(p, Aig_ObjFanin0(pObj)) +
+ Llb_ManCutVolume_rec(p, Aig_ObjFanin1(pObj));
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes volume of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManCutVolume( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper )
+{
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ // mark the lower cut with the traversal ID
+ Aig_ManIncrementTravId(p);
+ Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+ Aig_ObjSetTravIdCurrent( p, pObj );
+ // count the upper cut
+ Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i )
+ Counter += Llb_ManCutVolume_rec( p, pObj );
+ return Counter;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Computes volume of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManCutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ return;
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ assert( Aig_ObjIsNode(pObj) );
+ Llb_ManCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes);
+ Llb_ManCutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes);
+ Vec_PtrPush( vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes volume of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper )
+{
+ Vec_Ptr_t * vNodes;
+ Aig_Obj_t * pObj;
+ int i;
+ // mark the lower cut with the traversal ID
+ Aig_ManIncrementTravId(p);
+ Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+ Aig_ObjSetTravIdCurrent( p, pObj );
+ // count the upper cut
+ vNodes = Vec_PtrAlloc( 100 );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i )
+ Llb_ManCutNodes_rec( p, pObj, vNodes );
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes volume of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManCutSupp( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper )
+{
+ Vec_Ptr_t * vNodes, * vSupp;
+ Aig_Obj_t * pObj;
+ int i;
+ vNodes = Llb_ManCutNodes( p, vLower, vUpper );
+ // mark support of the nodes
+ Aig_ManIncrementTravId(p);
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+ {
+ assert( Aig_ObjIsNode(pObj) );
+ Aig_ObjSetTravIdCurrent( p, Aig_ObjFanin0(pObj) );
+ Aig_ObjSetTravIdCurrent( p, Aig_ObjFanin1(pObj) );
+ }
+ Vec_PtrFree( vNodes );
+ // collect the support nodes
+ vSupp = Vec_PtrAlloc( 100 );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ Vec_PtrPush( vSupp, pObj );
+ return vSupp;
+
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes volume of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManCutRange( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper )
+{
+ Vec_Ptr_t * vRange;
+ Aig_Obj_t * pObj;
+ int i;
+ // mark the lower cut with the traversal ID
+ Aig_ManIncrementTravId(p);
+ Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+ Aig_ObjSetTravIdCurrent( p, pObj );
+ // collect the upper ones that are not marked
+ vRange = Vec_PtrAlloc( 100 );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i )
+ if ( !Aig_ObjIsTravIdCurrent(p, pObj) )
+ Vec_PtrPush( vRange, pObj );
+ return vRange;
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints the given cluster.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManCutPrint( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper )
+{
+ Vec_Ptr_t * vSupp, * vRange;
+ int Pis, Ffs, And;
+
+ Pis = Llb_ManCutPiNum(p, vLower);
+ Ffs = Llb_ManCutLoNum(p, vLower);
+ And = Vec_PtrSize(vLower) - Pis - Ffs;
+ printf( "Leaf: %3d=%3d+%3d+%3d ", Vec_PtrSize(vLower), Pis, Ffs, And );
+
+ Pis = Llb_ManCutPiNum(p, vUpper);
+ Ffs = Llb_ManCutLiNum(p, vUpper);
+ And = Vec_PtrSize(vUpper) - Pis - Ffs;
+ printf( "Root: %3d=%3d+%3d+%3d ", Vec_PtrSize(vUpper), Pis, Ffs, And );
+
+ vSupp = Llb_ManCutSupp( p, vLower, vUpper );
+ Pis = Llb_ManCutPiNum(p, vSupp);
+ Ffs = Llb_ManCutLoNum(p, vSupp);
+ And = Vec_PtrSize(vSupp) - Pis - Ffs;
+ printf( "Supp: %3d=%3d+%3d+%3d ", Vec_PtrSize(vSupp), Pis, Ffs, And );
+
+ vRange = Llb_ManCutRange( p, vLower, vUpper );
+ Pis = Llb_ManCutPiNum(p, vRange);
+ Ffs = Llb_ManCutLiNum(p, vRange);
+ And = Vec_PtrSize(vRange) - Pis - Ffs;
+ printf( "Range: %3d=%3d+%3d+%3d ", Vec_PtrSize(vRange), Pis, Ffs, And );
+
+ printf( "S =%3d. V =%3d.\n",
+ Vec_PtrSize(vSupp)+Vec_PtrSize(vRange), Llb_ManCutVolume(p, vLower, vUpper) );
+ Vec_PtrFree( vSupp );
+ Vec_PtrFree( vRange );
+/*
+ {
+ Aig_Obj_t * pObj;
+ int i;
+ printf( "Lower: " );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+ printf( " %d", pObj->Id );
+ printf( " " );
+ printf( "Upper: " );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i )
+ printf( " %d", pObj->Id );
+ printf( "\n" );
+ }
+*/
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints the given cluster.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManResultPrint( Aig_Man_t * p, Vec_Ptr_t * vResult )
+{
+ Vec_Ptr_t * vLower, * vUpper;
+ int i;
+ Vec_PtrForEachEntryReverse( Vec_Ptr_t *, vResult, vLower, i )
+ {
+ if ( i < Vec_PtrSize(vResult) - 1 )
+ Llb_ManCutPrint( p, vLower, vUpper );
+ vUpper = vLower;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Tries to find an augmenting path originating in this node.]
+
+ Description [This procedure works for directed graphs only!]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManFlowBwdPath2_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+ Aig_Obj_t * pFanout;
+ assert( Aig_ObjIsNode(pObj) || Aig_ObjIsPi(pObj) || Aig_ObjIsConst1(pObj) );
+ // skip visited nodes
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ return 0;
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ // process node without flow
+ if ( !Llb_ObjGetPath(pObj) )
+ {
+ // start the path if we reached a terminal node
+ if ( pObj->fMarkA )
+ return Llb_ObjSetPath( pObj, (Aig_Obj_t *)1 );
+ // explore the fanins
+// Abc_ObjForEachFanin( pObj, pFanin, i )
+// if ( Abc_NtkMaxFlowBwdPath2_rec(pFanin) )
+// return Abc_ObjSetPath( pObj, pFanin );
+ if ( Aig_ObjIsNode(pObj) )
+ {
+ if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ) )
+ return Llb_ObjSetPath( pObj, Aig_ObjFanin0(pObj) );
+ if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ) )
+ return Llb_ObjSetPath( pObj, Aig_ObjFanin1(pObj) );
+ }
+ return 0;
+ }
+ // pObj has flow - find the fanout with flow
+ pFanout = Llb_ObjGetFanoutPath( p, pObj );
+ if ( pFanout == NULL )
+ return 0;
+ // go through the fanins of the fanout with flow
+// Abc_ObjForEachFanin( pFanout, pFanin, i )
+// if ( Abc_NtkMaxFlowBwdPath2_rec( pFanin ) )
+// return Abc_ObjSetPath( pFanout, pFanin );
+ assert( Aig_ObjIsNode(pFanout) );
+ if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pFanout) ) )
+ return Llb_ObjSetPath( pFanout, Aig_ObjFanin0(pFanout) );
+ if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pFanout) ) )
+ return Llb_ObjSetPath( pFanout, Aig_ObjFanin1(pFanout) );
+ // try the fanout
+ if ( Llb_ManFlowBwdPath2_rec( p, pFanout ) )
+ return Llb_ObjSetPath( pFanout, NULL );
+ return 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Cleans markB.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManFlowLabelTfi_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ return;
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ if ( Aig_ObjIsPi(pObj) || Aig_ObjIsConst1(pObj) )
+ return;
+ assert( Aig_ObjIsNode(pObj) );
+ Llb_ManFlowLabelTfi_rec( p, Aig_ObjFanin0(pObj) );
+ Llb_ManFlowLabelTfi_rec( p, Aig_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManFlowUpdateCut( Aig_Man_t * p, Vec_Ptr_t * vMinCut )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ // label the TFI of the cut nodes
+ Aig_ManIncrementTravId(p);
+ Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i )
+ Llb_ManFlowLabelTfi_rec( p, pObj );
+ // collect labeled fanins of non-labeled nodes
+ Vec_PtrClear( vMinCut );
+ Aig_ManIncrementTravId(p);
+ Aig_ManForEachObj( p, pObj, i )
+ {
+ if ( !Aig_ObjIsPo(pObj) && !Aig_ObjIsNode(pObj) )
+ continue;
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) || Aig_ObjIsTravIdPrevious(p, pObj) )
+ continue;
+ if ( Aig_ObjIsTravIdPrevious(p, Aig_ObjFanin0(pObj)) )
+ {
+ Aig_ObjSetTravIdCurrent(p, Aig_ObjFanin0(pObj));
+ Vec_PtrPush( vMinCut, Aig_ObjFanin0(pObj) );
+ }
+ if ( Aig_ObjIsNode(pObj) && Aig_ObjIsTravIdPrevious(p, Aig_ObjFanin1(pObj)) )
+ {
+ Aig_ObjSetTravIdCurrent(p, Aig_ObjFanin1(pObj));
+ Vec_PtrPush( vMinCut, Aig_ObjFanin1(pObj) );
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find minimum-volume minumum cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManFlowMinCut( Aig_Man_t * p )
+{
+ Vec_Ptr_t * vMinCut;
+ Aig_Obj_t * pObj;
+ int i;
+ // collect the cut nodes
+ vMinCut = Vec_PtrAlloc( Aig_ManRegNum(p) );
+ Aig_ManForEachObj( p, pObj, i )
+ {
+ // node without flow is not a cut node
+ if ( !Llb_ObjGetPath(pObj) )
+ continue;
+ // unvisited node is below the cut
+ if ( !Aig_ObjIsTravIdCurrent(p, pObj) )
+ continue;
+ // add terminal with flow or node whose path is not visited
+ if ( pObj->fMarkA || !Aig_ObjIsTravIdCurrent( p, Llb_ObjGetPath(pObj) ) )
+ Vec_PtrPush( vMinCut, pObj );
+ }
+ return vMinCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verifies the min-cut is indeed a cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManFlowVerifyCut_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+ // skip visited nodes
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ return 1;
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ // visit the node
+ if ( Aig_ObjIsConst1(pObj) )
+ return 1;
+ if ( Aig_ObjIsPi(pObj) )
+ return 0;
+ // explore the fanins
+ assert( Aig_ObjIsNode(pObj) );
+ if ( !Llb_ManFlowVerifyCut_rec(p, Aig_ObjFanin0(pObj)) )
+ return 0;
+ if ( !Llb_ManFlowVerifyCut_rec(p, Aig_ObjFanin1(pObj)) )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Verifies the min-cut is indeed a cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_ManFlowVerifyCut( Aig_Man_t * p, Vec_Ptr_t * vMinCut )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ // mark the cut with the current traversal ID
+ Aig_ManIncrementTravId(p);
+ Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i )
+ Aig_ObjSetTravIdCurrent( p, pObj );
+ // search from the latches for a path to the COs/CIs
+ Saig_ManForEachLi( p, pObj, i )
+ {
+ if ( !Llb_ManFlowVerifyCut_rec( p, Aig_ObjFanin0(pObj) ) )
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implementation of max-flow/min-cut computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManFlow( Aig_Man_t * p, Vec_Ptr_t * vSources, int * pnFlow )
+{
+ Vec_Ptr_t * vMinCut;
+ Aig_Obj_t * pObj;
+ int Flow, FlowCur, RetValue, i;
+ // find the max-flow
+ Flow = 0;
+ Aig_ManCleanData( p );
+ Aig_ManIncrementTravId(p);
+ Vec_PtrForEachEntry( Aig_Obj_t *, vSources, pObj, i )
+ {
+ assert( !pObj->fMarkA && pObj->fMarkB );
+ if ( !Aig_ObjFanin0(pObj)->fMarkB )
+ {
+ FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) );
+ Flow += FlowCur;
+ if ( FlowCur )
+ Aig_ManIncrementTravId(p);
+ }
+ if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB )
+ {
+ FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) );
+ Flow += FlowCur;
+ if ( FlowCur )
+ Aig_ManIncrementTravId(p);
+ }
+ }
+ if ( pnFlow )
+ *pnFlow = Flow;
+
+ // mark the nodes reachable from the latches
+ Aig_ManIncrementTravId(p);
+ Vec_PtrForEachEntry( Aig_Obj_t *, vSources, pObj, i )
+ {
+ assert( !pObj->fMarkA && pObj->fMarkB );
+ if ( !Aig_ObjFanin0(pObj)->fMarkB )
+ {
+ RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) );
+ assert( RetValue == 0 );
+ }
+ if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB )
+ {
+ RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) );
+ assert( RetValue == 0 );
+ }
+ }
+
+ // find the min-cut with the smallest volume
+ vMinCut = Llb_ManFlowMinCut( p );
+ assert( Vec_PtrSize(vMinCut) == Flow );
+ // verify the cut
+ if ( !Llb_ManFlowVerifyCut(p, vMinCut) )
+ printf( "Llb_ManFlow() error! The computed min-cut is not a cut!\n" );
+// Llb_ManFlowPrintCut( p, vMinCut );
+ return vMinCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Implementation of max-flow/min-cut computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManFlowCompute( Aig_Man_t * p )
+{
+ Vec_Ptr_t * vMinCut;
+ Aig_Obj_t * pObj;
+ int Flow, FlowCur, RetValue, i;
+ // find the max-flow
+ Flow = 0;
+ Aig_ManCleanData( p );
+ Aig_ManIncrementTravId(p);
+ Aig_ManForEachObj( p, pObj, i )
+ {
+ if ( !pObj->fMarkB )
+ continue;
+ assert( !pObj->fMarkA );
+ if ( !Aig_ObjFanin0(pObj)->fMarkB )
+ {
+//printf( "%d ", Aig_ObjFanin0(pObj)->Id );
+ FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) );
+ Flow += FlowCur;
+ if ( FlowCur )
+ Aig_ManIncrementTravId(p);
+ }
+ if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB )
+ {
+//printf( "%d ", Aig_ObjFanin1(pObj)->Id );
+ FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) );
+ Flow += FlowCur;
+ if ( FlowCur )
+ Aig_ManIncrementTravId(p);
+ }
+ }
+//printf( "\n" );
+
+ // mark the nodes reachable from the latches
+ Aig_ManIncrementTravId(p);
+ Aig_ManForEachObj( p, pObj, i )
+ {
+ if ( !pObj->fMarkB )
+ continue;
+ assert( !pObj->fMarkA );
+ if ( !Aig_ObjFanin0(pObj)->fMarkB )
+ {
+ RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) );
+ assert( RetValue == 0 );
+ }
+ if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB )
+ {
+ RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) );
+ assert( RetValue == 0 );
+ }
+ }
+ // find the min-cut with the smallest volume
+ vMinCut = Llb_ManFlowMinCut( p );
+ assert( Vec_PtrSize(vMinCut) == Flow );
+//printf( "%d ", Vec_PtrSize(vMinCut) );
+ Llb_ManFlowUpdateCut( p, vMinCut );
+//printf( "%d ", Vec_PtrSize(vMinCut) );
+ // verify the cut
+ if ( !Llb_ManFlowVerifyCut(p, vMinCut) )
+ printf( "Llb_ManFlow() error! The computed min-cut is not a cut!\n" );
+// Llb_ManFlowPrintCut( p, vMinCut );
+ return vMinCut;
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Cleans markB.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManFlowCleanMarkB_rec( Aig_Obj_t * pObj )
+{
+ if ( pObj->fMarkB == 0 )
+ return;
+ pObj->fMarkB = 0;
+ assert( Aig_ObjIsNode(pObj) );
+ Llb_ManFlowCleanMarkB_rec( Aig_ObjFanin0(pObj) );
+ Llb_ManFlowCleanMarkB_rec( Aig_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Cleans markB.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManFlowSetMarkA_rec( Aig_Obj_t * pObj )
+{
+ if ( pObj->fMarkA )
+ return;
+ pObj->fMarkA = 1;
+ if ( Aig_ObjIsPi(pObj) || Aig_ObjIsConst1(pObj) )
+ return;
+ assert( Aig_ObjIsNode(pObj) );
+ Llb_ManFlowSetMarkA_rec( Aig_ObjFanin0(pObj) );
+ Llb_ManFlowSetMarkA_rec( Aig_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares flow computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManFlowPrepareCut( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ // reset marks
+ Aig_ManForEachObj( p, pObj, i )
+ {
+ pObj->fMarkA = 0;
+ pObj->fMarkB = 1;
+ }
+ // clean PIs and const
+ Aig_ManConst1(p)->fMarkB = 0;
+ Aig_ManForEachPi( p, pObj, i )
+ pObj->fMarkB = 0;
+ // clean upper cut
+//printf( "Upper: ");
+ Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i )
+ {
+ Llb_ManFlowCleanMarkB_rec( pObj );
+//printf( "%d ", pObj->Id );
+ }
+//printf( "\n" );
+ // set lower cut
+//printf( "Lower: ");
+ Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+ {
+//printf( "%d ", pObj->Id );
+ assert( pObj->fMarkB == 0 );
+ Llb_ManFlowSetMarkA_rec( pObj );
+ }
+//printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares flow computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManFlowUnmarkCone( Aig_Man_t * p, Vec_Ptr_t * vCone )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Vec_PtrForEachEntry( Aig_Obj_t *, vCone, pObj, i )
+ {
+ assert( Aig_ObjIsNode(pObj) );
+ assert( pObj->fMarkB == 1 );
+ pObj->fMarkB = 0;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManFlowCollectAndMarkCone_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vCone )
+{
+ Aig_Obj_t * pFanout;
+ int i, iFanout;
+ if ( Saig_ObjIsLi(p, pObj) )
+ return;
+ if ( pObj->fMarkB )
+ return;
+ if ( pObj->fMarkA == 0 )
+ {
+ assert( Aig_ObjIsNode(pObj) );
+ pObj->fMarkB = 1;
+ if ( Aig_ObjIsNode(pObj) )
+ Vec_PtrPush( vCone, pObj );
+ }
+ Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i )
+ Llb_ManFlowCollectAndMarkCone_rec( p, pFanout, vCone );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the cone.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManFlowCollectAndMarkCone( Aig_Man_t * p, Vec_Ptr_t * vStarts, Vec_Ptr_t * vCone )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Vec_PtrClear( vCone );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vStarts, pObj, i )
+ {
+ assert( pObj->fMarkA && !pObj->fMarkB );
+ Llb_ManFlowCollectAndMarkCone_rec( p, pObj, vCone );
+ }
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds balanced cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManComputeCutLo( Aig_Man_t * p )
+{
+ Vec_Ptr_t * vMinCut;
+ Aig_Obj_t * pObj;
+ int i;
+ vMinCut = Vec_PtrAlloc( 100 );
+ Aig_ManForEachPi( p, pObj, i )
+ Vec_PtrPush( vMinCut, pObj );
+ return vMinCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds balanced cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManComputeCutLi( Aig_Man_t * p )
+{
+ Vec_Ptr_t * vMinCut;
+ Aig_Obj_t * pObj;
+ int i;
+ assert( Saig_ManPoNum(p) == 0 );
+ vMinCut = Vec_PtrAlloc( 100 );
+ Aig_ManIncrementTravId(p);
+ Saig_ManForEachLi( p, pObj, i )
+ {
+ pObj = Aig_ObjFanin0(pObj);
+ if ( Aig_ObjIsConst1(pObj) )
+ continue;
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ continue;
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ Vec_PtrPush( vMinCut, pObj );
+ }
+ return vMinCut;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds balanced cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManFlowGetObjSet( Aig_Man_t * p, Vec_Ptr_t * vLower, int iStart, int nSize, Vec_Ptr_t * vSet )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Vec_PtrClear( vSet );
+ for ( i = 0; i < nSize; i++ )
+ {
+ pObj = (Aig_Obj_t *)Vec_PtrEntry( vLower, (iStart + i) % Vec_PtrSize(vLower) );
+ Vec_PtrPush( vSet, pObj );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds balanced cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManFlowFindBestCut( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, int Num )
+{
+ int nVolMin = Aig_ManNodeNum(p) / Num / 2;
+ Vec_Ptr_t * vMinCut;
+ Vec_Ptr_t * vCone, * vSet;
+ Aig_Obj_t * pObj;
+ int i, s, Vol, VolLower, VolUpper, VolCmp;
+ int iBest = -1, iMinCut = ABC_INFINITY, iVolBest = 0;
+
+ Vol = Llb_ManCutVolume( p, vLower, vUpper );
+ assert( Vol > nVolMin );
+ VolCmp = Abc_MinInt( nVolMin, Vol - nVolMin );
+ vCone = Vec_PtrAlloc( 100 );
+ vSet = Vec_PtrAlloc( 100 );
+ Llb_ManFlowPrepareCut( p, vLower, vUpper );
+ for ( s = 1; s < Aig_ManRegNum(p); s += 5 )
+ {
+ Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+ {
+ Llb_ManFlowGetObjSet( p, vLower, i, s, vSet );
+ Llb_ManFlowCollectAndMarkCone( p, vSet, vCone );
+ if ( Vec_PtrSize(vCone) == 0 )
+ continue;
+ vMinCut = Llb_ManFlowCompute( p );
+ Llb_ManFlowUnmarkCone( p, vCone );
+
+ VolLower = Llb_ManCutVolume( p, vLower, vMinCut );
+ VolUpper = Llb_ManCutVolume( p, vMinCut, vUpper );
+ Vol = Abc_MinInt( VolLower, VolUpper );
+ if ( Vol >= VolCmp && (iMinCut == -1 ||
+ iMinCut > Vec_PtrSize(vMinCut) ||
+ (iMinCut == Vec_PtrSize(vMinCut) && iVolBest < Vol)) )
+ {
+ iBest = i;
+ iMinCut = Vec_PtrSize(vMinCut);
+ iVolBest = Vol;
+ }
+ Vec_PtrFree( vMinCut );
+ }
+ if ( iBest >= 0 )
+ break;
+ }
+ if ( iBest == -1 )
+ {
+ // cleanup
+ Vec_PtrFree( vCone );
+ Vec_PtrFree( vSet );
+ return NULL;
+ }
+ // get the best cut
+ assert( iBest >= 0 );
+ Llb_ManFlowGetObjSet( p, vLower, iBest, s, vSet );
+ Llb_ManFlowCollectAndMarkCone( p, vSet, vCone );
+ vMinCut = Llb_ManFlowCompute( p );
+ Llb_ManFlowUnmarkCone( p, vCone );
+ // cleanup
+ Vec_PtrFree( vCone );
+ Vec_PtrFree( vSet );
+ return vMinCut;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds balanced cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ManComputeCuts( Aig_Man_t * p, int Num, int fVerbose, int fVeryVerbose )
+{
+ int nVolMax = Aig_ManNodeNum(p) / Num;
+ Vec_Ptr_t * vResult, * vMinCut, * vLower, * vUpper;
+ int i, k, nVol, clk = clock();
+ vResult = Vec_PtrAlloc( 100 );
+ Vec_PtrPush( vResult, Llb_ManComputeCutLo(p) );
+ Vec_PtrPush( vResult, Llb_ManComputeCutLi(p) );
+ while ( 1 )
+ {
+ // find a place to insert new cut
+ vLower = (Vec_Ptr_t *)Vec_PtrEntry( vResult, 0 );
+ Vec_PtrForEachEntryStart( Vec_Ptr_t *, vResult, vUpper, i, 1 )
+ {
+ nVol = Llb_ManCutVolume( p, vLower, vUpper );
+ if ( nVol <= nVolMax )
+ {
+ vLower = vUpper;
+ continue;
+ }
+
+ if ( fVeryVerbose )
+ Llb_ManCutPrint( p, vLower, vUpper );
+ vMinCut = Llb_ManFlowFindBestCut( p, vLower, vUpper, Num );
+ if ( vMinCut == NULL )
+ {
+ if ( fVeryVerbose )
+ printf( "Could not break the cut.\n" );
+ if ( fVeryVerbose )
+ printf( "\n" );
+ vLower = vUpper;
+ continue;
+ }
+
+ if ( fVeryVerbose )
+ Llb_ManCutPrint( p, vMinCut, vUpper );
+ if ( fVeryVerbose )
+ Llb_ManCutPrint( p, vLower, vMinCut );
+ if ( fVeryVerbose )
+ printf( "\n" );
+
+ break;
+ }
+ if ( i == Vec_PtrSize(vResult) )
+ break;
+ // insert vMinCut before vUpper
+ Vec_PtrPush( vResult, NULL );
+ for ( k = Vec_PtrSize(vResult) - 1; k > i; k-- )
+ Vec_PtrWriteEntry( vResult, k, Vec_PtrEntry(vResult, k-1) );
+ Vec_PtrWriteEntry( vResult, i, vMinCut );
+ }
+ if ( fVerbose )
+ {
+ printf( "Finished computing %d partitions. ", Vec_PtrSize(vResult) - 1 );
+ Abc_PrintTime( 1, "Time", clock() - clk );
+ Llb_ManResultPrint( p, vResult );
+ }
+ return vResult;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_BddSetDefaultParams( Gia_ParLlb_t * p )
+{
+ memset( p, 0, sizeof(Gia_ParLlb_t) );
+ p->nBddMax = 1000000;
+ p->nIterMax = 10000000;
+ p->nClusterMax = 20;
+ p->nHintDepth = 0;
+ p->HintFirst = 0;
+ p->fUseFlow = 0; // use flow
+ p->nVolumeMax = 100; // max volume
+ p->nVolumeMin = 30; // min volume
+ p->fReorder = 1;
+ p->fIndConstr = 0;
+ p->fUsePivots = 0;
+ p->fCluster = 0;
+ p->fSchedule = 0;
+ p->fVerbose = 0;
+ p->fVeryVerbose = 0;
+ p->fSilent = 0;
+ p->TimeLimit = 0;
+// p->TimeLimit = 0;
+ p->TimeLimitGlo = 0;
+ p->TimeTarget = 0;
+ p->iFrame = -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds balanced cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ManMinCutTest( Aig_Man_t * pAig, int Num )
+{
+ extern void Llb_BddConstructTest( Aig_Man_t * p, Vec_Ptr_t * vResult );
+ extern void Llb_BddExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, Vec_Ptr_t * vMaps );
+
+
+ int fVerbose = 1;
+ Gia_ParLlb_t Pars, * pPars = &Pars;
+ Vec_Ptr_t * vResult;//, * vSupps, * vMaps;
+ Aig_Man_t * p;
+
+ Llb_BddSetDefaultParams( pPars );
+
+ p = Aig_ManDupFlopsOnly( pAig );
+//Aig_ManShow( p, 0, NULL );
+ Aig_ManPrintStats( pAig );
+ Aig_ManPrintStats( p );
+ Aig_ManFanoutStart( p );
+
+ vResult = Llb_ManComputeCuts( p, Num, 1, 0 );
+// vSupps = Llb_ManCutSupps( p, vResult );
+// vMaps = Llb_ManCutMap( p, vResult, vSupps );
+
+// Llb_BddExperiment( pAig, p, pPars, vResult, vMaps );
+ Llb_CoreExperiment( pAig, p, pPars, vResult, 0 );
+
+// Vec_VecFree( (Vec_Vec_t *)vMaps );
+// Vec_VecFree( (Vec_Vec_t *)vSupps );
+ Vec_VecFree( (Vec_Vec_t *)vResult );
+
+ Aig_ManFanoutStop( p );
+ Aig_ManCleanMarkAB( p );
+ Aig_ManStop( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/llb/llb2Image.c b/src/proof/llb/llb2Image.c
new file mode 100644
index 00000000..5baa5c57
--- /dev/null
+++ b/src/proof/llb/llb2Image.c
@@ -0,0 +1,478 @@
+/**CFile****************************************************************
+
+ FileName [llb2Image.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Computes image using partitioned structure.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb2Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+extern Vec_Ptr_t * Llb_ManCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper );
+extern Vec_Ptr_t * Llb_ManCutRange( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper );
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes supports of the partitions.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_ImgSupports( Aig_Man_t * p, Vec_Ptr_t * vDdMans, Vec_Int_t * vStart, Vec_Int_t * vStop, int fAddPis, int fVerbose )
+{
+ Vec_Ptr_t * vSupps;
+ Vec_Int_t * vOne;
+ Aig_Obj_t * pObj;
+ DdManager * dd;
+ DdNode * bSupp, * bTemp;
+ int i, Entry, nSize;
+ nSize = Cudd_ReadSize( (DdManager *)Vec_PtrEntry( vDdMans, 0 ) );
+ vSupps = Vec_PtrAlloc( 100 );
+ // create initial
+ vOne = Vec_IntStart( nSize );
+ Vec_IntForEachEntry( vStart, Entry, i )
+ Vec_IntWriteEntry( vOne, Entry, 1 );
+ Vec_PtrPush( vSupps, vOne );
+ // create intermediate
+ Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i )
+ {
+ vOne = Vec_IntStart( nSize );
+ bSupp = Cudd_Support( dd, dd->bFunc ); Cudd_Ref( bSupp );
+ for ( bTemp = bSupp; bTemp != Cudd_ReadOne(dd); bTemp = cuddT(bTemp) )
+ Vec_IntWriteEntry( vOne, bTemp->index, 1 );
+ Cudd_RecursiveDeref( dd, bSupp );
+ Vec_PtrPush( vSupps, vOne );
+ }
+ // create final
+ vOne = Vec_IntStart( nSize );
+ Vec_IntForEachEntry( vStop, Entry, i )
+ Vec_IntWriteEntry( vOne, Entry, 1 );
+ if ( fAddPis )
+ Saig_ManForEachPi( p, pObj, i )
+ Vec_IntWriteEntry( vOne, Aig_ObjId(pObj), 1 );
+ Vec_PtrPush( vSupps, vOne );
+
+ // print supports
+ assert( nSize == Aig_ManObjNumMax(p) );
+ if ( fVerbose )
+ Aig_ManForEachObj( p, pObj, i )
+ {
+ int k, Counter = 0;
+ Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k )
+ Counter += Vec_IntEntry(vOne, i);
+ if ( Counter == 0 )
+ continue;
+ printf( "Obj = %4d : ", i );
+ if ( Saig_ObjIsPi(p,pObj) )
+ printf( "pi " );
+ else if ( Saig_ObjIsLo(p,pObj) )
+ printf( "lo " );
+ else if ( Saig_ObjIsLi(p,pObj) )
+ printf( "li " );
+ else if ( Aig_ObjIsNode(pObj) )
+ printf( "and " );
+ Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k )
+ printf( "%d", Vec_IntEntry(vOne, i) );
+ printf( "\n" );
+ }
+ return vSupps;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes quantification schedule.]
+
+ Description [Input array contains supports: 0=starting, ... intermediate...
+ N-1=final. Output arrays contain immediately quantifiable vars (vQuant0)
+ and vars that should be quantified after conjunction (vQuant1).]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ImgSchedule( Vec_Ptr_t * vSupps, Vec_Ptr_t ** pvQuant0, Vec_Ptr_t ** pvQuant1, int fVerbose )
+{
+ Vec_Int_t * vOne;
+ int nVarsAll, Counter, iSupp, Entry, i, k;
+ // start quantification arrays
+ *pvQuant0 = Vec_PtrAlloc( Vec_PtrSize(vSupps) );
+ *pvQuant1 = Vec_PtrAlloc( Vec_PtrSize(vSupps) );
+ Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k )
+ {
+ Vec_PtrPush( *pvQuant0, Vec_IntAlloc(16) );
+ Vec_PtrPush( *pvQuant1, Vec_IntAlloc(16) );
+ }
+ // count how many times each var appears
+ nVarsAll = Vec_IntSize( (Vec_Int_t *)Vec_PtrEntry(vSupps, 0) );
+ for ( i = 0; i < nVarsAll; i++ )
+ {
+ Counter = 0;
+ Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k )
+ if ( Vec_IntEntry(vOne, i) )
+ {
+ iSupp = k;
+ Counter++;
+ }
+ if ( Counter == 0 )
+ continue;
+ if ( Counter == 1 )
+ Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(*pvQuant0, iSupp), i );
+ else // if ( Counter > 1 )
+ Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(*pvQuant1, iSupp), i );
+ }
+
+ if ( fVerbose )
+ for ( i = 0; i < Vec_PtrSize(vSupps); i++ )
+ {
+ printf( "%2d : Quant0 = ", i );
+ Vec_IntForEachEntry( (Vec_Int_t *)Vec_PtrEntry(*pvQuant0, i), Entry, k )
+ printf( "%d ", Entry );
+ printf( "\n" );
+ }
+
+ if ( fVerbose )
+ for ( i = 0; i < Vec_PtrSize(vSupps); i++ )
+ {
+ printf( "%2d : Quant1 = ", i );
+ Vec_IntForEachEntry( (Vec_Int_t *)Vec_PtrEntry(*pvQuant1, i), Entry, k )
+ printf( "%d ", Entry );
+ printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes one partition in a separate BDD manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdManager * Llb_ImgPartition( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, int TimeTarget )
+{
+ Vec_Ptr_t * vNodes, * vRange;
+ Aig_Obj_t * pObj;
+ DdManager * dd;
+ DdNode * bBdd0, * bBdd1, * bProd, * bRes, * bTemp;
+ int i;
+
+ dd = Cudd_Init( Aig_ManObjNumMax(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+ dd->TimeStop = TimeTarget;
+
+ Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+ pObj->pData = Cudd_bddIthVar( dd, Aig_ObjId(pObj) );
+
+ vNodes = Llb_ManCutNodes( p, vLower, vUpper );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+ {
+ bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+// pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData );
+// pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeTarget );
+ pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 );
+ if ( pObj->pData == NULL )
+ {
+ Cudd_Quit( dd );
+ Vec_PtrFree( vNodes );
+ return NULL;
+ }
+ Cudd_Ref( (DdNode *)pObj->pData );
+ }
+
+ vRange = Llb_ManCutRange( p, vLower, vUpper );
+ bRes = Cudd_ReadOne(dd); Cudd_Ref( bRes );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vRange, pObj, i )
+ {
+ assert( Aig_ObjIsNode(pObj) );
+ bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), (DdNode *)pObj->pData ); Cudd_Ref( bProd );
+// bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); Cudd_Ref( bRes );
+// bRes = Extra_bddAndTime( dd, bTemp = bRes, bProd, TimeTarget );
+ bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd );
+ if ( bRes == NULL )
+ {
+ Cudd_Quit( dd );
+ Vec_PtrFree( vRange );
+ Vec_PtrFree( vNodes );
+ return NULL;
+ }
+ Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bProd );
+ }
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+
+ Vec_PtrFree( vRange );
+ Vec_PtrFree( vNodes );
+ Cudd_AutodynDisable( dd );
+// Cudd_RecursiveDeref( dd, bRes );
+// Extra_StopManager( dd );
+ dd->bFunc = bRes;
+ dd->TimeStop = 0;
+ return dd;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives positive cube composed of nodes IDs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_ImgComputeCube( Aig_Man_t * pAig, Vec_Int_t * vNodeIds, DdManager * dd )
+{
+ DdNode * bProd, * bTemp;
+ Aig_Obj_t * pObj;
+ int i, TimeStop;
+ TimeStop = dd->TimeStop; dd->TimeStop = 0;
+ bProd = Cudd_ReadOne(dd); Cudd_Ref( bProd );
+ Aig_ManForEachObjVec( vNodeIds, pAig, pObj, i )
+ {
+ bProd = Cudd_bddAnd( dd, bTemp = bProd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)) ); Cudd_Ref( bProd );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bProd );
+ dd->TimeStop = TimeStop;
+ return bProd;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ImgQuantifyFirst( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, Vec_Ptr_t * vQuant0, int fVerbose )
+{
+ DdManager * dd;
+ DdNode * bProd, * bRes, * bTemp;
+ int i, clk = clock();
+ Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i )
+ {
+ // remember unquantified ones
+ assert( dd->bFunc2 == NULL );
+ dd->bFunc2 = dd->bFunc; Cudd_Ref( dd->bFunc2 );
+
+ Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+
+ bRes = dd->bFunc;
+ if ( fVerbose )
+ Abc_Print( 1, "Part %2d : Init =%5d. ", i, Cudd_DagSize(bRes) );
+ bProd = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, i+1), dd ); Cudd_Ref( bProd );
+ bRes = Cudd_bddExistAbstract( dd, bTemp = bRes, bProd ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bProd );
+ dd->bFunc = bRes;
+
+ Cudd_AutodynDisable( dd );
+
+ if ( fVerbose )
+ Abc_Print( 1, "Quant =%5d. ", Cudd_DagSize(bRes) );
+ Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+ if ( fVerbose )
+ Abc_Print( 1, "Reo = %5d. ", Cudd_DagSize(bRes) );
+ Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+ if ( fVerbose )
+ Abc_Print( 1, "Reo = %5d. ", Cudd_DagSize(bRes) );
+ if ( fVerbose )
+ Abc_Print( 1, "Supp = %3d. ", Cudd_SupportSize(dd, bRes) );
+ if ( fVerbose )
+ Abc_PrintTime( 1, "Time", clock() - clk );
+
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_ImgQuantifyReset( Vec_Ptr_t * vDdMans )
+{
+ DdManager * dd;
+ int i;
+ Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i )
+ {
+ assert( dd->bFunc2 != NULL );
+ Cudd_RecursiveDeref( dd, dd->bFunc );
+ dd->bFunc = dd->bFunc2;
+ dd->bFunc2 = NULL;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes image of the initial set of states.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_ImgComputeImage( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, DdManager * dd, DdNode * bInit,
+ Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1, Vec_Int_t * vDriRefs,
+ int TimeTarget, int fBackward, int fReorder, int fVerbose )
+{
+ int fCheckSupport = 0;
+ DdManager * ddPart;
+ DdNode * bImage, * bGroup, * bCube, * bTemp;
+ int i, clk, clk0 = clock();
+
+ bImage = bInit; Cudd_Ref( bImage );
+ if ( fBackward )
+ {
+ // change polarity
+ bCube = Llb_DriverPhaseCube( pAig, vDriRefs, dd ); Cudd_Ref( bCube );
+ bImage = Extra_bddChangePolarity( dd, bTemp = bImage, bCube ); Cudd_Ref( bImage );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bCube );
+ }
+ else
+ {
+ // quantify unique vriables
+ bCube = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, 0), dd ); Cudd_Ref( bCube );
+ bImage = Cudd_bddExistAbstract( dd, bTemp = bImage, bCube );
+ if ( bImage == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bCube );
+ return NULL;
+ }
+ Cudd_Ref( bImage );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bCube );
+ }
+ // perform image computation
+ Vec_PtrForEachEntry( DdManager *, vDdMans, ddPart, i )
+ {
+ clk = clock();
+if ( fVerbose )
+printf( " %2d : ", i );
+ // transfer the BDD from the group manager to the main manager
+ bGroup = Cudd_bddTransfer( ddPart, dd, ddPart->bFunc );
+ if ( bGroup == NULL )
+ return NULL;
+ Cudd_Ref( bGroup );
+if ( fVerbose )
+printf( "Pt0 =%6d. Pt1 =%6d. ", Cudd_DagSize(ddPart->bFunc), Cudd_DagSize(bGroup) );
+ // perform partial product
+ bCube = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant1, i+1), dd ); Cudd_Ref( bCube );
+// bImage = Cudd_bddAndAbstract( dd, bTemp = bImage, bGroup, bCube );
+// bImage = Extra_bddAndAbstractTime( dd, bTemp = bImage, bGroup, bCube, TimeTarget );
+ bImage = Cudd_bddAndAbstract( dd, bTemp = bImage, bGroup, bCube );
+ if ( bImage == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bCube );
+ Cudd_RecursiveDeref( dd, bGroup );
+ return NULL;
+ }
+ Cudd_Ref( bImage );
+
+if ( fVerbose )
+printf( "Im0 =%6d. Im1 =%6d. ", Cudd_DagSize(bTemp), Cudd_DagSize(bImage) );
+//printf("\n"); Extra_bddPrintSupport(dd, bImage); printf("\n");
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bCube );
+ Cudd_RecursiveDeref( dd, bGroup );
+
+// Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+// Abc_Print( 1, "Reo =%6d. ", Cudd_DagSize(bImage) );
+
+if ( fVerbose )
+printf( "Supp =%3d. ", Cudd_SupportSize(dd, bImage) );
+if ( fVerbose )
+Abc_PrintTime( 1, "T", clock() - clk );
+ }
+
+ if ( !fBackward )
+ {
+ // change polarity
+ bCube = Llb_DriverPhaseCube( pAig, vDriRefs, dd ); Cudd_Ref( bCube );
+ bImage = Extra_bddChangePolarity( dd, bTemp = bImage, bCube ); Cudd_Ref( bImage );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bCube );
+ }
+ else
+ {
+ // quantify unique vriables
+ bCube = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, 0), dd ); Cudd_Ref( bCube );
+ bImage = Cudd_bddExistAbstract( dd, bTemp = bImage, bCube ); Cudd_Ref( bImage );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bCube );
+ }
+
+ if ( fReorder )
+ {
+ if ( fVerbose )
+ Abc_Print( 1, " Reordering... Before =%5d. ", Cudd_DagSize(bImage) );
+ Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+ if ( fVerbose )
+ Abc_Print( 1, "After =%5d. ", Cudd_DagSize(bImage) );
+// Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+// Abc_Print( 1, "After =%5d. ", Cudd_DagSize(bImage) );
+ if ( fVerbose )
+ Abc_PrintTime( 1, "Time", clock() - clk0 );
+// Abc_Print( 1, "\n" );
+ }
+
+ Cudd_Deref( bImage );
+ return bImage;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/llb/llb3Image.c b/src/proof/llb/llb3Image.c
new file mode 100644
index 00000000..f674d4b1
--- /dev/null
+++ b/src/proof/llb/llb3Image.c
@@ -0,0 +1,1093 @@
+/**CFile****************************************************************
+
+ FileName [llb3Image.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Computes image using partitioned structure.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb3Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Llb_Var_t_ Llb_Var_t;
+struct Llb_Var_t_
+{
+ int iVar; // variable number
+ int nScore; // variable score
+ Vec_Int_t * vParts; // partitions
+};
+
+typedef struct Llb_Prt_t_ Llb_Prt_t;
+struct Llb_Prt_t_
+{
+ int iPart; // partition number
+ int nSize; // the number of BDD nodes
+ DdNode * bFunc; // the partition
+ Vec_Int_t * vVars; // support
+};
+
+typedef struct Llb_Mgr_t_ Llb_Mgr_t;
+struct Llb_Mgr_t_
+{
+ Aig_Man_t * pAig; // AIG manager
+ Vec_Ptr_t * vLeaves; // leaves in the AIG manager
+ Vec_Ptr_t * vRoots; // roots in the AIG manager
+ DdManager * dd; // working BDD manager
+ int * pVars2Q; // variables to quantify
+ // internal
+ Llb_Prt_t ** pParts; // partitions
+ Llb_Var_t ** pVars; // variables
+ int iPartFree; // next free partition
+ int nVars; // the number of BDD variables
+ int nSuppMax; // maximum support size
+ // temporary
+ int * pSupp; // temporary support storage
+};
+
+static inline Llb_Var_t * Llb_MgrVar( Llb_Mgr_t * p, int i ) { return p->pVars[i]; }
+static inline Llb_Prt_t * Llb_MgrPart( Llb_Mgr_t * p, int i ) { return p->pParts[i]; }
+
+// iterator over vars
+#define Llb_MgrForEachVar( p, pVar, i ) \
+ for ( i = 0; (i < p->nVars) && (((pVar) = Llb_MgrVar(p, i)), 1); i++ ) if ( pVar == NULL ) {} else
+// iterator over parts
+#define Llb_MgrForEachPart( p, pPart, i ) \
+ for ( i = 0; (i < p->iPartFree) && (((pPart) = Llb_MgrPart(p, i)), 1); i++ ) if ( pPart == NULL ) {} else
+
+// iterator over vars of one partition
+#define Llb_PartForEachVar( p, pPart, pVar, i ) \
+ for ( i = 0; (i < Vec_IntSize(pPart->vVars)) && (((pVar) = Llb_MgrVar(p, Vec_IntEntry(pPart->vVars,i))), 1); i++ )
+// iterator over parts of one variable
+#define Llb_VarForEachPart( p, pVar, pPart, i ) \
+ for ( i = 0; (i < Vec_IntSize(pVar->vParts)) && (((pPart) = Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,i))), 1); i++ )
+
+// statistics
+int timeBuild, timeAndEx, timeOther;
+int nSuppMax;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Removes one variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinRemoveVar( Llb_Mgr_t * p, Llb_Var_t * pVar )
+{
+ assert( p->pVars[pVar->iVar] == pVar );
+ p->pVars[pVar->iVar] = NULL;
+ Vec_IntFree( pVar->vParts );
+ ABC_FREE( pVar );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes one partition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinRemovePart( Llb_Mgr_t * p, Llb_Prt_t * pPart )
+{
+ assert( p->pParts[pPart->iPart] == pPart );
+ p->pParts[pPart->iPart] = NULL;
+ Vec_IntFree( pPart->vVars );
+ Cudd_RecursiveDeref( p->dd, pPart->bFunc );
+ ABC_FREE( pPart );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create cube with singleton variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_NonlinCreateCube1( Llb_Mgr_t * p, Llb_Prt_t * pPart )
+{
+ DdNode * bCube, * bTemp;
+ Llb_Var_t * pVar;
+ int i, TimeStop;
+ TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
+ bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube );
+ Llb_PartForEachVar( p, pPart, pVar, i )
+ {
+ assert( Vec_IntSize(pVar->vParts) > 0 );
+ if ( Vec_IntSize(pVar->vParts) != 1 )
+ continue;
+ assert( Vec_IntEntry(pVar->vParts, 0) == pPart->iPart );
+ bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ Cudd_Deref( bCube );
+ p->dd->TimeStop = TimeStop;
+ return bCube;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create cube of variables appearing only in two partitions.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_NonlinCreateCube2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 )
+{
+ DdNode * bCube, * bTemp;
+ Llb_Var_t * pVar;
+ int i, TimeStop;
+ TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
+ bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube );
+ Llb_PartForEachVar( p, pPart1, pVar, i )
+ {
+ assert( Vec_IntSize(pVar->vParts) > 0 );
+ if ( Vec_IntSize(pVar->vParts) != 2 )
+ continue;
+ if ( (Vec_IntEntry(pVar->vParts, 0) == pPart1->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart2->iPart) ||
+ (Vec_IntEntry(pVar->vParts, 0) == pPart2->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart1->iPart) )
+ {
+ bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ }
+ Cudd_Deref( bCube );
+ p->dd->TimeStop = TimeStop;
+ return bCube;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if partition has singleton variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_NonlinHasSingletonVars( Llb_Mgr_t * p, Llb_Prt_t * pPart )
+{
+ Llb_Var_t * pVar;
+ int i;
+ Llb_PartForEachVar( p, pPart, pVar, i )
+ if ( Vec_IntSize(pVar->vParts) == 1 )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if partition has singleton variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinPrint( Llb_Mgr_t * p )
+{
+ Llb_Prt_t * pPart;
+ Llb_Var_t * pVar;
+ int i, k;
+ printf( "\n" );
+ Llb_MgrForEachVar( p, pVar, i )
+ {
+ printf( "Var %3d : ", i );
+ Llb_VarForEachPart( p, pVar, pPart, k )
+ printf( "%d ", pPart->iPart );
+ printf( "\n" );
+ }
+ Llb_MgrForEachPart( p, pPart, i )
+ {
+ printf( "Part %3d : ", i );
+ Llb_PartForEachVar( p, pPart, pVar, k )
+ printf( "%d ", pVar->iVar );
+ printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Quantifies singles belonging to one partition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_NonlinQuantify1( Llb_Mgr_t * p, Llb_Prt_t * pPart, int fSubset )
+{
+ Llb_Var_t * pVar;
+ Llb_Prt_t * pTemp;
+ Vec_Ptr_t * vSingles;
+ DdNode * bCube, * bTemp;
+ int i, RetValue, nSizeNew;
+ if ( fSubset )
+ {
+ int Length;
+// int nSuppSize = Cudd_SupportSize( p->dd, pPart->bFunc );
+// pPart->bFunc = Cudd_SubsetHeavyBranch( p->dd, bTemp = pPart->bFunc, nSuppSize, 3*pPart->nSize/4 ); Cudd_Ref( pPart->bFunc );
+ pPart->bFunc = Cudd_LargestCube( p->dd, bTemp = pPart->bFunc, &Length ); Cudd_Ref( pPart->bFunc );
+
+ printf( "Subsetting %3d : ", pPart->iPart );
+ printf( "(Supp =%3d Node =%5d) -> ", Cudd_SupportSize(p->dd, bTemp), Cudd_DagSize(bTemp) );
+ printf( "(Supp =%3d Node =%5d)\n", Cudd_SupportSize(p->dd, pPart->bFunc), Cudd_DagSize(pPart->bFunc) );
+
+ RetValue = (Cudd_DagSize(bTemp) == Cudd_DagSize(pPart->bFunc));
+
+ Cudd_RecursiveDeref( p->dd, bTemp );
+
+ if ( RetValue )
+ return 1;
+ }
+ else
+ {
+ // create cube to be quantified
+ bCube = Llb_NonlinCreateCube1( p, pPart ); Cudd_Ref( bCube );
+// assert( !Cudd_IsConstant(bCube) );
+ // derive new function
+ pPart->bFunc = Cudd_bddExistAbstract( p->dd, bTemp = pPart->bFunc, bCube ); Cudd_Ref( pPart->bFunc );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->dd, bCube );
+ }
+ // get support
+ vSingles = Vec_PtrAlloc( 0 );
+ nSizeNew = Cudd_DagSize(pPart->bFunc);
+ Extra_SupportArray( p->dd, pPart->bFunc, p->pSupp );
+ Llb_PartForEachVar( p, pPart, pVar, i )
+ if ( p->pSupp[pVar->iVar] )
+ {
+ assert( Vec_IntSize(pVar->vParts) > 1 );
+ pVar->nScore -= pPart->nSize - nSizeNew;
+ }
+ else
+ {
+ RetValue = Vec_IntRemove( pVar->vParts, pPart->iPart );
+ assert( RetValue );
+ pVar->nScore -= pPart->nSize;
+ if ( Vec_IntSize(pVar->vParts) == 0 )
+ Llb_NonlinRemoveVar( p, pVar );
+ else if ( Vec_IntSize(pVar->vParts) == 1 )
+ Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) );
+ }
+
+ // update partition
+ pPart->nSize = nSizeNew;
+ Vec_IntClear( pPart->vVars );
+ for ( i = 0; i < p->nVars; i++ )
+ if ( p->pSupp[i] && p->pVars2Q[i] )
+ Vec_IntPush( pPart->vVars, i );
+ // remove other variables
+ Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i )
+ Llb_NonlinQuantify1( p, pTemp, 0 );
+ Vec_PtrFree( vSingles );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Quantifies singles belonging to one partition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_NonlinQuantify2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2, int Limit, int TimeOut )
+{
+ int fVerbose = 0;
+ Llb_Var_t * pVar;
+ Llb_Prt_t * pTemp;
+ Vec_Ptr_t * vSingles;
+ DdNode * bCube, * bFunc;
+ int i, RetValue, nSuppSize;
+ int iPart1 = pPart1->iPart;
+ int iPart2 = pPart2->iPart;
+
+ // create cube to be quantified
+ bCube = Llb_NonlinCreateCube2( p, pPart1, pPart2 ); Cudd_Ref( bCube );
+if ( fVerbose )
+{
+printf( "\n" );
+printf( "\n" );
+Llb_NonlinPrint( p );
+printf( "Conjoining partitions %d and %d.\n", pPart1->iPart, pPart2->iPart );
+Extra_bddPrintSupport( p->dd, bCube ); printf( "\n" );
+}
+
+ // derive new function
+// bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube ); Cudd_Ref( bFunc );
+/*
+ bFunc = Cudd_bddAndAbstractLimit( p->dd, pPart1->bFunc, pPart2->bFunc, bCube, Limit );
+ if ( bFunc == NULL )
+ {
+ int RetValue;
+ Cudd_RecursiveDeref( p->dd, bCube );
+ if ( pPart1->nSize < pPart2->nSize )
+ RetValue = Llb_NonlinQuantify1( p, pPart1, 1 );
+ else
+ RetValue = Llb_NonlinQuantify1( p, pPart2, 1 );
+ if ( RetValue )
+ Limit = Limit + 1000;
+ Llb_NonlinQuantify2( p, pPart1, pPart2, Limit, TimeOut );
+ return 0;
+ }
+ Cudd_Ref( bFunc );
+*/
+
+// bFunc = Extra_bddAndAbstractTime( p->dd, pPart1->bFunc, pPart2->bFunc, bCube, TimeOut );
+ bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube );
+ if ( bFunc == NULL )
+ {
+ Cudd_RecursiveDeref( p->dd, bCube );
+ return 0;
+ }
+ Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( p->dd, bCube );
+
+ // create new partition
+ pTemp = p->pParts[p->iPartFree] = ABC_CALLOC( Llb_Prt_t, 1 );
+ pTemp->iPart = p->iPartFree++;
+ pTemp->nSize = Cudd_DagSize(bFunc);
+ pTemp->bFunc = bFunc;
+ pTemp->vVars = Vec_IntAlloc( 8 );
+ // update variables
+ Llb_PartForEachVar( p, pPart1, pVar, i )
+ {
+ RetValue = Vec_IntRemove( pVar->vParts, pPart1->iPart );
+ assert( RetValue );
+ pVar->nScore -= pPart1->nSize;
+ }
+ // update variables
+ Llb_PartForEachVar( p, pPart2, pVar, i )
+ {
+ RetValue = Vec_IntRemove( pVar->vParts, pPart2->iPart );
+ assert( RetValue );
+ pVar->nScore -= pPart2->nSize;
+ }
+ // add variables to the new partition
+ nSuppSize = 0;
+ Extra_SupportArray( p->dd, bFunc, p->pSupp );
+ for ( i = 0; i < p->nVars; i++ )
+ {
+ nSuppSize += p->pSupp[i];
+ if ( p->pSupp[i] && p->pVars2Q[i] )
+ {
+ pVar = Llb_MgrVar( p, i );
+ pVar->nScore += pTemp->nSize;
+ Vec_IntPush( pVar->vParts, pTemp->iPart );
+ Vec_IntPush( pTemp->vVars, i );
+ }
+ }
+ p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize );
+ // remove variables and collect partitions with singleton variables
+ vSingles = Vec_PtrAlloc( 0 );
+ Llb_PartForEachVar( p, pPart1, pVar, i )
+ {
+ if ( Vec_IntSize(pVar->vParts) == 0 )
+ Llb_NonlinRemoveVar( p, pVar );
+ else if ( Vec_IntSize(pVar->vParts) == 1 )
+ {
+ if ( fVerbose )
+ printf( "Adding partition %d because of var %d.\n",
+ Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar );
+ Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) );
+ }
+ }
+ Llb_PartForEachVar( p, pPart2, pVar, i )
+ {
+ if ( pVar == NULL )
+ continue;
+ if ( Vec_IntSize(pVar->vParts) == 0 )
+ Llb_NonlinRemoveVar( p, pVar );
+ else if ( Vec_IntSize(pVar->vParts) == 1 )
+ {
+ if ( fVerbose )
+ printf( "Adding partition %d because of var %d.\n",
+ Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar );
+ Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) );
+ }
+ }
+ // remove partitions
+ Llb_NonlinRemovePart( p, pPart1 );
+ Llb_NonlinRemovePart( p, pPart2 );
+ // remove other variables
+if ( fVerbose )
+Llb_NonlinPrint( p );
+ Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i )
+ {
+if ( fVerbose )
+printf( "Updating partitiong %d with singlton vars.\n", pTemp->iPart );
+ Llb_NonlinQuantify1( p, pTemp, 0 );
+ }
+if ( fVerbose )
+Llb_NonlinPrint( p );
+ Vec_PtrFree( vSingles );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes volume of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinCutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ return;
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ if ( Saig_ObjIsLi(p, pObj) )
+ {
+ Llb_NonlinCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes);
+ return;
+ }
+ if ( Aig_ObjIsConst1(pObj) )
+ return;
+ assert( Aig_ObjIsNode(pObj) );
+ Llb_NonlinCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes);
+ Llb_NonlinCutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes);
+ Vec_PtrPush( vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes volume of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_NonlinCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper )
+{
+ Vec_Ptr_t * vNodes;
+ Aig_Obj_t * pObj;
+ int i;
+ // mark the lower cut with the traversal ID
+ Aig_ManIncrementTravId(p);
+ Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+ Aig_ObjSetTravIdCurrent( p, pObj );
+ // count the upper cut
+ vNodes = Vec_PtrAlloc( 100 );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i )
+ Llb_NonlinCutNodes_rec( p, pObj, vNodes );
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns array of BDDs for the roots in terms of the leaves.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_NonlinBuildBdds( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, DdManager * dd, int TimeOut )
+{
+ Vec_Ptr_t * vNodes, * vResult;
+ Aig_Obj_t * pObj;
+ DdNode * bBdd0, * bBdd1, * bProd;
+ int i, k;
+
+ Aig_ManConst1(p)->pData = Cudd_ReadOne( dd );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+ pObj->pData = Cudd_bddIthVar( dd, Aig_ObjId(pObj) );
+
+ vNodes = Llb_NonlinCutNodes( p, vLower, vUpper );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+ {
+ bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+// pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeOut );
+ pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 );
+ if ( pObj->pData == NULL )
+ {
+ Vec_PtrForEachEntryStop( Aig_Obj_t *, vNodes, pObj, k, i )
+ if ( pObj->pData )
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+ Vec_PtrFree( vNodes );
+ return NULL;
+ }
+ Cudd_Ref( (DdNode *)pObj->pData );
+ }
+
+ vResult = Vec_PtrAlloc( 100 );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i )
+ {
+ if ( Aig_ObjIsNode(pObj) )
+ {
+ bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), (DdNode *)pObj->pData ); Cudd_Ref( bProd );
+ }
+ else
+ {
+ assert( Saig_ObjIsLi(p, pObj) );
+ bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), bBdd0 ); Cudd_Ref( bProd );
+ }
+ Vec_PtrPush( vResult, bProd );
+ }
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+
+ Vec_PtrFree( vNodes );
+ return vResult;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts non-linear quantification scheduling.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinAddPair( Llb_Mgr_t * p, DdNode * bFunc, int iPart, int iVar )
+{
+ if ( p->pVars[iVar] == NULL )
+ {
+ p->pVars[iVar] = ABC_CALLOC( Llb_Var_t, 1 );
+ p->pVars[iVar]->iVar = iVar;
+ p->pVars[iVar]->nScore = 0;
+ p->pVars[iVar]->vParts = Vec_IntAlloc( 8 );
+ }
+ Vec_IntPush( p->pVars[iVar]->vParts, iPart );
+ Vec_IntPush( p->pParts[iPart]->vVars, iVar );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts non-linear quantification scheduling.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinAddPartition( Llb_Mgr_t * p, int i, DdNode * bFunc )
+{
+ int k, nSuppSize;
+ assert( !Cudd_IsConstant(bFunc) );
+ // create partition
+ p->pParts[i] = ABC_CALLOC( Llb_Prt_t, 1 );
+ p->pParts[i]->iPart = i;
+ p->pParts[i]->bFunc = bFunc;
+ p->pParts[i]->vVars = Vec_IntAlloc( 8 );
+ // add support dependencies
+ nSuppSize = 0;
+ Extra_SupportArray( p->dd, bFunc, p->pSupp );
+ for ( k = 0; k < p->nVars; k++ )
+ {
+ nSuppSize += p->pSupp[k];
+ if ( p->pSupp[k] && p->pVars2Q[k] )
+ Llb_NonlinAddPair( p, bFunc, i, k );
+ }
+ p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts non-linear quantification scheduling.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_NonlinStart( Llb_Mgr_t * p, int TimeOut )
+{
+ Vec_Ptr_t * vRootBdds;
+ DdNode * bFunc;
+ int i;
+ // create and collect BDDs
+ vRootBdds = Llb_NonlinBuildBdds( p->pAig, p->vLeaves, p->vRoots, p->dd, TimeOut ); // come referenced
+ if ( vRootBdds == NULL )
+ return 0;
+ // add pairs (refs are consumed inside)
+ Vec_PtrForEachEntry( DdNode *, vRootBdds, bFunc, i )
+ Llb_NonlinAddPartition( p, i, bFunc );
+ Vec_PtrFree( vRootBdds );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks that each var appears in at least one partition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+**********************************************************************/
+void Llb_NonlinCheckVars( Llb_Mgr_t * p )
+{
+ Llb_Var_t * pVar;
+ int i;
+ Llb_MgrForEachVar( p, pVar, i )
+ assert( Vec_IntSize(pVar->vParts) > 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find next partition to quantify]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_NonlinNextPartitions( Llb_Mgr_t * p, Llb_Prt_t ** ppPart1, Llb_Prt_t ** ppPart2 )
+{
+ Llb_Var_t * pVar, * pVarBest = NULL;
+ Llb_Prt_t * pPart, * pPart1Best = NULL, * pPart2Best = NULL;
+ int i;
+ Llb_NonlinCheckVars( p );
+ // find variable with minimum score
+ Llb_MgrForEachVar( p, pVar, i )
+ if ( pVarBest == NULL || pVarBest->nScore > pVar->nScore )
+ pVarBest = pVar;
+ if ( pVarBest == NULL )
+ return 0;
+ // find two partitions with minimum size
+ Llb_VarForEachPart( p, pVarBest, pPart, i )
+ {
+ if ( pPart1Best == NULL )
+ pPart1Best = pPart;
+ else if ( pPart2Best == NULL )
+ pPart2Best = pPart;
+ else if ( pPart1Best->nSize > pPart->nSize || pPart2Best->nSize > pPart->nSize )
+ {
+ if ( pPart1Best->nSize > pPart2Best->nSize )
+ pPart1Best = pPart;
+ else
+ pPart2Best = pPart;
+ }
+ }
+ *ppPart1 = pPart1Best;
+ *ppPart2 = pPart2Best;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reorders BDDs in the working manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinReorder( DdManager * dd, int fTwice, int fVerbose )
+{
+ int clk = clock();
+ if ( fVerbose )
+ Abc_Print( 1, "Reordering... Before =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+ Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+ if ( fVerbose )
+ Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+ if ( fTwice )
+ {
+ Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+ if ( fVerbose )
+ Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+ }
+ if ( fVerbose )
+ Abc_PrintTime( 1, "Time", clock() - clk );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recomputes scores after variable reordering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinRecomputeScores( Llb_Mgr_t * p )
+{
+ Llb_Prt_t * pPart;
+ Llb_Var_t * pVar;
+ int i, k;
+ Llb_MgrForEachPart( p, pPart, i )
+ pPart->nSize = Cudd_DagSize(pPart->bFunc);
+ Llb_MgrForEachVar( p, pVar, i )
+ {
+ pVar->nScore = 0;
+ Llb_VarForEachPart( p, pVar, pPart, k )
+ pVar->nScore += pPart->nSize;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recomputes scores after variable reordering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinVerifyScores( Llb_Mgr_t * p )
+{
+ Llb_Prt_t * pPart;
+ Llb_Var_t * pVar;
+ int i, k, nScore;
+ Llb_MgrForEachPart( p, pPart, i )
+ assert( pPart->nSize == Cudd_DagSize(pPart->bFunc) );
+ Llb_MgrForEachVar( p, pVar, i )
+ {
+ nScore = 0;
+ Llb_VarForEachPart( p, pVar, pPart, k )
+ nScore += pPart->nSize;
+ assert( nScore == pVar->nScore );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts non-linear quantification scheduling.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Mgr_t * Llb_NonlinAlloc( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, DdManager * dd )
+{
+ Llb_Mgr_t * p;
+ p = ABC_CALLOC( Llb_Mgr_t, 1 );
+ p->pAig = pAig;
+ p->vLeaves = vLeaves;
+ p->vRoots = vRoots;
+ p->dd = dd;
+ p->pVars2Q = pVars2Q;
+ p->nVars = Cudd_ReadSize(dd);
+ p->iPartFree = Vec_PtrSize(vRoots);
+ p->pVars = ABC_CALLOC( Llb_Var_t *, p->nVars );
+ p->pParts = ABC_CALLOC( Llb_Prt_t *, 2 * p->iPartFree + 2 );
+ p->pSupp = ABC_ALLOC( int, Cudd_ReadSize(dd) );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops non-linear quantification scheduling.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinFree( Llb_Mgr_t * p )
+{
+ Llb_Prt_t * pPart;
+ Llb_Var_t * pVar;
+ int i;
+ Llb_MgrForEachVar( p, pVar, i )
+ Llb_NonlinRemoveVar( p, pVar );
+ Llb_MgrForEachPart( p, pPart, i )
+ Llb_NonlinRemovePart( p, pPart );
+ ABC_FREE( p->pVars );
+ ABC_FREE( p->pParts );
+ ABC_FREE( p->pSupp );
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs image computation.]
+
+ Description [Computes image of BDDs (vFuncs).]
+
+ SideEffects [BDDs in vFuncs are derefed inside. The result is refed.]
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_NonlinImage( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q,
+ DdManager * dd, DdNode * bCurrent, int fReorder, int fVerbose, int * pOrder, int Limit, int TimeOut )
+{
+ Llb_Prt_t * pPart, * pPart1, * pPart2;
+ Llb_Mgr_t * p;
+ DdNode * bFunc, * bTemp;
+ int i, nReorders, timeInside;
+ int clk = clock(), clk2;
+ // start the manager
+ clk2 = clock();
+ p = Llb_NonlinAlloc( pAig, vLeaves, vRoots, pVars2Q, dd );
+ if ( !Llb_NonlinStart( p, TimeOut ) )
+ {
+ Llb_NonlinFree( p );
+ return NULL;
+ }
+ // add partition
+ Llb_NonlinAddPartition( p, p->iPartFree++, bCurrent );
+ // remove singles
+ Llb_MgrForEachPart( p, pPart, i )
+ if ( Llb_NonlinHasSingletonVars(p, pPart) )
+ Llb_NonlinQuantify1( p, pPart, 0 );
+ timeBuild += clock() - clk2;
+ timeInside = clock() - clk2;
+ // compute scores
+ Llb_NonlinRecomputeScores( p );
+ // save permutation
+ if ( pOrder )
+ memcpy( pOrder, dd->invperm, sizeof(int) * dd->size );
+ // iteratively quantify variables
+ while ( Llb_NonlinNextPartitions(p, &pPart1, &pPart2) )
+ {
+ clk2 = clock();
+ nReorders = Cudd_ReadReorderings(dd);
+ if ( !Llb_NonlinQuantify2( p, pPart1, pPart2, Limit, TimeOut ) )
+ {
+ Llb_NonlinFree( p );
+ return NULL;
+ }
+ timeAndEx += clock() - clk2;
+ timeInside += clock() - clk2;
+ if ( nReorders < Cudd_ReadReorderings(dd) )
+ Llb_NonlinRecomputeScores( p );
+// else
+// Llb_NonlinVerifyScores( p );
+ }
+ // load partitions
+ bFunc = Cudd_ReadOne(p->dd); Cudd_Ref( bFunc );
+ Llb_MgrForEachPart( p, pPart, i )
+ {
+ bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ nSuppMax = p->nSuppMax;
+ Llb_NonlinFree( p );
+ // reorder variables
+ if ( fReorder )
+ Llb_NonlinReorder( dd, 0, fVerbose );
+ timeOther += clock() - clk - timeInside;
+ // return
+ Cudd_Deref( bFunc );
+ return bFunc;
+}
+
+
+
+static Llb_Mgr_t * p = NULL;
+
+/**Function*************************************************************
+
+ Synopsis [Starts image computation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdManager * Llb_NonlinImageStart( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, int * pOrder, int fFirst, int TimeTarget )
+{
+ DdManager * dd;
+ int clk = clock();
+ assert( p == NULL );
+ // start a new manager (disable reordering)
+ dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ dd->TimeStop = TimeTarget;
+ Cudd_ShuffleHeap( dd, pOrder );
+// if ( fFirst )
+ Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+ // start the manager
+ p = Llb_NonlinAlloc( pAig, vLeaves, vRoots, pVars2Q, dd );
+ if ( !Llb_NonlinStart( p, 0 ) )
+ {
+ Llb_NonlinFree( p );
+ p = NULL;
+ return NULL;
+ }
+ timeBuild += clock() - clk;
+// if ( !fFirst )
+// Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+ return dd;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs image computation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_NonlinImageCompute( DdNode * bCurrent, int fReorder, int fDrop, int fVerbose, int * pOrder )
+{
+ Llb_Prt_t * pPart, * pPart1, * pPart2;
+ DdNode * bFunc, * bTemp;
+ int i, nReorders, timeInside = 0;
+ int clk = clock(), clk2;
+
+ // add partition
+ Llb_NonlinAddPartition( p, p->iPartFree++, bCurrent );
+ // remove singles
+ Llb_MgrForEachPart( p, pPart, i )
+ if ( Llb_NonlinHasSingletonVars(p, pPart) )
+ Llb_NonlinQuantify1( p, pPart, 0 );
+ // reorder
+ if ( fReorder )
+ Llb_NonlinReorder( p->dd, 0, 0 );
+ // save permutation
+ memcpy( pOrder, p->dd->invperm, sizeof(int) * p->dd->size );
+
+ // compute scores
+ Llb_NonlinRecomputeScores( p );
+ // iteratively quantify variables
+ while ( Llb_NonlinNextPartitions(p, &pPart1, &pPart2) )
+ {
+ clk2 = clock();
+ nReorders = Cudd_ReadReorderings(p->dd);
+ if ( !Llb_NonlinQuantify2( p, pPart1, pPart2, 0, 0 ) )
+ {
+ Llb_NonlinFree( p );
+ return NULL;
+ }
+ timeAndEx += clock() - clk2;
+ timeInside += clock() - clk2;
+ if ( nReorders < Cudd_ReadReorderings(p->dd) )
+ Llb_NonlinRecomputeScores( p );
+// else
+// Llb_NonlinVerifyScores( p );
+ }
+ // load partitions
+ bFunc = Cudd_ReadOne(p->dd); Cudd_Ref( bFunc );
+ Llb_MgrForEachPart( p, pPart, i )
+ {
+ bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc );
+ if ( bFunc == NULL )
+ {
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Llb_NonlinFree( p );
+ return NULL;
+ }
+ Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ nSuppMax = p->nSuppMax;
+ // reorder variables
+// if ( fReorder )
+// Llb_NonlinReorder( p->dd, 0, fVerbose );
+ // save permutation
+// memcpy( pOrder, p->dd->invperm, sizeof(int) * Cudd_ReadSize(p->dd) );
+
+ timeOther += clock() - clk - timeInside;
+ // return
+ Cudd_Deref( bFunc );
+ return bFunc;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Quits image computation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinImageQuit()
+{
+ DdManager * dd;
+ if ( p == NULL )
+ return;
+ dd = p->dd;
+ Llb_NonlinFree( p );
+ if ( dd->bFunc )
+ Cudd_RecursiveDeref( dd, dd->bFunc );
+ Extra_StopManager( dd );
+// Cudd_Quit ( dd );
+ p = NULL;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/llb/llb3Nonlin.c b/src/proof/llb/llb3Nonlin.c
new file mode 100644
index 00000000..45f6f11e
--- /dev/null
+++ b/src/proof/llb/llb3Nonlin.c
@@ -0,0 +1,871 @@
+/**CFile****************************************************************
+
+ FileName [llb2Nonlin.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Non-linear quantification scheduling.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb2Nonlin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Llb_Mnn_t_ Llb_Mnn_t;
+struct Llb_Mnn_t_
+{
+ Aig_Man_t * pInit; // AIG manager
+ Aig_Man_t * pAig; // AIG manager
+ Gia_ParLlb_t * pPars; // parameters
+
+ DdManager * dd; // BDD manager
+ DdManager * ddG; // BDD manager
+ DdManager * ddR; // BDD manager
+ Vec_Ptr_t * vRings; // onion rings in ddR
+
+ Vec_Ptr_t * vLeaves;
+ Vec_Ptr_t * vRoots;
+ int * pVars2Q;
+ int * pOrderL;
+ int * pOrderL2;
+ int * pOrderG;
+
+ Vec_Int_t * vCs2Glo; // cur state variables into global variables
+ Vec_Int_t * vNs2Glo; // next state variables into global variables
+ Vec_Int_t * vGlo2Cs; // global variables into cur state variables
+ Vec_Int_t * vGlo2Ns; // global variables into next state variables
+
+ int ddLocReos;
+ int ddLocGrbs;
+
+ int timeImage;
+ int timeTran1;
+ int timeTran2;
+ int timeGloba;
+ int timeOther;
+ int timeTotal;
+ int timeReo;
+ int timeReoG;
+
+};
+
+extern int timeBuild, timeAndEx, timeOther;
+extern int nSuppMax;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Finds variable whose 0-cofactor is the smallest.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_NonlinFindBestVar( DdManager * dd, DdNode * bFunc, Aig_Man_t * pAig )
+{
+ int fVerbose = 0;
+ Aig_Obj_t * pObj;
+ DdNode * bCof, * bVar;
+ int i, iVar, iVarBest = -1, iValue, iValueBest = ABC_INFINITY, Size0Best = -1;
+ int Size, Size0, Size1;
+ int clk = clock();
+ Size = Cudd_DagSize(bFunc);
+// printf( "Original = %6d. SuppSize = %3d. Vars = %3d.\n",
+// Size = Cudd_DagSize(bFunc), Cudd_SupportSize(dd, bFunc), Aig_ManRegNum(pAig) );
+ Saig_ManForEachLo( pAig, pObj, i )
+ {
+ iVar = Aig_ObjId(pObj);
+
+if ( fVerbose )
+printf( "Var =%3d : ", iVar );
+ bVar = Cudd_bddIthVar(dd, iVar);
+
+ bCof = Cudd_bddAnd( dd, bFunc, Cudd_Not(bVar) ); Cudd_Ref( bCof );
+ Size0 = Cudd_DagSize(bCof);
+if ( fVerbose )
+printf( "Supp0 =%3d ", Cudd_SupportSize(dd, bCof) );
+if ( fVerbose )
+printf( "Size0 =%6d ", Size0 );
+ Cudd_RecursiveDeref( dd, bCof );
+
+ bCof = Cudd_bddAnd( dd, bFunc, bVar ); Cudd_Ref( bCof );
+ Size1 = Cudd_DagSize(bCof);
+if ( fVerbose )
+printf( "Supp1 =%3d ", Cudd_SupportSize(dd, bCof) );
+if ( fVerbose )
+printf( "Size1 =%6d ", Size1 );
+ Cudd_RecursiveDeref( dd, bCof );
+
+ iValue = Abc_MaxInt(Size0, Size1) - Abc_MinInt(Size0, Size1) + Size0 + Size1 - Size;
+if ( fVerbose )
+printf( "D =%6d ", Size0 + Size1 - Size );
+if ( fVerbose )
+printf( "B =%6d ", Abc_MaxInt(Size0, Size1) - Abc_MinInt(Size0, Size1) );
+if ( fVerbose )
+printf( "S =%6d\n", iValue );
+ if ( Size0 > 1 && Size1 > 1 && iValueBest > iValue )
+ {
+ iValueBest = iValue;
+ iVarBest = i;
+ Size0Best = Size0;
+ }
+ }
+ printf( "BestVar = %4d/%4d. Value =%6d. Orig =%6d. Size0 =%6d. ",
+ iVarBest, Aig_ObjId(Saig_ManLo(pAig,iVarBest)), iValueBest, Size, Size0Best );
+ Abc_PrintTime( 1, "Time", clock() - clk );
+ return iVarBest;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds variable whose 0-cofactor is the smallest.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinTrySubsetting( DdManager * dd, DdNode * bFunc )
+{
+ DdNode * bNew;
+ printf( "Original = %6d. SuppSize = %3d. ",
+ Cudd_DagSize(bFunc), Cudd_SupportSize(dd, bFunc) );
+ bNew = Cudd_SubsetHeavyBranch( dd, bFunc, Cudd_SupportSize(dd, bFunc), 1000 ); Cudd_Ref( bNew );
+ printf( "Result = %6d. SuppSize = %3d.\n",
+ Cudd_DagSize(bNew), Cudd_SupportSize(dd, bNew) );
+ Cudd_RecursiveDeref( dd, bNew );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinPrepareVarMap( Llb_Mnn_t * p )
+{
+ Aig_Obj_t * pObjLi, * pObjLo, * pObj;
+ int i, iVarLi, iVarLo;
+ p->vCs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) );
+ p->vNs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) );
+ p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) );
+ p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) );
+ Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+ {
+ iVarLi = Aig_ObjId(pObjLi);
+ iVarLo = Aig_ObjId(pObjLo);
+ assert( iVarLi >= 0 && iVarLi < Aig_ManObjNumMax(p->pAig) );
+ assert( iVarLo >= 0 && iVarLo < Aig_ManObjNumMax(p->pAig) );
+ Vec_IntWriteEntry( p->vCs2Glo, iVarLo, i );
+ Vec_IntWriteEntry( p->vNs2Glo, iVarLi, i );
+ Vec_IntWriteEntry( p->vGlo2Cs, i, iVarLo );
+ Vec_IntWriteEntry( p->vGlo2Ns, i, iVarLi );
+ }
+ // add mapping of the PIs
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ {
+ Vec_IntWriteEntry( p->vCs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i );
+ Vec_IntWriteEntry( p->vNs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i );
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_NonlinComputeInitState( Aig_Man_t * pAig, DdManager * dd )
+{
+ Aig_Obj_t * pObj;
+ DdNode * bRes, * bVar, * bTemp;
+ int i, iVar, TimeStop;
+ TimeStop = dd->TimeStop; dd->TimeStop = 0;
+ bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes );
+ Saig_ManForEachLo( pAig, pObj, i )
+ {
+ iVar = (Cudd_ReadSize(dd) == Aig_ManRegNum(pAig)) ? i : Aig_ObjId(pObj);
+ bVar = Cudd_bddIthVar( dd, iVar );
+ bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bRes );
+ dd->TimeStop = TimeStop;
+ return bRes;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Derives counter-example by backward reachability.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Cex_t * Llb_NonlinDeriveCex( Llb_Mnn_t * p )
+{
+ Abc_Cex_t * pCex;
+ Aig_Obj_t * pObj;
+ Vec_Int_t * vVarsNs;
+ DdNode * bState, * bImage, * bOneCube, * bTemp, * bRing;
+ int i, v, RetValue, nPiOffset;
+ char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) );
+ assert( Vec_PtrSize(p->vRings) > 0 );
+
+ p->dd->TimeStop = 0;
+ p->ddR->TimeStop = 0;
+
+ // update quantifiable vars
+ memset( p->pVars2Q, 0, sizeof(int) * Cudd_ReadSize(p->dd) );
+ vVarsNs = Vec_IntAlloc( Aig_ManRegNum(p->pAig) );
+ Saig_ManForEachLi( p->pAig, pObj, i )
+ {
+ p->pVars2Q[Aig_ObjId(pObj)] = 1;
+ Vec_IntPush( vVarsNs, Aig_ObjId(pObj) );
+ }
+/*
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ printf( "%d ", pObj->Id );
+ printf( "\n" );
+ Saig_ManForEachLi( p->pAig, pObj, i )
+ printf( "%d(%d) ", pObj->Id, Aig_ObjFaninId0(pObj) );
+ printf( "\n" );
+*/
+ // allocate room for the counter-example
+ pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) );
+ pCex->iFrame = Vec_PtrSize(p->vRings) - 1;
+ pCex->iPo = -1;
+
+ // get the last cube
+ bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc ); Cudd_Ref( bOneCube );
+ RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues );
+ Cudd_RecursiveDeref( p->ddR, bOneCube );
+ assert( RetValue );
+
+ // write PIs of counter-example
+ nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1);
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 )
+ Abc_InfoSetBit( pCex->pData, nPiOffset + i );
+
+ // write state in terms of NS variables
+ if ( Vec_PtrSize(p->vRings) > 1 )
+ {
+ bState = Llb_CoreComputeCube( p->dd, vVarsNs, 1, pValues ); Cudd_Ref( bState );
+ }
+ // perform backward analysis
+ Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v )
+ {
+ if ( v == Vec_PtrSize(p->vRings) - 1 )
+ continue;
+//Extra_bddPrintSupport( p->dd, bState ); printf( "\n" );
+//Extra_bddPrintSupport( p->dd, bRing ); printf( "\n" );
+ // compute the next states
+ bImage = Llb_NonlinImage( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->dd, bState,
+ p->pPars->fReorder, p->pPars->fVeryVerbose, NULL, ABC_INFINITY, ABC_INFINITY ); // consumed reference
+ assert( bImage != NULL );
+ Cudd_Ref( bImage );
+//Extra_bddPrintSupport( p->dd, bImage ); printf( "\n" );
+
+ // move reached states into ring manager
+ bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) ); Cudd_Ref( bImage );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+
+ // intersect with the previous set
+ bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing ); Cudd_Ref( bOneCube );
+ Cudd_RecursiveDeref( p->ddR, bImage );
+
+ // find any assignment of the BDD
+ RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues );
+ Cudd_RecursiveDeref( p->ddR, bOneCube );
+ assert( RetValue );
+
+ // write PIs of counter-example
+ nPiOffset -= Saig_ManPiNum(p->pAig);
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 )
+ Abc_InfoSetBit( pCex->pData, nPiOffset + i );
+
+ // check that we get the init state
+ if ( v == 0 )
+ {
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ assert( pValues[i] == 0 );
+ break;
+ }
+
+ // write state in terms of NS variables
+ bState = Llb_CoreComputeCube( p->dd, vVarsNs, 1, pValues ); Cudd_Ref( bState );
+ }
+ assert( nPiOffset == Saig_ManRegNum(p->pAig) );
+ // update the output number
+//Abc_CexPrint( pCex );
+ RetValue = Saig_ManFindFailedPoCex( p->pInit, pCex );
+ assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pInit) ); // invalid CEX!!!
+ pCex->iPo = RetValue;
+ // cleanup
+ ABC_FREE( pValues );
+ Vec_IntFree( vVarsNs );
+ return pCex;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Perform reachability with hints.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_NonlinReoHook( DdManager * dd, char * Type, void * Method )
+{
+ Aig_Man_t * pAig = (Aig_Man_t *)dd->bFunc;
+ Aig_Obj_t * pObj;
+ int i;
+ printf( "Order: " );
+ for ( i = 0; i < Cudd_ReadSize(dd); i++ )
+ {
+ pObj = Aig_ManObj( pAig, i );
+ if ( pObj == NULL )
+ continue;
+ if ( Saig_ObjIsPi(pAig, pObj) )
+ printf( "pi" );
+ else if ( Saig_ObjIsLo(pAig, pObj) )
+ printf( "lo" );
+ else if ( Saig_ObjIsPo(pAig, pObj) )
+ printf( "po" );
+ else if ( Saig_ObjIsLi(pAig, pObj) )
+ printf( "li" );
+ else continue;
+ printf( "%d=%d ", i, dd->perm[i] );
+ }
+ printf( "\n" );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Perform reachability with hints.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_NonlinCompPerms( DdManager * dd, int * pVar2Lev )
+{
+ DdSubtable * pSubt;
+ int i, Sum = 0, Entry;
+ for ( i = 0; i < dd->size; i++ )
+ {
+ pSubt = &(dd->subtables[dd->perm[i]]);
+ if ( pSubt->keys == pSubt->dead + 1 )
+ continue;
+ Entry = Abc_MaxInt(dd->perm[i], pVar2Lev[i]) - Abc_MinInt(dd->perm[i], pVar2Lev[i]);
+ Sum += Entry;
+//printf( "%d-%d(%d) ", dd->perm[i], pV2L[i], Entry );
+ }
+ return Sum;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Perform reachability with hints.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_NonlinReachability( Llb_Mnn_t * p )
+{
+ DdNode * bTemp, * bNext;
+ int nIters, nBddSize0, nBddSize, NumCmp, Limit = p->pPars->nBddMax;
+ int clk2, clk3, clk = clock();
+ assert( Aig_ManRegNum(p->pAig) > 0 );
+
+ // compute time to stop
+ p->pPars->TimeTarget = p->pPars->TimeLimit ? time(NULL) + p->pPars->TimeLimit : 0;
+
+ // set the stop time parameter
+ p->dd->TimeStop = p->pPars->TimeTarget;
+ p->ddG->TimeStop = p->pPars->TimeTarget;
+ p->ddR->TimeStop = p->pPars->TimeTarget;
+
+ // set reordering hooks
+ assert( p->dd->bFunc == NULL );
+// p->dd->bFunc = (DdNode *)p->pAig;
+// Cudd_AddHook( p->dd, Llb_NonlinReoHook, CUDD_POST_REORDERING_HOOK );
+
+ // create bad state in the ring manager
+ p->ddR->bFunc = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget );
+ if ( p->ddR->bFunc == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = -1;
+ return -1;
+ }
+ Cudd_Ref( p->ddR->bFunc );
+ // compute the starting set of states
+ Cudd_Quit( p->dd );
+ p->dd = Llb_NonlinImageStart( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->pOrderL, 1, p->pPars->TimeTarget );
+ if ( p->dd == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = -1;
+ return -1;
+ }
+ p->dd->bFunc = Llb_NonlinComputeInitState( p->pAig, p->dd ); Cudd_Ref( p->dd->bFunc ); // current
+ p->ddG->bFunc = Llb_NonlinComputeInitState( p->pAig, p->ddG ); Cudd_Ref( p->ddG->bFunc ); // reached
+ p->ddG->bFunc2 = Llb_NonlinComputeInitState( p->pAig, p->ddG ); Cudd_Ref( p->ddG->bFunc2 ); // frontier
+ for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ )
+ {
+ // check the runtime limit
+ clk2 = clock();
+ if ( p->pPars->TimeLimit && time(NULL) > p->pPars->TimeTarget )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Llb_NonlinImageQuit();
+ return -1;
+ }
+
+ // save the onion ring
+ bTemp = Extra_TransferPermute( p->dd, p->ddR, p->dd->bFunc, Vec_IntArray(p->vCs2Glo) );
+ if ( bTemp == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during ring transfer.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Llb_NonlinImageQuit();
+ return -1;
+ }
+ Cudd_Ref( bTemp );
+ Vec_PtrPush( p->vRings, bTemp );
+
+ // check it for bad states
+ if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) )
+ {
+ assert( p->pInit->pSeqModel == NULL );
+ if ( !p->pPars->fBackward )
+ p->pInit->pSeqModel = Llb_NonlinDeriveCex( p );
+ if ( !p->pPars->fSilent )
+ {
+ if ( !p->pPars->fBackward )
+ printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump a witness). ", p->pInit->pSeqModel->iPo, nIters );
+ else
+ printf( "Output ??? was asserted in frame %d (counter-example is not produced). ", nIters );
+ Abc_PrintTime( 1, "Time", clock() - clk );
+ }
+ p->pPars->iFrame = nIters - 1;
+ Llb_NonlinImageQuit();
+ return 0;
+ }
+
+ // compute the next states
+ clk3 = clock();
+ nBddSize0 = Cudd_DagSize( p->dd->bFunc );
+ bNext = Llb_NonlinImageCompute( p->dd->bFunc, p->pPars->fReorder, 0, 1, p->pOrderL ); // consumes ref
+// bNext = Llb_NonlinImage( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->dd, bCurrent,
+// p->pPars->fReorder, p->pPars->fVeryVerbose, NULL, ABC_INFINITY, p->pPars->TimeTarget );
+ if ( bNext == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation in quantification.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Llb_NonlinImageQuit();
+ return -1;
+ }
+ Cudd_Ref( bNext );
+ nBddSize = Cudd_DagSize( bNext );
+ p->timeImage += clock() - clk3;
+
+
+ // transfer to the state manager
+ clk3 = clock();
+ Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc2 );
+ p->ddG->bFunc2 = Extra_TransferPermute( p->dd, p->ddG, bNext, Vec_IntArray(p->vNs2Glo) );
+// p->ddG->bFunc2 = Extra_bddAndPermute( p->ddG, Cudd_Not(p->ddG->bFunc), p->dd, bNext, Vec_IntArray(p->vNs2Glo) );
+ if ( p->ddG->bFunc2 == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->dd, bNext );
+ Llb_NonlinImageQuit();
+ return -1;
+ }
+ Cudd_Ref( p->ddG->bFunc2 );
+ Cudd_RecursiveDeref( p->dd, bNext );
+ p->timeTran1 += clock() - clk3;
+
+ // save permutation
+ NumCmp = Llb_NonlinCompPerms( p->dd, p->pOrderL2 );
+ // save order before image computation
+ memcpy( p->pOrderL2, p->dd->perm, sizeof(int) * p->dd->size );
+ // update the image computation manager
+ p->timeReo += Cudd_ReadReorderingTime(p->dd);
+ p->ddLocReos += Cudd_ReadReorderings(p->dd);
+ p->ddLocGrbs += Cudd_ReadGarbageCollections(p->dd);
+ Llb_NonlinImageQuit();
+ p->dd = Llb_NonlinImageStart( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->pOrderL, 0, p->pPars->TimeTarget );
+ if ( p->dd == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ return -1;
+ }
+ //Extra_TestAndPerm( p->ddG, Cudd_Not(p->ddG->bFunc), p->ddG->bFunc2 );
+
+ // derive new states
+ clk3 = clock();
+ p->ddG->bFunc2 = Cudd_bddAnd( p->ddG, bTemp = p->ddG->bFunc2, Cudd_Not(p->ddG->bFunc) );
+ if ( p->ddG->bFunc2 == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->ddG, bTemp );
+ Llb_NonlinImageQuit();
+ return -1;
+ }
+ Cudd_Ref( p->ddG->bFunc2 );
+ Cudd_RecursiveDeref( p->ddG, bTemp );
+ p->timeGloba += clock() - clk3;
+
+ if ( Cudd_IsConstant(p->ddG->bFunc2) )
+ break;
+ // add to the reached set
+ clk3 = clock();
+ p->ddG->bFunc = Cudd_bddOr( p->ddG, bTemp = p->ddG->bFunc, p->ddG->bFunc2 );
+ if ( p->ddG->bFunc == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->ddG, bTemp );
+ Llb_NonlinImageQuit();
+ return -1;
+ }
+ Cudd_Ref( p->ddG->bFunc );
+ Cudd_RecursiveDeref( p->ddG, bTemp );
+ p->timeGloba += clock() - clk3;
+
+ // reset permutation
+// RetValue = Cudd_CheckZeroRef( dd );
+// assert( RetValue == 0 );
+// Cudd_ShuffleHeap( dd, pOrderG );
+
+ // move new states to the working manager
+ clk3 = clock();
+ p->dd->bFunc = Extra_TransferPermute( p->ddG, p->dd, p->ddG->bFunc2, Vec_IntArray(p->vGlo2Cs) );
+ if ( p->dd->bFunc == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Llb_NonlinImageQuit();
+ return -1;
+ }
+ Cudd_Ref( p->dd->bFunc );
+ p->timeTran2 += clock() - clk3;
+
+ // report the results
+ if ( p->pPars->fVerbose )
+ {
+ printf( "I =%3d : ", nIters );
+ printf( "Fr =%7d ", nBddSize0 );
+ printf( "Im =%7d ", nBddSize );
+ printf( "(%4d %4d) ", p->ddLocReos, p->ddLocGrbs );
+ printf( "Rea =%6d ", Cudd_DagSize(p->ddG->bFunc) );
+ printf( "(%4d %4d) ", Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) );
+ printf( "S =%4d ", nSuppMax );
+ printf( "cL =%5d ", NumCmp );
+ printf( "cG =%5d ", Llb_NonlinCompPerms( p->ddG, p->pOrderG ) );
+ Abc_PrintTime( 1, "T", clock() - clk2 );
+ memcpy( p->pOrderG, p->ddG->perm, sizeof(int) * p->ddG->size );
+ }
+/*
+ if ( pPars->fVerbose )
+ {
+ double nMints = Cudd_CountMinterm(ddG, bReached, Saig_ManRegNum(pAig) );
+// Extra_bddPrint( ddG, bReached );printf( "\n" );
+ printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(pAig)) );
+ fflush( stdout );
+ }
+*/
+ if ( nIters == p->pPars->nIterMax - 1 )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nIterMax );
+ p->pPars->iFrame = nIters;
+ Llb_NonlinImageQuit();
+ return -1;
+ }
+ }
+ Llb_NonlinImageQuit();
+
+ // report the stats
+ if ( p->pPars->fVerbose )
+ {
+ double nMints = Cudd_CountMinterm(p->ddG, p->ddG->bFunc, Saig_ManRegNum(p->pAig) );
+ if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax )
+ printf( "Reachability analysis is stopped after %d frames.\n", nIters );
+ else
+ printf( "Reachability analysis completed after %d frames.\n", nIters );
+ printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) );
+ fflush( stdout );
+ }
+ if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Verified only for states reachable in %d frames. ", nIters );
+ p->pPars->iFrame = p->pPars->nIterMax;
+ return -1; // undecided
+ }
+ // report
+ if ( !p->pPars->fSilent )
+ printf( "The miter is proved unreachable after %d iterations. ", nIters );
+ p->pPars->iFrame = nIters - 1;
+ Abc_PrintTime( 1, "Time", clock() - clk );
+ return 1; // unreachable
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Mnn_t * Llb_MnnStart( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars )
+{
+ Llb_Mnn_t * p;
+ Aig_Obj_t * pObj;
+ int i;
+ p = ABC_CALLOC( Llb_Mnn_t, 1 );
+ p->pInit = pInit;
+ p->pAig = pAig;
+ p->pPars = pPars;
+ p->dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ p->ddG = Cudd_Init( Aig_ManRegNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ p->ddR = Cudd_Init( Aig_ManPiNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT );
+ Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT );
+ Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT );
+ p->vRings = Vec_PtrAlloc( 100 );
+ // create leaves
+ p->vLeaves = Vec_PtrAlloc( Aig_ManPiNum(pAig) );
+ Aig_ManForEachPi( pAig, pObj, i )
+ Vec_PtrPush( p->vLeaves, pObj );
+ // create roots
+ p->vRoots = Vec_PtrAlloc( Aig_ManPoNum(pAig) );
+ Saig_ManForEachLi( pAig, pObj, i )
+ Vec_PtrPush( p->vRoots, pObj );
+ // variables to quantify
+ p->pOrderL = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) );
+ p->pOrderL2= ABC_CALLOC( int, Aig_ManObjNumMax(pAig) );
+ p->pOrderG = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) );
+ p->pVars2Q = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) );
+ Aig_ManForEachPi( pAig, pObj, i )
+ p->pVars2Q[Aig_ObjId(pObj)] = 1;
+ for ( i = 0; i < Aig_ManObjNumMax(pAig); i++ )
+ p->pOrderL[i] = p->pOrderL2[i] = p->pOrderG[i] = i;
+ Llb_NonlinPrepareVarMap( p );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MnnStop( Llb_Mnn_t * p )
+{
+ DdNode * bTemp;
+ int i;
+ if ( p->pPars->fVerbose )
+ {
+ p->timeOther = p->timeTotal - p->timeImage - p->timeTran1 - p->timeTran2 - p->timeGloba;
+ p->timeReoG = Cudd_ReadReorderingTime(p->ddG);
+ ABC_PRTP( "Image ", p->timeImage, p->timeTotal );
+ ABC_PRTP( " build ", timeBuild, p->timeTotal );
+ ABC_PRTP( " and-ex ", timeAndEx, p->timeTotal );
+ ABC_PRTP( " other ", timeOther, p->timeTotal );
+ ABC_PRTP( "Transfer1", p->timeTran1, p->timeTotal );
+ ABC_PRTP( "Transfer2", p->timeTran2, p->timeTotal );
+ ABC_PRTP( "Global ", p->timeGloba, p->timeTotal );
+ ABC_PRTP( "Other ", p->timeOther, p->timeTotal );
+ ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal );
+ ABC_PRTP( " reo ", p->timeReo, p->timeTotal );
+ ABC_PRTP( " reoG ", p->timeReoG, p->timeTotal );
+ }
+ if ( p->ddR->bFunc )
+ Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc );
+ Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i )
+ Cudd_RecursiveDeref( p->ddR, bTemp );
+ Vec_PtrFree( p->vRings );
+ if ( p->ddG->bFunc )
+ Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc );
+ if ( p->ddG->bFunc2 )
+ Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc2 );
+// printf( "manager1\n" );
+// Extra_StopManager( p->dd );
+// printf( "manager2\n" );
+ Extra_StopManager( p->ddG );
+// printf( "manager3\n" );
+ Extra_StopManager( p->ddR );
+ Vec_IntFreeP( &p->vCs2Glo );
+ Vec_IntFreeP( &p->vNs2Glo );
+ Vec_IntFreeP( &p->vGlo2Cs );
+ Vec_IntFreeP( &p->vGlo2Ns );
+ Vec_PtrFree( p->vLeaves );
+ Vec_PtrFree( p->vRoots );
+ ABC_FREE( p->pVars2Q );
+ ABC_FREE( p->pOrderL );
+ ABC_FREE( p->pOrderL2 );
+ ABC_FREE( p->pOrderG );
+ ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Finds balanced cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_NonlinExperiment( Aig_Man_t * pAig, int Num )
+{
+ Llb_Mnn_t * pMnn;
+ Gia_ParLlb_t Pars, * pPars = &Pars;
+ Aig_Man_t * p;
+ int clk = clock();
+
+ Llb_ManSetDefaultParams( pPars );
+ pPars->fVerbose = 1;
+
+ p = Aig_ManDupFlopsOnly( pAig );
+//Aig_ManShow( p, 0, NULL );
+ Aig_ManPrintStats( pAig );
+ Aig_ManPrintStats( p );
+
+ pMnn = Llb_MnnStart( pAig, p, pPars );
+ Llb_NonlinReachability( pMnn );
+ pMnn->timeTotal = clock() - clk;
+ Llb_MnnStop( pMnn );
+
+ Aig_ManStop( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds balanced cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_NonlinCoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars )
+{
+ Llb_Mnn_t * pMnn;
+ Aig_Man_t * p;
+ int RetValue = -1;
+
+ p = Aig_ManDupFlopsOnly( pAig );
+//Aig_ManShow( p, 0, NULL );
+ if ( pPars->fVerbose )
+ Aig_ManPrintStats( pAig );
+ if ( pPars->fVerbose )
+ Aig_ManPrintStats( p );
+
+ if ( !pPars->fSkipReach )
+ {
+ int clk = clock();
+ pMnn = Llb_MnnStart( pAig, p, pPars );
+ RetValue = Llb_NonlinReachability( pMnn );
+ pMnn->timeTotal = clock() - clk;
+ Llb_MnnStop( pMnn );
+ }
+
+ Aig_ManStop( p );
+ return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/llb/llb4Cex.c b/src/proof/llb/llb4Cex.c
new file mode 100644
index 00000000..a68be711
--- /dev/null
+++ b/src/proof/llb/llb4Cex.c
@@ -0,0 +1,320 @@
+/**CFile****************************************************************
+
+ FileName [llb2Cex.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Non-linear quantification scheduling.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb2Cex.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+#include "src/sat/cnf/cnf.h"
+#include "src/sat/bsat/satSolver.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Translates a sequence of states into a counter-example.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Cex_t * Llb4_Nonlin4TransformCex( Aig_Man_t * pAig, Vec_Ptr_t * vStates, int iCexPo, int fVerbose )
+{
+ Abc_Cex_t * pCex;
+ Cnf_Dat_t * pCnf;
+ Vec_Int_t * vAssumps;
+ sat_solver * pSat;
+ Aig_Obj_t * pObj;
+ unsigned * pNext, * pThis;
+ int i, k, iBit, status, nRegs, clk = clock();
+/*
+ Vec_PtrForEachEntry( unsigned *, vStates, pNext, i )
+ {
+ printf( "%4d : ", i );
+ Extra_PrintBinary( stdout, pNext, Aig_ManRegNum(pAig) );
+ printf( "\n" );
+ }
+*/
+ // derive SAT solver
+ nRegs = Aig_ManRegNum(pAig); pAig->nRegs = 0;
+ pCnf = Cnf_Derive( pAig, Aig_ManPoNum(pAig) );
+ pAig->nRegs = nRegs;
+// Cnf_DataTranformPolarity( pCnf, 0 );
+ // convert into SAT solver
+ pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+ if ( pSat == NULL )
+ {
+ printf( "Llb4_Nonlin4TransformCex(): Counter-example generation has failed.\n" );
+ Cnf_DataFree( pCnf );
+ return NULL;
+ }
+ // simplify the problem
+ status = sat_solver_simplify(pSat);
+ if ( status == 0 )
+ {
+ printf( "Llb4_Nonlin4TransformCex(): SAT solver is invalid.\n" );
+ sat_solver_delete( pSat );
+ Cnf_DataFree( pCnf );
+ return NULL;
+ }
+ // start the counter-example
+ pCex = Abc_CexAlloc( Saig_ManRegNum(pAig), Saig_ManPiNum(pAig), Vec_PtrSize(vStates) );
+ pCex->iFrame = Vec_PtrSize(vStates)-1;
+ pCex->iPo = -1;
+
+ // solve each time frame
+ iBit = Saig_ManRegNum(pAig);
+ pThis = (unsigned *)Vec_PtrEntry( vStates, 0 );
+ vAssumps = Vec_IntAlloc( 2 * Aig_ManRegNum(pAig) );
+ Vec_PtrForEachEntryStart( unsigned *, vStates, pNext, i, 1 )
+ {
+ // create assumptions
+ Vec_IntClear( vAssumps );
+ Saig_ManForEachLo( pAig, pObj, k )
+ Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Abc_InfoHasBit(pThis,k) ) );
+ Saig_ManForEachLi( pAig, pObj, k )
+ Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Abc_InfoHasBit(pNext,k) ) );
+ // solve SAT problem
+ status = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps),
+ (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+ // if the problem is SAT, get the counterexample
+ if ( status != l_True )
+ {
+ printf( "Llb4_Nonlin4TransformCex(): There is no transition between state %d and %d.\n", i-1, i );
+ Vec_IntFree( vAssumps );
+ sat_solver_delete( pSat );
+ Cnf_DataFree( pCnf );
+ ABC_FREE( pCex );
+ return NULL;
+ }
+ // get the assignment of PIs
+ Saig_ManForEachPi( pAig, pObj, k )
+ if ( sat_solver_var_value(pSat, pCnf->pVarNums[Aig_ObjId(pObj)]) )
+ Abc_InfoSetBit( pCex->pData, iBit + k );
+ // update the counter
+ iBit += Saig_ManPiNum(pAig);
+ pThis = pNext;
+ }
+
+ // add the last frame when the property fails
+ Vec_IntClear( vAssumps );
+ if ( iCexPo >= 0 )
+ {
+ Saig_ManForEachPo( pAig, pObj, k )
+ if ( k == iCexPo )
+ Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 ) );
+ }
+ else
+ {
+ Saig_ManForEachPo( pAig, pObj, k )
+ Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 ) );
+ }
+
+ // add clause
+ status = sat_solver_addclause( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps) );
+ if ( status == 0 )
+ {
+ printf( "Llb4_Nonlin4TransformCex(): The SAT solver is unsat after adding last clause.\n" );
+ Vec_IntFree( vAssumps );
+ sat_solver_delete( pSat );
+ Cnf_DataFree( pCnf );
+ ABC_FREE( pCex );
+ return NULL;
+ }
+ // create assumptions
+ Vec_IntClear( vAssumps );
+ Saig_ManForEachLo( pAig, pObj, k )
+ Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Abc_InfoHasBit(pThis,k) ) );
+ // solve the last frame
+ status = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps),
+ (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+ if ( status != l_True )
+ {
+ printf( "Llb4_Nonlin4TransformCex(): There is no last transition that makes the property fail.\n" );
+ Vec_IntFree( vAssumps );
+ sat_solver_delete( pSat );
+ Cnf_DataFree( pCnf );
+ ABC_FREE( pCex );
+ return NULL;
+ }
+ // get the assignment of PIs
+ Saig_ManForEachPi( pAig, pObj, k )
+ if ( sat_solver_var_value(pSat, pCnf->pVarNums[Aig_ObjId(pObj)]) )
+ Abc_InfoSetBit( pCex->pData, iBit + k );
+ iBit += Saig_ManPiNum(pAig);
+ assert( iBit == pCex->nBits );
+
+ // free the sat_solver
+ Vec_IntFree( vAssumps );
+ sat_solver_delete( pSat );
+ Cnf_DataFree( pCnf );
+
+ // verify counter-example
+ status = Saig_ManFindFailedPoCex( pAig, pCex );
+ if ( status >= 0 && status < Saig_ManPoNum(pAig) )
+ pCex->iPo = status;
+ else
+ {
+ printf( "Llb4_Nonlin4TransformCex(): Counter-example verification has FAILED.\n" );
+ ABC_FREE( pCex );
+ return NULL;
+ }
+ // report the results
+// if ( fVerbose )
+// Abc_PrintTime( 1, "SAT-based cex generation time", clock() - clk );
+ return pCex;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Resimulates the counter-example.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb4_Nonlin4VerifyCex( Aig_Man_t * pAig, Abc_Cex_t * p )
+{
+ Vec_Ptr_t * vStates;
+ Aig_Obj_t * pObj, * pObjRi, * pObjRo;
+ int i, k, iBit = 0;
+ // create storage for states
+ vStates = Vec_PtrAllocSimInfo( p->iFrame+1, Abc_BitWordNum(Aig_ManRegNum(pAig)) );
+ Vec_PtrCleanSimInfo( vStates, 0, Abc_BitWordNum(Aig_ManRegNum(pAig)) );
+ // verify counter-example
+ Aig_ManCleanMarkB(pAig);
+ Aig_ManConst1(pAig)->fMarkB = 1;
+ Saig_ManForEachLo( pAig, pObj, i )
+ pObj->fMarkB = 0; //Abc_InfoHasBit(p->pData, iBit++);
+ // do not require equal flop count in the AIG and in the CEX
+ iBit = p->nRegs;
+ for ( i = 0; i <= p->iFrame; i++ )
+ {
+ // save current state
+ Saig_ManForEachLo( pAig, pObj, k )
+ if ( pObj->fMarkB )
+ Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(vStates, i), k );
+ // compute new state
+ Saig_ManForEachPi( pAig, pObj, k )
+ pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++);
+ Aig_ManForEachNode( pAig, pObj, k )
+ pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) &
+ (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj));
+ Aig_ManForEachPo( pAig, pObj, k )
+ pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj);
+ if ( i == p->iFrame )
+ break;
+ Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, k )
+ pObjRo->fMarkB = pObjRi->fMarkB;
+ }
+/*
+ {
+ unsigned * pNext;
+ Vec_PtrForEachEntry( unsigned *, vStates, pNext, i )
+ {
+ printf( "%4d : ", i );
+ Extra_PrintBinary( stdout, pNext, Aig_ManRegNum(pAig) );
+ printf( "\n" );
+ }
+ }
+*/
+ assert( iBit == p->nBits );
+// if ( Aig_ManPo(pAig, p->iPo)->fMarkB == 0 )
+// Vec_PtrFreeP( &vStates );
+ for ( i = Saig_ManPoNum(pAig) - 1; i >= 0; i-- )
+ {
+ if ( Aig_ManPo(pAig, i)->fMarkB )
+ {
+ p->iPo = i;
+ break;
+ }
+ }
+ if ( i == -1 )
+ Vec_PtrFreeP( &vStates );
+ Aig_ManCleanMarkB(pAig);
+ return vStates;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Translates a sequence of states into a counter-example.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Cex_t * Llb4_Nonlin4NormalizeCex( Aig_Man_t * pAigOrg, Aig_Man_t * pAigRpm, Abc_Cex_t * pCexRpm )
+{
+ Abc_Cex_t * pCexOrg;
+ Vec_Ptr_t * vStates;
+ // check parameters of the AIG
+ if ( Saig_ManRegNum(pAigOrg) != Saig_ManRegNum(pAigRpm) )
+ {
+ printf( "Llb4_Nonlin4NormalizeCex(): The number of flops in the original and reparametrized AIGs do not agree.\n" );
+ return NULL;
+ }
+/*
+ if ( Saig_ManRegNum(pAigRpm) != pCexRpm->nRegs )
+ {
+ printf( "Llb4_Nonlin4NormalizeCex(): The number of flops in the reparametrized AIG and in the CEX do not agree.\n" );
+ return NULL;
+ }
+*/
+ if ( Saig_ManPiNum(pAigRpm) != pCexRpm->nPis )
+ {
+ printf( "Llb4_Nonlin4NormalizeCex(): The number of PIs in the reparametrized AIG and in the CEX do not agree.\n" );
+ return NULL;
+ }
+ // get the sequence of states
+ vStates = Llb4_Nonlin4VerifyCex( pAigRpm, pCexRpm );
+ if ( vStates == NULL )
+ {
+ Abc_Print( 1, "Llb4_Nonlin4NormalizeCex(): The given CEX does not fail outputs of pAigRpm.\n" );
+ return NULL;
+ }
+ // derive updated counter-example
+ pCexOrg = Llb4_Nonlin4TransformCex( pAigOrg, vStates, pCexRpm->iPo, 0 );
+ Vec_PtrFree( vStates );
+ return pCexOrg;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/llb/llb4Cluster.c b/src/proof/llb/llb4Cluster.c
new file mode 100644
index 00000000..8d29eed4
--- /dev/null
+++ b/src/proof/llb/llb4Cluster.c
@@ -0,0 +1,452 @@
+/**CFile****************************************************************
+
+ FileName [llb2Cluster.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Non-linear quantification scheduling.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb2Cluster.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Find good static variable ordering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4FindOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter )
+{
+ Aig_Obj_t * pFanin0, * pFanin1;
+ if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+ return;
+ Aig_ObjSetTravIdCurrent( pAig, pObj );
+ assert( Llb_ObjBddVar(vOrder, pObj) < 0 );
+ if ( Aig_ObjIsPi(pObj) )
+ {
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ );
+ return;
+ }
+ // try fanins with higher level first
+ pFanin0 = Aig_ObjFanin0(pObj);
+ pFanin1 = Aig_ObjFanin1(pObj);
+// if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) )
+ if ( pFanin0->Level > pFanin1->Level )
+ {
+ Llb_Nonlin4FindOrder_rec( pAig, pFanin0, vOrder, pCounter );
+ Llb_Nonlin4FindOrder_rec( pAig, pFanin1, vOrder, pCounter );
+ }
+ else
+ {
+ Llb_Nonlin4FindOrder_rec( pAig, pFanin1, vOrder, pCounter );
+ Llb_Nonlin4FindOrder_rec( pAig, pFanin0, vOrder, pCounter );
+ }
+ if ( pObj->fMarkA )
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find good static variable ordering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_Nonlin4FindOrder( Aig_Man_t * pAig, int * pCounter )
+{
+ Vec_Int_t * vNodes = NULL;
+ Vec_Int_t * vOrder;
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ // mark nodes to exclude: AND with low level and CO drivers
+ Aig_ManCleanMarkA( pAig );
+ Aig_ManForEachNode( pAig, pObj, i )
+ if ( Aig_ObjLevel(pObj) > 3 )
+ pObj->fMarkA = 1;
+ Aig_ManForEachPo( pAig, pObj, i )
+ Aig_ObjFanin0(pObj)->fMarkA = 0;
+
+ // collect nodes in the order
+ vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) );
+ Aig_ManIncrementTravId( pAig );
+ Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) );
+// Aig_ManForEachPo( pAig, pObj, i )
+ Saig_ManForEachLi( pAig, pObj, i )
+ {
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ );
+ Llb_Nonlin4FindOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter );
+ }
+ Aig_ManForEachPi( pAig, pObj, i )
+ if ( Llb_ObjBddVar(vOrder, pObj) < 0 )
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ );
+ Aig_ManCleanMarkA( pAig );
+ Vec_IntFreeP( &vNodes );
+// assert( Counter == Aig_ManObjNum(pAig) - 1 );
+
+/*
+ Saig_ManForEachPi( pAig, pObj, i )
+ printf( "pi%d ", Llb_ObjBddVar(vOrder, pObj) );
+ printf( "\n" );
+ Saig_ManForEachLo( pAig, pObj, i )
+ printf( "lo%d ", Llb_ObjBddVar(vOrder, pObj) );
+ printf( "\n" );
+ Saig_ManForEachPo( pAig, pObj, i )
+ printf( "po%d ", Llb_ObjBddVar(vOrder, pObj) );
+ printf( "\n" );
+ Saig_ManForEachLi( pAig, pObj, i )
+ printf( "li%d ", Llb_ObjBddVar(vOrder, pObj) );
+ printf( "\n" );
+ Aig_ManForEachNode( pAig, pObj, i )
+ printf( "n%d ", Llb_ObjBddVar(vOrder, pObj) );
+ printf( "\n" );
+*/
+ if ( pCounter )
+ *pCounter = Counter;
+ return vOrder;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives BDDs for the partitions.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_Nonlin4FindPartitions_rec( DdManager * dd, Aig_Obj_t * pObj, Vec_Int_t * vOrder, Vec_Ptr_t * vRoots )
+{
+ DdNode * bBdd, * bBdd0, * bBdd1, * bPart, * vVar;
+ if ( Aig_ObjIsConst1(pObj) )
+ return Cudd_ReadOne(dd);
+ if ( Aig_ObjIsPi(pObj) )
+ return Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+ if ( pObj->pData )
+ return (DdNode *)pObj->pData;
+ if ( Aig_ObjIsPo(pObj) )
+ {
+ bBdd0 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) );
+ bPart = Cudd_bddXnor( dd, Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ), bBdd0 ); Cudd_Ref( bPart );
+ Vec_PtrPush( vRoots, bPart );
+ return NULL;
+ }
+ bBdd0 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) );
+ bBdd1 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin1(pObj), vOrder, vRoots), Aig_ObjFaninC1(pObj) );
+ bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bBdd );
+ if ( Llb_ObjBddVar(vOrder, pObj) >= 0 )
+ {
+ vVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+ bPart = Cudd_bddXnor( dd, vVar, bBdd ); Cudd_Ref( bPart );
+ Vec_PtrPush( vRoots, bPart );
+ Cudd_RecursiveDeref( dd, bBdd );
+ bBdd = vVar; Cudd_Ref( vVar );
+ }
+ pObj->pData = bBdd;
+ return bBdd;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives BDDs for the partitions.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_Nonlin4FindPartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fOutputs )
+{
+ Vec_Ptr_t * vRoots;
+ Aig_Obj_t * pObj;
+ int i;
+ Aig_ManCleanData( pAig );
+ vRoots = Vec_PtrAlloc( 100 );
+ if ( fOutputs )
+ {
+ Saig_ManForEachPo( pAig, pObj, i )
+ Llb_Nonlin4FindPartitions_rec( dd, pObj, vOrder, vRoots );
+ }
+ else
+ {
+ Saig_ManForEachLi( pAig, pObj, i )
+ Llb_Nonlin4FindPartitions_rec( dd, pObj, vOrder, vRoots );
+ }
+ Aig_ManForEachNode( pAig, pObj, i )
+ if ( pObj->pData )
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+ return vRoots;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates quantifiable variables for both types of traversal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_Nonlin4FindVars2Q( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder )
+{
+ Vec_Int_t * vVars2Q;
+ Aig_Obj_t * pObj;
+ int i;
+ vVars2Q = Vec_IntAlloc( 0 );
+ Vec_IntFill( vVars2Q, Cudd_ReadSize(dd), 1 );
+ Saig_ManForEachLo( pAig, pObj, i )
+ Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 );
+// Aig_ManForEachPo( pAig, pObj, i )
+ Saig_ManForEachLi( pAig, pObj, i )
+ Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 );
+ return vVars2Q;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates quantifiable variables for both types of traversal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_Nonlin4CountTerms( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, DdNode * bFunc, int fCo, int fFlop )
+{
+ DdNode * bSupp;
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp );
+ if ( !fCo && !fFlop )
+ {
+ Saig_ManForEachPi( pAig, pObj, i )
+ if ( Llb_ObjBddVar(vOrder, pObj) >= 0 )
+ Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) );
+ }
+ else if ( fCo && !fFlop )
+ {
+ Saig_ManForEachPo( pAig, pObj, i )
+ if ( Llb_ObjBddVar(vOrder, pObj) >= 0 )
+ Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) );
+ }
+ else if ( !fCo && fFlop )
+ {
+ Saig_ManForEachLo( pAig, pObj, i )
+ if ( Llb_ObjBddVar(vOrder, pObj) >= 0 )
+ Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) );
+ }
+ else if ( fCo && fFlop )
+ {
+ Saig_ManForEachLi( pAig, pObj, i )
+ if ( Llb_ObjBddVar(vOrder, pObj) >= 0 )
+ Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) );
+ }
+ Cudd_RecursiveDeref( dd, bSupp );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates quantifiable variables for both types of traversal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4PrintGroups( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups )
+{
+ DdNode * bTemp;
+ int i, nSuppAll, nSuppPi, nSuppPo, nSuppLi, nSuppLo, nSuppAnd;
+ Vec_PtrForEachEntry( DdNode *, vGroups, bTemp, i )
+ {
+//Extra_bddPrintSupport(dd, bTemp); printf("\n" );
+ nSuppAll = Cudd_SupportSize(dd,bTemp);
+ nSuppPi = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 0, 0);
+ nSuppPo = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 1, 0);
+ nSuppLi = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 0, 1);
+ nSuppLo = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 1, 1);
+ nSuppAnd = nSuppAll - (nSuppPi+nSuppPo+nSuppLi+nSuppLo);
+
+ if ( Cudd_DagSize(bTemp) <= 10 )
+ continue;
+
+ printf( "%4d : bdd =%6d supp =%3d ", i, Cudd_DagSize(bTemp), nSuppAll );
+ printf( "pi =%3d ", nSuppPi );
+ printf( "po =%3d ", nSuppPo );
+ printf( "lo =%3d ", nSuppLo );
+ printf( "li =%3d ", nSuppLi );
+ printf( "and =%3d", nSuppAnd );
+ printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates quantifiable variables for both types of traversal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4PrintSuppProfile( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups )
+{
+ Aig_Obj_t * pObj;
+ int i, * pSupp;
+ int nSuppAll = 0, nSuppPi = 0, nSuppPo = 0, nSuppLi = 0, nSuppLo = 0, nSuppAnd = 0;
+
+ pSupp = ABC_CALLOC( int, Cudd_ReadSize(dd) );
+ Extra_VectorSupportArray( dd, (DdNode **)Vec_PtrArray(vGroups), Vec_PtrSize(vGroups), pSupp );
+
+ Aig_ManForEachObj( pAig, pObj, i )
+ {
+ if ( Llb_ObjBddVar(vOrder, pObj) < 0 )
+ continue;
+ // remove variables that do not participate
+ if ( pSupp[Llb_ObjBddVar(vOrder, pObj)] == 0 )
+ {
+ if ( Aig_ObjIsNode(pObj) )
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), -1 );
+ continue;
+ }
+ nSuppAll++;
+ if ( Saig_ObjIsPi(pAig, pObj) )
+ nSuppPi++;
+ else if ( Saig_ObjIsLo(pAig, pObj) )
+ nSuppLo++;
+ else if ( Saig_ObjIsPo(pAig, pObj) )
+ nSuppPo++;
+ else if ( Saig_ObjIsLi(pAig, pObj) )
+ nSuppLi++;
+ else
+ nSuppAnd++;
+ }
+ ABC_FREE( pSupp );
+
+ printf( "Groups =%3d ", Vec_PtrSize(vGroups) );
+ printf( "Variables: all =%4d ", nSuppAll );
+ printf( "pi =%4d ", nSuppPi );
+ printf( "po =%4d ", nSuppPo );
+ printf( "lo =%4d ", nSuppLo );
+ printf( "li =%4d ", nSuppLi );
+ printf( "and =%4d", nSuppAnd );
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4Cluster( Aig_Man_t * pAig, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int nBddMax, int fVerbose )
+{
+ DdManager * dd;
+ Vec_Int_t * vOrder, * vVars2Q;
+ Vec_Ptr_t * vParts, * vGroups;
+ DdNode * bTemp;
+ int i, nVarNum;
+
+ // create the BDD manager
+ vOrder = Llb_Nonlin4FindOrder( pAig, &nVarNum );
+ dd = Cudd_Init( nVarNum, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+// Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+
+ vVars2Q = Llb_Nonlin4FindVars2Q( dd, pAig, vOrder );
+ vParts = Llb_Nonlin4FindPartitions( dd, pAig, vOrder, 0 );
+
+ vGroups = Llb_Nonlin4Group( dd, vParts, vVars2Q, nBddMax );
+ Vec_IntFree( vVars2Q );
+
+ Vec_PtrForEachEntry( DdNode *, vParts, bTemp, i )
+ Cudd_RecursiveDeref( dd, bTemp );
+ Vec_PtrFree( vParts );
+
+
+// if ( fVerbose )
+ Llb_Nonlin4PrintSuppProfile( dd, pAig, vOrder, vGroups );
+ if ( fVerbose )
+ printf( "Before reordering\n" );
+ if ( fVerbose )
+ Llb_Nonlin4PrintGroups( dd, pAig, vOrder, vGroups );
+
+// Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 );
+// printf( "After reordering\n" );
+// Llb_Nonlin4PrintGroups( dd, pAig, vOrder, vGroups );
+
+ if ( pvOrder )
+ *pvOrder = vOrder;
+ else
+ Vec_IntFree( vOrder );
+
+ if ( pvGroups )
+ *pvGroups = vGroups;
+ else
+ {
+ Vec_PtrForEachEntry( DdNode *, vGroups, bTemp, i )
+ Cudd_RecursiveDeref( dd, bTemp );
+ Vec_PtrFree( vGroups );
+ }
+
+ if ( pdd )
+ *pdd = dd;
+ else
+ Extra_StopManager( dd );
+// Cudd_Quit( dd );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/llb/llb4Image.c b/src/proof/llb/llb4Image.c
new file mode 100644
index 00000000..91eb62f8
--- /dev/null
+++ b/src/proof/llb/llb4Image.c
@@ -0,0 +1,861 @@
+/**CFile****************************************************************
+
+ FileName [llb3Image.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Computes image using partitioned structure.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb3Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Llb_Var_t_ Llb_Var_t;
+struct Llb_Var_t_
+{
+ int iVar; // variable number
+ int nScore; // variable score
+ Vec_Int_t * vParts; // partitions
+};
+
+typedef struct Llb_Prt_t_ Llb_Prt_t;
+struct Llb_Prt_t_
+{
+ int iPart; // partition number
+ int nSize; // the number of BDD nodes
+ DdNode * bFunc; // the partition
+ Vec_Int_t * vVars; // support
+};
+
+typedef struct Llb_Mgr_t_ Llb_Mgr_t;
+struct Llb_Mgr_t_
+{
+ DdManager * dd; // working BDD manager
+ Vec_Int_t * vVars2Q; // variables to quantify
+ int nSizeMax; // maximum size of the cluster
+ // internal
+ Llb_Prt_t ** pParts; // partitions
+ Llb_Var_t ** pVars; // variables
+ int iPartFree; // next free partition
+ int nVars; // the number of BDD variables
+ int nSuppMax; // maximum support size
+ // temporary
+ int * pSupp; // temporary support storage
+};
+
+static inline Llb_Var_t * Llb_MgrVar( Llb_Mgr_t * p, int i ) { return p->pVars[i]; }
+static inline Llb_Prt_t * Llb_MgrPart( Llb_Mgr_t * p, int i ) { return p->pParts[i]; }
+
+// iterator over vars
+#define Llb_MgrForEachVar( p, pVar, i ) \
+ for ( i = 0; (i < p->nVars) && (((pVar) = Llb_MgrVar(p, i)), 1); i++ ) if ( pVar == NULL ) {} else
+// iterator over parts
+#define Llb_MgrForEachPart( p, pPart, i ) \
+ for ( i = 0; (i < p->iPartFree) && (((pPart) = Llb_MgrPart(p, i)), 1); i++ ) if ( pPart == NULL ) {} else
+
+// iterator over vars of one partition
+#define Llb_PartForEachVar( p, pPart, pVar, i ) \
+ for ( i = 0; (i < Vec_IntSize(pPart->vVars)) && (((pVar) = Llb_MgrVar(p, Vec_IntEntry(pPart->vVars,i))), 1); i++ )
+// iterator over parts of one variable
+#define Llb_VarForEachPart( p, pVar, pPart, i ) \
+ for ( i = 0; (i < Vec_IntSize(pVar->vParts)) && (((pPart) = Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,i))), 1); i++ )
+
+// statistics
+//int timeBuild, timeAndEx, timeOther;
+//int nSuppMax;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Removes one variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4RemoveVar( Llb_Mgr_t * p, Llb_Var_t * pVar )
+{
+ assert( p->pVars[pVar->iVar] == pVar );
+ p->pVars[pVar->iVar] = NULL;
+ Vec_IntFree( pVar->vParts );
+ ABC_FREE( pVar );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes one partition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4RemovePart( Llb_Mgr_t * p, Llb_Prt_t * pPart )
+{
+//printf( "Removing %d\n", pPart->iPart );
+ assert( p->pParts[pPart->iPart] == pPart );
+ p->pParts[pPart->iPart] = NULL;
+ Vec_IntFree( pPart->vVars );
+ Cudd_RecursiveDeref( p->dd, pPart->bFunc );
+ ABC_FREE( pPart );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create cube with singleton variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_Nonlin4CreateCube1( Llb_Mgr_t * p, Llb_Prt_t * pPart )
+{
+ DdNode * bCube, * bTemp;
+ Llb_Var_t * pVar;
+ int i, TimeStop;
+ TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
+ bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube );
+ Llb_PartForEachVar( p, pPart, pVar, i )
+ {
+ assert( Vec_IntSize(pVar->vParts) > 0 );
+ if ( Vec_IntSize(pVar->vParts) != 1 )
+ continue;
+ assert( Vec_IntEntry(pVar->vParts, 0) == pPart->iPart );
+ bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ Cudd_Deref( bCube );
+ p->dd->TimeStop = TimeStop;
+ return bCube;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Create cube of variables appearing only in two partitions.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_Nonlin4CreateCube2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 )
+{
+ DdNode * bCube, * bTemp;
+ Llb_Var_t * pVar;
+ int i, TimeStop;
+ TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0;
+ bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube );
+ Llb_PartForEachVar( p, pPart1, pVar, i )
+ {
+ assert( Vec_IntSize(pVar->vParts) > 0 );
+ if ( Vec_IntSize(pVar->vParts) != 2 )
+ continue;
+ if ( (Vec_IntEntry(pVar->vParts, 0) == pPart1->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart2->iPart) ||
+ (Vec_IntEntry(pVar->vParts, 0) == pPart2->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart1->iPart) )
+ {
+ bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+ }
+ Cudd_Deref( bCube );
+ p->dd->TimeStop = TimeStop;
+ return bCube;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if partition has singleton variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_Nonlin4HasSingletonVars( Llb_Mgr_t * p, Llb_Prt_t * pPart )
+{
+ Llb_Var_t * pVar;
+ int i;
+ Llb_PartForEachVar( p, pPart, pVar, i )
+ if ( Vec_IntSize(pVar->vParts) == 1 )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if partition has singleton variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4Print( Llb_Mgr_t * p )
+{
+ Llb_Prt_t * pPart;
+ Llb_Var_t * pVar;
+ int i, k;
+ printf( "\n" );
+ Llb_MgrForEachVar( p, pVar, i )
+ {
+ printf( "Var %3d : ", i );
+ Llb_VarForEachPart( p, pVar, pPart, k )
+ printf( "%d ", pPart->iPart );
+ printf( "\n" );
+ }
+ Llb_MgrForEachPart( p, pPart, i )
+ {
+ printf( "Part %3d : ", i );
+ Llb_PartForEachVar( p, pPart, pVar, k )
+ printf( "%d ", pVar->iVar );
+ printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Quantifies singles belonging to one partition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_Nonlin4Quantify1( Llb_Mgr_t * p, Llb_Prt_t * pPart )
+{
+ Llb_Var_t * pVar;
+ Llb_Prt_t * pTemp;
+ Vec_Ptr_t * vSingles;
+ DdNode * bCube, * bTemp;
+ int i, RetValue, nSizeNew;
+ // create cube to be quantified
+ bCube = Llb_Nonlin4CreateCube1( p, pPart ); Cudd_Ref( bCube );
+// assert( !Cudd_IsConstant(bCube) );
+ // derive new function
+ pPart->bFunc = Cudd_bddExistAbstract( p->dd, bTemp = pPart->bFunc, bCube ); Cudd_Ref( pPart->bFunc );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ Cudd_RecursiveDeref( p->dd, bCube );
+ // get support
+ vSingles = Vec_PtrAlloc( 0 );
+ nSizeNew = Cudd_DagSize(pPart->bFunc);
+ Extra_SupportArray( p->dd, pPart->bFunc, p->pSupp );
+ Llb_PartForEachVar( p, pPart, pVar, i )
+ if ( p->pSupp[pVar->iVar] )
+ {
+ assert( Vec_IntSize(pVar->vParts) > 1 );
+ pVar->nScore -= pPart->nSize - nSizeNew;
+ }
+ else
+ {
+ RetValue = Vec_IntRemove( pVar->vParts, pPart->iPart );
+ assert( RetValue );
+ pVar->nScore -= pPart->nSize;
+ if ( Vec_IntSize(pVar->vParts) == 0 )
+ Llb_Nonlin4RemoveVar( p, pVar );
+ else if ( Vec_IntSize(pVar->vParts) == 1 )
+ Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) );
+ }
+
+ // update partition
+ pPart->nSize = nSizeNew;
+ Vec_IntClear( pPart->vVars );
+ for ( i = 0; i < p->nVars; i++ )
+ if ( p->pSupp[i] && Vec_IntEntry(p->vVars2Q, i) )
+ Vec_IntPush( pPart->vVars, i );
+ // remove other variables
+ Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i )
+ Llb_Nonlin4Quantify1( p, pTemp );
+ Vec_PtrFree( vSingles );
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Quantifies singles belonging to one partition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_Nonlin4Quantify2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 )
+{
+ int fVerbose = 0;
+ Llb_Var_t * pVar;
+ Llb_Prt_t * pTemp;
+ Vec_Ptr_t * vSingles;
+ DdNode * bCube, * bFunc;
+ int i, RetValue, nSuppSize;
+ int iPart1 = pPart1->iPart;
+ int iPart2 = pPart2->iPart;
+ int liveBeg, liveEnd;
+
+ // create cube to be quantified
+ bCube = Llb_Nonlin4CreateCube2( p, pPart1, pPart2 ); Cudd_Ref( bCube );
+
+//printf( "Quantifying " ); Extra_bddPrintSupport( p->dd, bCube ); printf( "\n" );
+
+if ( fVerbose )
+{
+printf( "\n" );
+printf( "\n" );
+Llb_Nonlin4Print( p );
+printf( "Conjoining partitions %d and %d.\n", pPart1->iPart, pPart2->iPart );
+Extra_bddPrintSupport( p->dd, bCube ); printf( "\n" );
+}
+liveBeg = p->dd->keys - p->dd->dead;
+ bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube );
+liveEnd = p->dd->keys - p->dd->dead;
+//printf( "%d ", liveEnd-liveBeg );
+
+ if ( bFunc == NULL )
+ {
+ Cudd_RecursiveDeref( p->dd, bCube );
+ return 0;
+ }
+ Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( p->dd, bCube );
+
+//printf( "Creating part %d ", p->iPartFree ); Extra_bddPrintSupport( p->dd, bFunc ); printf( "\n" );
+
+//printf( "Creating %d\n", p->iPartFree );
+
+ // create new partition
+ pTemp = p->pParts[p->iPartFree] = ABC_CALLOC( Llb_Prt_t, 1 );
+ pTemp->iPart = p->iPartFree++;
+ pTemp->nSize = Cudd_DagSize(bFunc);
+ pTemp->bFunc = bFunc;
+ pTemp->vVars = Vec_IntAlloc( 8 );
+ // update variables
+ Llb_PartForEachVar( p, pPart1, pVar, i )
+ {
+ RetValue = Vec_IntRemove( pVar->vParts, pPart1->iPart );
+ assert( RetValue );
+ pVar->nScore -= pPart1->nSize;
+ }
+ // update variables
+ Llb_PartForEachVar( p, pPart2, pVar, i )
+ {
+ RetValue = Vec_IntRemove( pVar->vParts, pPart2->iPart );
+ assert( RetValue );
+ pVar->nScore -= pPart2->nSize;
+ }
+ // add variables to the new partition
+ nSuppSize = 0;
+ Extra_SupportArray( p->dd, bFunc, p->pSupp );
+ for ( i = 0; i < p->nVars; i++ )
+ {
+ nSuppSize += p->pSupp[i];
+ if ( p->pSupp[i] && Vec_IntEntry(p->vVars2Q, i) )
+ {
+ pVar = Llb_MgrVar( p, i );
+ pVar->nScore += pTemp->nSize;
+ Vec_IntPush( pVar->vParts, pTemp->iPart );
+ Vec_IntPush( pTemp->vVars, i );
+ }
+ }
+ p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize );
+ // remove variables and collect partitions with singleton variables
+ vSingles = Vec_PtrAlloc( 0 );
+ Llb_PartForEachVar( p, pPart1, pVar, i )
+ {
+ if ( Vec_IntSize(pVar->vParts) == 0 )
+ Llb_Nonlin4RemoveVar( p, pVar );
+ else if ( Vec_IntSize(pVar->vParts) == 1 )
+ {
+ if ( fVerbose )
+ printf( "Adding partition %d because of var %d.\n",
+ Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar );
+ Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) );
+ }
+ }
+ Llb_PartForEachVar( p, pPart2, pVar, i )
+ {
+ if ( pVar == NULL )
+ continue;
+ if ( Vec_IntSize(pVar->vParts) == 0 )
+ Llb_Nonlin4RemoveVar( p, pVar );
+ else if ( Vec_IntSize(pVar->vParts) == 1 )
+ {
+ if ( fVerbose )
+ printf( "Adding partition %d because of var %d.\n",
+ Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar );
+ Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) );
+ }
+ }
+ // remove partitions
+ Llb_Nonlin4RemovePart( p, pPart1 );
+ Llb_Nonlin4RemovePart( p, pPart2 );
+ // remove other variables
+if ( fVerbose )
+Llb_Nonlin4Print( p );
+ Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i )
+ {
+if ( fVerbose )
+printf( "Updating partitiong %d with singlton vars.\n", pTemp->iPart );
+ Llb_Nonlin4Quantify1( p, pTemp );
+ }
+if ( fVerbose )
+Llb_Nonlin4Print( p );
+ Vec_PtrFree( vSingles );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes volume of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4CutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
+{
+ if ( Aig_ObjIsTravIdCurrent(p, pObj) )
+ return;
+ Aig_ObjSetTravIdCurrent(p, pObj);
+ if ( Saig_ObjIsLi(p, pObj) )
+ {
+ Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes);
+ return;
+ }
+ if ( Aig_ObjIsConst1(pObj) )
+ return;
+ assert( Aig_ObjIsNode(pObj) );
+ Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes);
+ Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes);
+ Vec_PtrPush( vNodes, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes volume of the cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_Nonlin4CutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper )
+{
+ Vec_Ptr_t * vNodes;
+ Aig_Obj_t * pObj;
+ int i;
+ // mark the lower cut with the traversal ID
+ Aig_ManIncrementTravId(p);
+ Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i )
+ Aig_ObjSetTravIdCurrent( p, pObj );
+ // count the upper cut
+ vNodes = Vec_PtrAlloc( 100 );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i )
+ Llb_Nonlin4CutNodes_rec( p, pObj, vNodes );
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts non-linear quantification scheduling.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4AddPair( Llb_Mgr_t * p, int iPart, int iVar )
+{
+ if ( p->pVars[iVar] == NULL )
+ {
+ p->pVars[iVar] = ABC_CALLOC( Llb_Var_t, 1 );
+ p->pVars[iVar]->iVar = iVar;
+ p->pVars[iVar]->nScore = 0;
+ p->pVars[iVar]->vParts = Vec_IntAlloc( 8 );
+ }
+ Vec_IntPush( p->pVars[iVar]->vParts, iPart );
+ Vec_IntPush( p->pParts[iPart]->vVars, iVar );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts non-linear quantification scheduling.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4AddPartition( Llb_Mgr_t * p, int i, DdNode * bFunc )
+{
+ int k, nSuppSize;
+ assert( !Cudd_IsConstant(bFunc) );
+//printf( "Creating init %d\n", i );
+ // create partition
+ p->pParts[i] = ABC_CALLOC( Llb_Prt_t, 1 );
+ p->pParts[i]->iPart = i;
+ p->pParts[i]->bFunc = bFunc; Cudd_Ref( bFunc );
+ p->pParts[i]->vVars = Vec_IntAlloc( 8 );
+ // add support dependencies
+ nSuppSize = 0;
+ Extra_SupportArray( p->dd, bFunc, p->pSupp );
+ for ( k = 0; k < p->nVars; k++ )
+ {
+ nSuppSize += p->pSupp[k];
+ if ( p->pSupp[k] && Vec_IntEntry(p->vVars2Q, k) )
+ Llb_Nonlin4AddPair( p, i, k );
+ }
+ p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks that each var appears in at least one partition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+**********************************************************************/
+void Llb_Nonlin4CheckVars( Llb_Mgr_t * p )
+{
+ Llb_Var_t * pVar;
+ int i;
+ Llb_MgrForEachVar( p, pVar, i )
+ assert( Vec_IntSize(pVar->vParts) > 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find next partition to quantify]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_Nonlin4NextPartitions( Llb_Mgr_t * p, Llb_Prt_t ** ppPart1, Llb_Prt_t ** ppPart2 )
+{
+ Llb_Var_t * pVar, * pVarBest = NULL;
+ Llb_Prt_t * pPart, * pPart1Best = NULL, * pPart2Best = NULL;
+ int i;
+ Llb_Nonlin4CheckVars( p );
+ // find variable with minimum score
+ Llb_MgrForEachVar( p, pVar, i )
+ {
+ if ( p->nSizeMax && pVar->nScore > p->nSizeMax )
+ continue;
+// if ( pVarBest == NULL || Vec_IntSize(pVarBest->vParts) * pVarBest->nScore > Vec_IntSize(pVar->vParts) * pVar->nScore )
+ if ( pVarBest == NULL || pVarBest->nScore > pVar->nScore )
+ pVarBest = pVar;
+// printf( "%d ", pVar->nScore );
+ }
+//printf( "\n" );
+ if ( pVarBest == NULL )
+ return 0;
+ // find two partitions with minimum size
+ Llb_VarForEachPart( p, pVarBest, pPart, i )
+ {
+ if ( pPart1Best == NULL )
+ pPart1Best = pPart;
+ else if ( pPart2Best == NULL )
+ pPart2Best = pPart;
+ else if ( pPart1Best->nSize > pPart->nSize || pPart2Best->nSize > pPart->nSize )
+ {
+ if ( pPart1Best->nSize > pPart2Best->nSize )
+ pPart1Best = pPart;
+ else
+ pPart2Best = pPart;
+ }
+ }
+//printf( "Selecting %d and parts %d and %d\n", pVarBest->iVar, pPart1Best->nSize, pPart2Best->nSize );
+//Extra_bddPrintSupport( p->dd, pPart1Best->bFunc ); printf( "\n" );
+//Extra_bddPrintSupport( p->dd, pPart2Best->bFunc ); printf( "\n" );
+
+ *ppPart1 = pPart1Best;
+ *ppPart2 = pPart2Best;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recomputes scores after variable reordering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4RecomputeScores( Llb_Mgr_t * p )
+{
+ Llb_Prt_t * pPart;
+ Llb_Var_t * pVar;
+ int i, k;
+ Llb_MgrForEachPart( p, pPart, i )
+ pPart->nSize = Cudd_DagSize(pPart->bFunc);
+ Llb_MgrForEachVar( p, pVar, i )
+ {
+ pVar->nScore = 0;
+ Llb_VarForEachPart( p, pVar, pPart, k )
+ pVar->nScore += pPart->nSize;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recomputes scores after variable reordering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4VerifyScores( Llb_Mgr_t * p )
+{
+ Llb_Prt_t * pPart;
+ Llb_Var_t * pVar;
+ int i, k, nScore;
+ Llb_MgrForEachPart( p, pPart, i )
+ assert( pPart->nSize == Cudd_DagSize(pPart->bFunc) );
+ Llb_MgrForEachVar( p, pVar, i )
+ {
+ nScore = 0;
+ Llb_VarForEachPart( p, pVar, pPart, k )
+ nScore += pPart->nSize;
+ assert( nScore == pVar->nScore );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts non-linear quantification scheduling.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Mgr_t * Llb_Nonlin4Alloc( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q, int nSizeMax )
+{
+ Llb_Mgr_t * p;
+ DdNode * bFunc;
+ int i;
+ p = ABC_CALLOC( Llb_Mgr_t, 1 );
+ p->dd = dd;
+ p->nSizeMax = nSizeMax;
+ p->vVars2Q = vVars2Q;
+ p->nVars = Cudd_ReadSize(dd);
+ p->iPartFree = Vec_PtrSize(vParts);
+ p->pVars = ABC_CALLOC( Llb_Var_t *, p->nVars );
+ p->pParts = ABC_CALLOC( Llb_Prt_t *, 2 * p->iPartFree + 2 );
+ p->pSupp = ABC_ALLOC( int, Cudd_ReadSize(dd) );
+ // add pairs (refs are consumed inside)
+ Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i )
+ Llb_Nonlin4AddPartition( p, i, bFunc );
+ // add partition
+ if ( bCurrent )
+ Llb_Nonlin4AddPartition( p, p->iPartFree++, bCurrent );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops non-linear quantification scheduling.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4Free( Llb_Mgr_t * p )
+{
+ Llb_Prt_t * pPart;
+ Llb_Var_t * pVar;
+ int i;
+ Llb_MgrForEachVar( p, pVar, i )
+ Llb_Nonlin4RemoveVar( p, pVar );
+ Llb_MgrForEachPart( p, pPart, i )
+ Llb_Nonlin4RemovePart( p, pPart );
+ ABC_FREE( p->pVars );
+ ABC_FREE( p->pParts );
+ ABC_FREE( p->pSupp );
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_Nonlin4Image( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q )
+{
+ Llb_Prt_t * pPart, * pPart1, * pPart2;
+ Llb_Mgr_t * p;
+ DdNode * bFunc, * bTemp;
+ int i, nReorders;
+ // start the manager
+ p = Llb_Nonlin4Alloc( dd, vParts, bCurrent, vVars2Q, 0 );
+ // remove singles
+ Llb_MgrForEachPart( p, pPart, i )
+ if ( Llb_Nonlin4HasSingletonVars(p, pPart) )
+ Llb_Nonlin4Quantify1( p, pPart );
+ // compute scores
+ Llb_Nonlin4RecomputeScores( p );
+ // iteratively quantify variables
+ while ( Llb_Nonlin4NextPartitions(p, &pPart1, &pPart2) )
+ {
+ nReorders = Cudd_ReadReorderings(dd);
+ if ( !Llb_Nonlin4Quantify2( p, pPart1, pPart2 ) )
+ {
+ Llb_Nonlin4Free( p );
+ return NULL;
+ }
+ if ( nReorders < Cudd_ReadReorderings(dd) )
+ Llb_Nonlin4RecomputeScores( p );
+// else
+// Llb_Nonlin4VerifyScores( p );
+ }
+ // load partitions
+ bFunc = Cudd_ReadOne(p->dd); Cudd_Ref( bFunc );
+ Llb_MgrForEachPart( p, pPart, i )
+ {
+ bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc ); Cudd_Ref( bFunc );
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ }
+// nSuppMax = p->nSuppMax;
+ Llb_Nonlin4Free( p );
+//printf( "\n" );
+ // return
+ Cudd_Deref( bFunc );
+ return bFunc;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_Nonlin4Group( DdManager * dd, Vec_Ptr_t * vParts, Vec_Int_t * vVars2Q, int nSizeMax )
+{
+ Vec_Ptr_t * vGroups;
+ Llb_Prt_t * pPart, * pPart1, * pPart2;
+ Llb_Mgr_t * p;
+ int i, nReorders, clk = clock();
+ // start the manager
+ p = Llb_Nonlin4Alloc( dd, vParts, NULL, vVars2Q, nSizeMax );
+ // remove singles
+ Llb_MgrForEachPart( p, pPart, i )
+ if ( Llb_Nonlin4HasSingletonVars(p, pPart) )
+ Llb_Nonlin4Quantify1( p, pPart );
+ // compute scores
+ Llb_Nonlin4RecomputeScores( p );
+ // iteratively quantify variables
+ while ( Llb_Nonlin4NextPartitions(p, &pPart1, &pPart2) )
+ {
+ nReorders = Cudd_ReadReorderings(dd);
+ if ( !Llb_Nonlin4Quantify2( p, pPart1, pPart2 ) )
+ {
+ Llb_Nonlin4Free( p );
+ return NULL;
+ }
+ if ( nReorders < Cudd_ReadReorderings(dd) )
+ Llb_Nonlin4RecomputeScores( p );
+// else
+// Llb_Nonlin4VerifyScores( p );
+ }
+ // load partitions
+ vGroups = Vec_PtrAlloc( 1000 );
+ Llb_MgrForEachPart( p, pPart, i )
+ {
+//printf( "Iteration %d ", pPart->iPart );
+ if ( Cudd_IsConstant(pPart->bFunc) )
+ {
+//printf( "Constant\n" );
+ assert( !Cudd_IsComplement(pPart->bFunc) );
+ continue;
+ }
+//printf( "\n" );
+ Vec_PtrPush( vGroups, pPart->bFunc );
+ Cudd_Ref( pPart->bFunc );
+//printf( "Part %d ", pPart->iPart );
+//Extra_bddPrintSupport( p->dd, pPart->bFunc ); printf( "\n" );
+ }
+ Llb_Nonlin4Free( p );
+//Abc_PrintTime( 1, "Reparametrization time", clock() - clk );
+ return vGroups;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/llb/llb4Map.c b/src/proof/llb/llb4Map.c
new file mode 100644
index 00000000..b1442699
--- /dev/null
+++ b/src/proof/llb/llb4Map.c
@@ -0,0 +1,123 @@
+/**CFile****************************************************************
+
+ FileName [llb2Map.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Non-linear quantification scheduling.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb2Map.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+#include "src/base/abc/abc.h"
+#include "src/map/if/if.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Returns internal nodes used in the mapping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_AigMap( Aig_Man_t * pAig, int nLutSize, int nLutMin )
+{
+ extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan );
+ extern If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars );
+ extern void Gia_ManSetIfParsDefault( If_Par_t * pPars );
+ If_Par_t Pars, * pPars = &Pars;
+ If_Man_t * pIfMan;
+ If_Obj_t * pAnd;
+ Abc_Ntk_t * pNtk;
+ Abc_Obj_t * pNode;
+ Vec_Int_t * vNodes;
+ Aig_Obj_t * pObj;
+ int i;
+
+ // create ABC network
+ pNtk = Abc_NtkFromAigPhase( pAig );
+ assert( Abc_NtkIsStrash(pNtk) );
+
+ // derive mapping parameters
+ Gia_ManSetIfParsDefault( pPars );
+ pPars->nLutSize = nLutSize;
+
+ // get timing information
+ pPars->pTimesArr = Abc_NtkGetCiArrivalFloats(pNtk);
+ pPars->pTimesReq = NULL;
+
+ // perform LUT mapping
+ pIfMan = Abc_NtkToIf( pNtk, pPars );
+ if ( pIfMan == NULL )
+ {
+ Abc_NtkDelete( pNtk );
+ return NULL;
+ }
+ if ( !If_ManPerformMapping( pIfMan ) )
+ {
+ Abc_NtkDelete( pNtk );
+ If_ManStop( pIfMan );
+ return NULL;
+ }
+
+ // mark nodes in the AIG used in the mapping
+ Aig_ManCleanMarkA( pAig );
+ Aig_ManForEachNode( pAig, pObj, i )
+ {
+ pNode = (Abc_Obj_t *)pObj->pData;
+ if ( pNode == NULL )
+ continue;
+ pAnd = (If_Obj_t *)pNode->pCopy;
+ if ( pAnd == NULL )
+ continue;
+ if ( pAnd->nRefs > 0 && (int)If_ObjCutBest(pAnd)->nLeaves >= nLutMin )
+ pObj->fMarkA = 1;
+ }
+ Abc_NtkDelete( pNtk );
+ If_ManStop( pIfMan );
+
+ // unmark flop drivers
+ Saig_ManForEachLi( pAig, pObj, i )
+ Aig_ObjFanin0(pObj)->fMarkA = 0;
+
+ // collect mapping
+ vNodes = Vec_IntAlloc( 100 );
+ Aig_ManForEachNode( pAig, pObj, i )
+ if ( pObj->fMarkA )
+ Vec_IntPush( vNodes, Aig_ObjId(pObj) );
+ Aig_ManCleanMarkA( pAig );
+ return vNodes;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/llb/llb4Nonlin.c b/src/proof/llb/llb4Nonlin.c
new file mode 100644
index 00000000..33c6b3f7
--- /dev/null
+++ b/src/proof/llb/llb4Nonlin.c
@@ -0,0 +1,1080 @@
+/**CFile****************************************************************
+
+ FileName [llb2Nonlin.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Non-linear quantification scheduling.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb2Nonlin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Llb_Mnx_t_ Llb_Mnx_t;
+struct Llb_Mnx_t_
+{
+ // user info
+ Aig_Man_t * pAig; // AIG manager
+ Gia_ParLlb_t * pPars; // parameters
+
+ // intermediate BDDs
+ DdManager * dd; // BDD manager
+ DdNode * bBad; // bad states in terms of CIs
+ DdNode * bReached; // reached states
+ DdNode * bCurrent; // from states
+ DdNode * bNext; // to states
+ Vec_Ptr_t * vRings; // onion rings in ddR
+ Vec_Ptr_t * vRoots; // BDDs for partitions
+
+ // structural info
+ Vec_Int_t * vOrder; // for each object ID, its BDD variable number or -1
+ Vec_Int_t * vVars2Q; // 1 if variable is quantifiable; 0 othervise
+
+ int timeImage;
+ int timeRemap;
+ int timeReo;
+ int timeOther;
+ int timeTotal;
+};
+
+//extern int timeBuild, timeAndEx, timeOther;
+//extern int nSuppMax;
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes bad in working manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_Nonlin4ComputeBad( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder )
+{
+ Vec_Ptr_t * vNodes;
+ DdNode * bBdd, * bBdd0, * bBdd1, * bTemp, * bResult, * bCube;
+ Aig_Obj_t * pObj;
+ int i;
+ Aig_ManCleanData( pAig );
+ // assign elementary variables
+ Aig_ManConst1(pAig)->pData = Cudd_ReadOne(dd);
+ Aig_ManForEachPi( pAig, pObj, i )
+ pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+ // compute internal nodes
+ vNodes = Aig_ManDfsNodes( pAig, (Aig_Obj_t **)Vec_PtrArray(pAig->vPos), Saig_ManPoNum(pAig) );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+ {
+ if ( !Aig_ObjIsNode(pObj) )
+ continue;
+ bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+ bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 );
+ if ( bBdd == NULL )
+ {
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+ if ( Aig_ObjIsNode(pObj) && pObj->pData != NULL )
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+ Vec_PtrFree( vNodes );
+ return NULL;
+ }
+ Cudd_Ref( bBdd );
+ pObj->pData = bBdd;
+ }
+ // quantify PIs of each PO
+ bResult = Cudd_ReadLogicZero( dd ); Cudd_Ref( bResult );
+ Saig_ManForEachPo( pAig, pObj, i )
+ {
+ bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bResult = Cudd_bddOr( dd, bTemp = bResult, bBdd0 );
+ if ( bResult == NULL )
+ {
+ Cudd_RecursiveDeref( dd, bTemp );
+ break;
+ }
+ Cudd_Ref( bResult );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ // deref
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
+ if ( Aig_ObjIsNode(pObj) && pObj->pData != NULL )
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+ Vec_PtrFree( vNodes );
+ if ( bResult )
+ {
+ bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube );
+ Saig_ManForEachPi( pAig, pObj, i )
+ {
+ bCube = Cudd_bddAnd( dd, bTemp = bCube, (DdNode *)pObj->pData ); Cudd_Ref( bCube );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ bResult = Cudd_bddExistAbstract( dd, bTemp = bResult, bCube ); Cudd_Ref( bResult );
+ Cudd_RecursiveDeref( dd, bTemp );
+ Cudd_RecursiveDeref( dd, bCube );
+ Cudd_Deref( bResult );
+ }
+//if ( bResult )
+//printf( "Bad state = %d.\n", Cudd_DagSize(bResult) );
+ return bResult;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives BDDs for the partitions.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_Nonlin4DerivePartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder )
+{
+ Vec_Ptr_t * vRoots;
+ Aig_Obj_t * pObj;
+ DdNode * bBdd, * bBdd0, * bBdd1, * bPart;
+ int i;
+ Aig_ManCleanData( pAig );
+ // assign elementary variables
+ Aig_ManConst1(pAig)->pData = Cudd_ReadOne(dd);
+ Aig_ManForEachPi( pAig, pObj, i )
+ pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+ Aig_ManForEachNode( pAig, pObj, i )
+ if ( Llb_ObjBddVar(vOrder, pObj) >= 0 )
+ {
+ pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+ Cudd_Ref( (DdNode *)pObj->pData );
+ }
+ Saig_ManForEachLi( pAig, pObj, i )
+ pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+ // compute intermediate BDDs
+ vRoots = Vec_PtrAlloc( 100 );
+ Aig_ManForEachNode( pAig, pObj, i )
+ {
+ bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+ bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 );
+ if ( bBdd == NULL )
+ goto finish;
+ Cudd_Ref( bBdd );
+ if ( pObj->pData == NULL )
+ {
+ pObj->pData = bBdd;
+ continue;
+ }
+ // create new partition
+ bPart = Cudd_bddXnor( dd, (DdNode *)pObj->pData, bBdd );
+ if ( bPart == NULL )
+ goto finish;
+ Cudd_Ref( bPart );
+ Cudd_RecursiveDeref( dd, bBdd );
+ Vec_PtrPush( vRoots, bPart );
+//printf( "%d ", Cudd_DagSize(bPart) );
+ }
+ // compute register output BDDs
+ Saig_ManForEachLi( pAig, pObj, i )
+ {
+ bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bPart = Cudd_bddXnor( dd, (DdNode *)pObj->pData, bBdd0 );
+ if ( bPart == NULL )
+ goto finish;
+ Cudd_Ref( bPart );
+ Vec_PtrPush( vRoots, bPart );
+//printf( "%d ", Cudd_DagSize(bPart) );
+ }
+//printf( "\n" );
+ Aig_ManForEachNode( pAig, pObj, i )
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+ return vRoots;
+ // early termination
+finish:
+ Aig_ManForEachNode( pAig, pObj, i )
+ if ( pObj->pData )
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+ Vec_PtrForEachEntry( DdNode *, vRoots, bPart, i )
+ Cudd_RecursiveDeref( dd, bPart );
+ Vec_PtrFree( vRoots );
+ return NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find simple variable ordering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_Nonlin4CreateOrderSimple( Aig_Man_t * pAig )
+{
+ Vec_Int_t * vOrder;
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) );
+ Aig_ManForEachPi( pAig, pObj, i )
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ );
+ Saig_ManForEachLi( pAig, pObj, i )
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ );
+ return vOrder;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find good static variable ordering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4CreateOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter )
+{
+ Aig_Obj_t * pFanin0, * pFanin1;
+ if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+ return;
+ Aig_ObjSetTravIdCurrent( pAig, pObj );
+ assert( Llb_ObjBddVar(vOrder, pObj) < 0 );
+ if ( Aig_ObjIsPi(pObj) )
+ {
+// if ( Saig_ObjIsLo(pAig, pObj) )
+// Vec_IntWriteEntry( vOrder, Aig_ObjId(Saig_ObjLoToLi(pAig, pObj)), (*pCounter)++ );
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ );
+ return;
+ }
+ // try fanins with higher level first
+ pFanin0 = Aig_ObjFanin0(pObj);
+ pFanin1 = Aig_ObjFanin1(pObj);
+// if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) )
+ if ( pFanin0->Level > pFanin1->Level )
+ {
+ Llb_Nonlin4CreateOrder_rec( pAig, pFanin0, vOrder, pCounter );
+ Llb_Nonlin4CreateOrder_rec( pAig, pFanin1, vOrder, pCounter );
+ }
+ else
+ {
+ Llb_Nonlin4CreateOrder_rec( pAig, pFanin1, vOrder, pCounter );
+ Llb_Nonlin4CreateOrder_rec( pAig, pFanin0, vOrder, pCounter );
+ }
+ if ( pObj->fMarkA )
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collect nodes with the given fanout count.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_Nonlin4CollectHighRefNodes( Aig_Man_t * pAig, int nFans )
+{
+ Vec_Int_t * vNodes;
+ Aig_Obj_t * pObj;
+ int i;
+ Aig_ManCleanMarkA( pAig );
+ Aig_ManForEachNode( pAig, pObj, i )
+ if ( Aig_ObjRefs(pObj) >= nFans )
+ pObj->fMarkA = 1;
+ // unmark flop drivers
+ Saig_ManForEachLi( pAig, pObj, i )
+ Aig_ObjFanin0(pObj)->fMarkA = 0;
+ // collect mapping
+ vNodes = Vec_IntAlloc( 100 );
+ Aig_ManForEachNode( pAig, pObj, i )
+ if ( pObj->fMarkA )
+ Vec_IntPush( vNodes, Aig_ObjId(pObj) );
+ Aig_ManCleanMarkA( pAig );
+ return vNodes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find good static variable ordering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_Nonlin4CreateOrder( Aig_Man_t * pAig )
+{
+ Vec_Int_t * vNodes = NULL;
+ Vec_Int_t * vOrder;
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+/*
+ // mark internal nodes to be used
+ Aig_ManCleanMarkA( pAig );
+ vNodes = Llb_Nonlin4CollectHighRefNodes( pAig, 4 );
+ Aig_ManForEachObjVec( vNodes, pAig, pObj, i )
+ pObj->fMarkA = 1;
+printf( "Techmapping added %d pivots.\n", Vec_IntSize(vNodes) );
+*/
+ // collect nodes in the order
+ vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) );
+ Aig_ManIncrementTravId( pAig );
+ Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) );
+ Saig_ManForEachLi( pAig, pObj, i )
+ {
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ );
+ Llb_Nonlin4CreateOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter );
+ }
+ Aig_ManForEachPi( pAig, pObj, i )
+ if ( Llb_ObjBddVar(vOrder, pObj) < 0 )
+ {
+// if ( Saig_ObjIsLo(pAig, pObj) )
+// Vec_IntWriteEntry( vOrder, Aig_ObjId(Saig_ObjLoToLi(pAig, pObj)), Counter++ );
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ );
+ }
+ assert( Counter <= Aig_ManPiNum(pAig) + Aig_ManRegNum(pAig) + (vNodes?Vec_IntSize(vNodes):0) );
+ Aig_ManCleanMarkA( pAig );
+ Vec_IntFreeP( &vNodes );
+ return vOrder;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Creates quantifiable varaibles for both types of traversal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_Nonlin4CreateVars2Q( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fBackward )
+{
+ Vec_Int_t * vVars2Q;
+ Aig_Obj_t * pObjLi, * pObjLo;
+ int i;
+ vVars2Q = Vec_IntAlloc( 0 );
+ Vec_IntFill( vVars2Q, Cudd_ReadSize(dd), 1 );
+ Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
+ Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, fBackward ? pObjLo : pObjLi), 0 );
+ return vVars2Q;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute initial state in terms of current state variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4SetupVarMap( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder )
+{
+ DdNode ** pVarsX, ** pVarsY;
+ Aig_Obj_t * pObjLo, * pObjLi;
+ int i;
+ pVarsX = ABC_ALLOC( DdNode *, Cudd_ReadSize(dd) );
+ pVarsY = ABC_ALLOC( DdNode *, Cudd_ReadSize(dd) );
+ Saig_ManForEachLiLo( pAig, pObjLo, pObjLi, i )
+ {
+ assert( Llb_ObjBddVar(vOrder, pObjLo) >= 0 );
+ assert( Llb_ObjBddVar(vOrder, pObjLi) >= 0 );
+ pVarsX[i] = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLo) );
+ pVarsY[i] = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLi) );
+ }
+ Cudd_SetVarMap( dd, pVarsX, pVarsY, Aig_ManRegNum(pAig) );
+ ABC_FREE( pVarsX );
+ ABC_FREE( pVarsY );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute initial state in terms of current state variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_Nonlin4ComputeInitState( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fBackward )
+{
+ Aig_Obj_t * pObjLi, * pObjLo;
+ DdNode * bRes, * bVar, * bTemp;
+ int i, TimeStop;
+ TimeStop = dd->TimeStop; dd->TimeStop = 0;
+ bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes );
+ Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
+ {
+ bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, fBackward? pObjLi : pObjLo) );
+ bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bRes );
+ dd->TimeStop = TimeStop;
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute initial state in terms of current state variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_Nonlin4ComputeCube( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, char * pValues, int Flag )
+{
+ Aig_Obj_t * pObjLo, * pObjLi, * pObjTemp;
+ DdNode * bRes, * bVar, * bTemp;
+ int i, TimeStop;
+ TimeStop = dd->TimeStop; dd->TimeStop = 0;
+ bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes );
+ Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
+ {
+ if ( Flag )
+ pObjTemp = pObjLo, pObjLo = pObjLi, pObjLi = pObjTemp;
+ // get the correspoding flop input variable
+ bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLi) );
+ if ( pValues[Llb_ObjBddVar(vOrder, pObjLo)] != 1 )
+ bVar = Cudd_Not(bVar);
+ // create cube
+ bRes = Cudd_bddAnd( dd, bTemp = bRes, bVar ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bRes );
+ dd->TimeStop = TimeStop;
+ return bRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute initial state in terms of current state variables.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4RecordState( Aig_Man_t * pAig, Vec_Int_t * vOrder, unsigned * pState, char * pValues, int fBackward )
+{
+ Aig_Obj_t * pObjLo, * pObjLi;
+ int i;
+ Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
+ if ( pValues[Llb_ObjBddVar(vOrder, fBackward? pObjLi : pObjLo)] == 1 )
+ Abc_InfoSetBit( pState, i );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Multiply every partition by the cube.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_Nonlin4Multiply( DdManager * dd, DdNode * bCube, Vec_Ptr_t * vParts )
+{
+ Vec_Ptr_t * vNew;
+ DdNode * bTemp, * bFunc;
+ int i;
+ vNew = Vec_PtrAlloc( Vec_PtrSize(vParts) );
+ Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i )
+ {
+ bTemp = Cudd_bddAnd( dd, bFunc, bCube ); Cudd_Ref( bTemp );
+ Vec_PtrPush( vNew, bTemp );
+ }
+ return vNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Multiply every partition by the cube.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4Deref( DdManager * dd, Vec_Ptr_t * vParts )
+{
+ DdNode * bFunc;
+ int i;
+ Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i )
+ Cudd_RecursiveDeref( dd, bFunc );
+ Vec_PtrFree( vParts );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives counter-example by backward reachability.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_Nonlin4DeriveCex( Llb_Mnx_t * p, int fBackward, int fVerbose )
+{
+ Vec_Int_t * vVars2Q;
+ Vec_Ptr_t * vStates, * vRootsNew;
+ Aig_Obj_t * pObj;
+ DdNode * bState, * bImage, * bOneCube, * bRing;
+ int i, v, RetValue, clk = clock();
+ char * pValues;
+ assert( Vec_PtrSize(p->vRings) > 0 );
+ // disable the timeout
+ p->dd->TimeStop = 0;
+
+ // start the state set
+ vStates = Vec_PtrAllocSimInfo( Vec_PtrSize(p->vRings), Abc_BitWordNum(Aig_ManRegNum(p->pAig)) );
+ Vec_PtrCleanSimInfo( vStates, 0, Abc_BitWordNum(Aig_ManRegNum(p->pAig)) );
+ if ( fBackward )
+ Vec_PtrReverseOrder( vStates );
+
+ // get the last cube
+ pValues = ABC_ALLOC( char, Cudd_ReadSize(p->dd) );
+ bOneCube = Cudd_bddIntersect( p->dd, (DdNode *)Vec_PtrEntryLast(p->vRings), p->bBad ); Cudd_Ref( bOneCube );
+ RetValue = Cudd_bddPickOneCube( p->dd, bOneCube, pValues );
+ Cudd_RecursiveDeref( p->dd, bOneCube );
+ assert( RetValue );
+
+ // record the cube
+ Llb_Nonlin4RecordState( p->pAig, p->vOrder, (unsigned *)Vec_PtrEntryLast(vStates), pValues, fBackward );
+
+ // write state in terms of NS variables
+ if ( Vec_PtrSize(p->vRings) > 1 )
+ {
+ bState = Llb_Nonlin4ComputeCube( p->dd, p->pAig, p->vOrder, pValues, fBackward ); Cudd_Ref( bState );
+ }
+ // perform backward analysis
+ vVars2Q = Llb_Nonlin4CreateVars2Q( p->dd, p->pAig, p->vOrder, !fBackward );
+ Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v )
+ {
+ if ( v == Vec_PtrSize(p->vRings) - 1 )
+ continue;
+
+ // preprocess partitions
+ vRootsNew = Llb_Nonlin4Multiply( p->dd, bState, p->vRoots );
+ Cudd_RecursiveDeref( p->dd, bState );
+
+ // compute the next states
+ bImage = Llb_Nonlin4Image( p->dd, vRootsNew, NULL, vVars2Q ); Cudd_Ref( bImage );
+ Llb_Nonlin4Deref( p->dd, vRootsNew );
+
+ // intersect with the previous set
+ bOneCube = Cudd_bddIntersect( p->dd, bImage, bRing ); Cudd_Ref( bOneCube );
+ Cudd_RecursiveDeref( p->dd, bImage );
+
+ // find any assignment of the BDD
+ RetValue = Cudd_bddPickOneCube( p->dd, bOneCube, pValues );
+ Cudd_RecursiveDeref( p->dd, bOneCube );
+ assert( RetValue );
+
+ // record the cube
+ Llb_Nonlin4RecordState( p->pAig, p->vOrder, (unsigned *)Vec_PtrEntry(vStates, v), pValues, fBackward );
+
+ // check that we get the init state
+ if ( v == 0 )
+ {
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ assert( fBackward || pValues[Llb_ObjBddVar(p->vOrder, pObj)] == 0 );
+ break;
+ }
+
+ // write state in terms of NS variables
+ bState = Llb_Nonlin4ComputeCube( p->dd, p->pAig, p->vOrder, pValues, fBackward ); Cudd_Ref( bState );
+ }
+ Vec_IntFree( vVars2Q );
+ ABC_FREE( pValues );
+ if ( fBackward )
+ Vec_PtrReverseOrder( vStates );
+// if ( fVerbose )
+// Abc_PrintTime( 1, "BDD-based cex generation time", clock() - clk );
+ return vStates;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Perform reachability with hints.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_Nonlin4Reachability( Llb_Mnx_t * p )
+{
+ DdNode * bAux;
+ int nIters, nBddSizeFr, nBddSizeTo, nBddSizeTo2;
+ int clkTemp, clkIter, clk = clock();
+ assert( Aig_ManRegNum(p->pAig) > 0 );
+
+ if ( p->pPars->fBackward )
+ {
+ // create bad state in the ring manager
+ if ( !p->pPars->fSkipOutCheck )
+ {
+ p->bBad = Llb_Nonlin4ComputeInitState( p->dd, p->pAig, p->vOrder, p->pPars->fBackward ); Cudd_Ref( p->bBad );
+ }
+ // create init state
+ if ( p->pPars->fCluster )
+ p->bCurrent = p->dd->bFunc, p->dd->bFunc = NULL;
+ else
+ {
+ p->bCurrent = Llb_Nonlin4ComputeBad( p->dd, p->pAig, p->vOrder );
+ if ( p->bCurrent == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = -1;
+ return -1;
+ }
+ Cudd_Ref( p->bCurrent );
+ }
+ // remap into the next states
+ p->bCurrent = Cudd_bddVarMap( p->dd, bAux = p->bCurrent );
+ if ( p->bCurrent == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during remapping bad states.\n", p->pPars->TimeLimit );
+ Cudd_RecursiveDeref( p->dd, bAux );
+ p->pPars->iFrame = -1;
+ return -1;
+ }
+ Cudd_Ref( p->bCurrent );
+ Cudd_RecursiveDeref( p->dd, bAux );
+ }
+ else
+ {
+ // create bad state in the ring manager
+ if ( !p->pPars->fSkipOutCheck )
+ {
+ if ( p->pPars->fCluster )
+ p->bBad = p->dd->bFunc, p->dd->bFunc = NULL;
+ else
+ {
+ p->bBad = Llb_Nonlin4ComputeBad( p->dd, p->pAig, p->vOrder );
+ if ( p->bBad == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = -1;
+ return -1;
+ }
+ Cudd_Ref( p->bBad );
+ }
+ }
+ else if ( p->dd->bFunc )
+ Cudd_RecursiveDeref( p->dd, p->dd->bFunc ), p->dd->bFunc = NULL;
+ // compute the starting set of states
+ p->bCurrent = Llb_Nonlin4ComputeInitState( p->dd, p->pAig, p->vOrder, p->pPars->fBackward ); Cudd_Ref( p->bCurrent );
+ }
+ // perform iterations
+ p->bReached = p->bCurrent; Cudd_Ref( p->bReached );
+ for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ )
+ {
+ clkIter = clock();
+ // check the runtime limit
+ if ( p->pPars->TimeLimit && time(NULL) > p->pPars->TimeTarget )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ return -1;
+ }
+
+ // save the onion ring
+ Vec_PtrPush( p->vRings, p->bCurrent ); Cudd_Ref( p->bCurrent );
+
+ // check it for bad states
+ if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->dd, p->bCurrent, Cudd_Not(p->bBad) ) )
+ {
+ Vec_Ptr_t * vStates;
+ assert( p->pAig->pSeqModel == NULL );
+ vStates = Llb_Nonlin4DeriveCex( p, p->pPars->fBackward, p->pPars->fVerbose );
+ p->pAig->pSeqModel = Llb4_Nonlin4TransformCex( p->pAig, vStates, -1, p->pPars->fVerbose );
+ Vec_PtrFreeP( &vStates );
+ if ( !p->pPars->fSilent )
+ {
+ printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump a witness). ", p->pAig->pSeqModel->iPo, nIters );
+ Abc_PrintTime( 1, "Time", clock() - clk );
+ }
+ p->pPars->iFrame = nIters - 1;
+ return 0;
+ }
+
+ // compute the next states
+ clkTemp = clock();
+ p->bNext = Llb_Nonlin4Image( p->dd, p->vRoots, p->bCurrent, p->vVars2Q );
+ if ( p->bNext == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation in quantification.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ return -1;
+ }
+ Cudd_Ref( p->bNext );
+ p->timeImage += clock() - clkTemp;
+
+ // remap into current states
+ clkTemp = clock();
+ p->bNext = Cudd_bddVarMap( p->dd, bAux = p->bNext );
+ if ( p->bNext == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during remapping next states.\n", p->pPars->TimeLimit );
+ Cudd_RecursiveDeref( p->dd, bAux );
+ p->pPars->iFrame = nIters - 1;
+ return -1;
+ }
+ Cudd_Ref( p->bNext );
+ Cudd_RecursiveDeref( p->dd, bAux );
+ p->timeRemap += clock() - clkTemp;
+
+ // collect statistics
+ if ( p->pPars->fVerbose )
+ {
+ nBddSizeFr = Cudd_DagSize( p->bCurrent );
+ nBddSizeTo = Cudd_DagSize( bAux );
+ nBddSizeTo2 = Cudd_DagSize( p->bNext );
+ }
+ Cudd_RecursiveDeref( p->dd, p->bCurrent ); p->bCurrent = NULL;
+
+ // derive new states
+ p->bCurrent = Cudd_bddAnd( p->dd, p->bNext, Cudd_Not(p->bReached) );
+ if ( p->bCurrent == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ return -1;
+ }
+ Cudd_Ref( p->bCurrent );
+ Cudd_RecursiveDeref( p->dd, p->bNext ); p->bNext = NULL;
+ if ( Cudd_IsConstant(p->bCurrent) )
+ break;
+/*
+ // reduce BDD size using constrain // Cudd_bddRestrict
+ p->bCurrent = Cudd_bddRestrict( p->dd, bAux = p->bCurrent, Cudd_Not(p->bReached) );
+ Cudd_Ref( p->bCurrent );
+printf( "Before = %d. After = %d.\n", Cudd_DagSize(bAux), Cudd_DagSize(p->bCurrent) );
+ Cudd_RecursiveDeref( p->dd, bAux );
+*/
+
+ // add to the reached set
+ p->bReached = Cudd_bddOr( p->dd, bAux = p->bReached, p->bCurrent );
+ if ( p->bReached == NULL )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit );
+ p->pPars->iFrame = nIters - 1;
+ Cudd_RecursiveDeref( p->dd, bAux );
+ return -1;
+ }
+ Cudd_Ref( p->bReached );
+ Cudd_RecursiveDeref( p->dd, bAux );
+
+
+ // report the results
+ if ( p->pPars->fVerbose )
+ {
+ printf( "I =%5d : ", nIters );
+ printf( "Fr =%7d ", nBddSizeFr );
+ printf( "ImNs =%7d ", nBddSizeTo );
+ printf( "ImCs =%7d ", nBddSizeTo2 );
+ printf( "Rea =%7d ", Cudd_DagSize(p->bReached) );
+ printf( "(%4d %4d) ", Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) );
+ Abc_PrintTime( 1, "T", clock() - clkIter );
+ }
+/*
+ if ( pPars->fVerbose )
+ {
+ double nMints = Cudd_CountMinterm(p->dd, bReached, Saig_ManRegNum(p->pAig) );
+// Extra_bddPrint( p->dd, bReached );printf( "\n" );
+ printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) );
+ fflush( stdout );
+ }
+*/
+ if ( nIters == p->pPars->nIterMax - 1 )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nIterMax );
+ p->pPars->iFrame = nIters;
+ return -1;
+ }
+ }
+
+ // report the stats
+ if ( p->pPars->fVerbose )
+ {
+ double nMints = Cudd_CountMinterm(p->dd, p->bReached, Saig_ManRegNum(p->pAig) );
+ if ( p->bCurrent && Cudd_IsConstant(p->bCurrent) )
+ printf( "Reachability analysis completed after %d frames.\n", nIters );
+ else
+ printf( "Reachability analysis is stopped after %d frames.\n", nIters );
+ printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) );
+ fflush( stdout );
+ }
+ if ( p->bCurrent == NULL || !Cudd_IsConstant(p->bCurrent) )
+ {
+ if ( !p->pPars->fSilent )
+ printf( "Verified only for states reachable in %d frames. ", nIters );
+ p->pPars->iFrame = p->pPars->nIterMax;
+ return -1; // undecided
+ }
+ // report
+ if ( !p->pPars->fSilent )
+ printf( "The miter is proved unreachable after %d iterations. ", nIters );
+ p->pPars->iFrame = nIters - 1;
+ Abc_PrintTime( 1, "Time", clock() - clk );
+ return 1; // unreachable
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reorders BDDs in the working manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4Reorder( DdManager * dd, int fTwice, int fVerbose )
+{
+ int clk = clock();
+ if ( fVerbose )
+ Abc_Print( 1, "Reordering... Before =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+ Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+ if ( fVerbose )
+ Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+ if ( fTwice )
+ {
+ Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
+ if ( fVerbose )
+ Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
+ }
+ if ( fVerbose )
+ Abc_PrintTime( 1, "Time", clock() - clk );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Llb_Mnx_t * Llb_MnxStart( Aig_Man_t * pAig, Gia_ParLlb_t * pPars )
+{
+ Llb_Mnx_t * p;
+
+ p = ABC_CALLOC( Llb_Mnx_t, 1 );
+ p->pAig = pAig;
+ p->pPars = pPars;
+
+ // compute time to stop
+ p->pPars->TimeTarget = p->pPars->TimeLimit ? time(NULL) + p->pPars->TimeLimit : 0;
+
+ if ( pPars->fCluster )
+ {
+// Llb_Nonlin4Cluster( p->pAig, &p->dd, &p->vOrder, &p->vRoots, pPars->nBddMax, pPars->fVerbose );
+// Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT );
+ Llb4_Nonlin4Sweep( p->pAig, pPars->nBddMax, pPars->nClusterMax, &p->dd, &p->vOrder, &p->vRoots, pPars->fVerbose );
+ // set the stop time parameter
+ p->dd->TimeStop = p->pPars->TimeTarget;
+ }
+ else
+ {
+// p->vOrder = Llb_Nonlin4CreateOrderSimple( pAig );
+ p->vOrder = Llb_Nonlin4CreateOrder( pAig );
+ p->dd = Cudd_Init( Vec_IntCountPositive(p->vOrder) + 1, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT );
+ Cudd_SetMaxGrowth( p->dd, 1.05 );
+ // set the stop time parameter
+ p->dd->TimeStop = p->pPars->TimeTarget;
+ p->vRoots = Llb_Nonlin4DerivePartitions( p->dd, pAig, p->vOrder );
+ }
+
+ Llb_Nonlin4SetupVarMap( p->dd, pAig, p->vOrder );
+ p->vVars2Q = Llb_Nonlin4CreateVars2Q( p->dd, pAig, p->vOrder, p->pPars->fBackward );
+ p->vRings = Vec_PtrAlloc( 100 );
+
+ if ( pPars->fReorder )
+ Llb_Nonlin4Reorder( p->dd, 0, 1 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MnxStop( Llb_Mnx_t * p )
+{
+ DdNode * bTemp;
+ int i;
+ if ( p->pPars->fVerbose )
+ {
+ p->timeReo = Cudd_ReadReorderingTime(p->dd);
+ p->timeOther = p->timeTotal - p->timeImage - p->timeRemap;
+ ABC_PRTP( "Image ", p->timeImage, p->timeTotal );
+ ABC_PRTP( "Remap ", p->timeRemap, p->timeTotal );
+ ABC_PRTP( "Other ", p->timeOther, p->timeTotal );
+ ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal );
+ ABC_PRTP( " reo ", p->timeReo, p->timeTotal );
+ }
+ // remove BDDs
+ if ( p->bBad )
+ Cudd_RecursiveDeref( p->dd, p->bBad );
+ if ( p->bReached )
+ Cudd_RecursiveDeref( p->dd, p->bReached );
+ if ( p->bCurrent )
+ Cudd_RecursiveDeref( p->dd, p->bCurrent );
+ if ( p->bNext )
+ Cudd_RecursiveDeref( p->dd, p->bNext );
+ if ( p->vRings )
+ Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i )
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ if ( p->vRoots )
+ Vec_PtrForEachEntry( DdNode *, p->vRoots, bTemp, i )
+ Cudd_RecursiveDeref( p->dd, bTemp );
+ // remove arrays
+ Vec_PtrFreeP( &p->vRings );
+ Vec_PtrFreeP( &p->vRoots );
+//Cudd_PrintInfo( p->dd, stdout );
+ Extra_StopManager( p->dd );
+ Vec_IntFreeP( &p->vOrder );
+ Vec_IntFreeP( &p->vVars2Q );
+ ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_MnxCheckNextStateVars( Llb_Mnx_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i, Counter0 = 0, Counter1 = 0;
+ Saig_ManForEachLi( p->pAig, pObj, i )
+ if ( Saig_ObjIsLo(p->pAig, Aig_ObjFanin0(pObj)) )
+ {
+ if ( Aig_ObjFaninC0(pObj) )
+ Counter0++;
+ else
+ Counter1++;
+ }
+ printf( "Total = %d. Direct LO = %d. Compl LO = %d.\n", Aig_ManRegNum(p->pAig), Counter1, Counter0 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds balanced cut.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars )
+{
+ Llb_Mnx_t * pMnn;
+ int RetValue = -1;
+ if ( pPars->fVerbose )
+ Aig_ManPrintStats( pAig );
+ if ( pPars->fCluster && Aig_ManObjNum(pAig) >= (1 << 15) )
+ {
+ printf( "The number of objects is more than 2^15. Clustering cannot be used.\n" );
+ return RetValue;
+ }
+ {
+ int clk = clock();
+ pMnn = Llb_MnxStart( pAig, pPars );
+//Llb_MnxCheckNextStateVars( pMnn );
+ if ( !pPars->fSkipReach )
+ RetValue = Llb_Nonlin4Reachability( pMnn );
+ pMnn->timeTotal = clock() - clk;
+ Llb_MnxStop( pMnn );
+ }
+ return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/llb/llb4Sweep.c b/src/proof/llb/llb4Sweep.c
new file mode 100644
index 00000000..d13c366f
--- /dev/null
+++ b/src/proof/llb/llb4Sweep.c
@@ -0,0 +1,588 @@
+/**CFile****************************************************************
+
+ FileName [llb2Sweep.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD based reachability.]
+
+ Synopsis [Non-linear quantification scheduling.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: llb2Sweep.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "llbInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Find good static variable ordering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4SweepOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter, int fSaveAll )
+{
+ Aig_Obj_t * pFanin0, * pFanin1;
+ if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+ return;
+ Aig_ObjSetTravIdCurrent( pAig, pObj );
+ assert( Llb_ObjBddVar(vOrder, pObj) < 0 );
+ if ( Aig_ObjIsPi(pObj) )
+ {
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ );
+ return;
+ }
+ // try fanins with higher level first
+ pFanin0 = Aig_ObjFanin0(pObj);
+ pFanin1 = Aig_ObjFanin1(pObj);
+// if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) )
+ if ( pFanin0->Level > pFanin1->Level )
+ {
+ Llb_Nonlin4SweepOrder_rec( pAig, pFanin0, vOrder, pCounter, fSaveAll );
+ Llb_Nonlin4SweepOrder_rec( pAig, pFanin1, vOrder, pCounter, fSaveAll );
+ }
+ else
+ {
+ Llb_Nonlin4SweepOrder_rec( pAig, pFanin1, vOrder, pCounter, fSaveAll );
+ Llb_Nonlin4SweepOrder_rec( pAig, pFanin0, vOrder, pCounter, fSaveAll );
+ }
+ if ( fSaveAll || pObj->fMarkA )
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find good static variable ordering.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_Nonlin4SweepOrder( Aig_Man_t * pAig, int * pCounter, int fSaveAll )
+{
+ Vec_Int_t * vOrder;
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ // collect nodes in the order
+ vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) );
+ Aig_ManIncrementTravId( pAig );
+ Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) );
+ Aig_ManForEachPo( pAig, pObj, i )
+ {
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ );
+ Llb_Nonlin4SweepOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter, fSaveAll );
+ }
+ Aig_ManForEachPi( pAig, pObj, i )
+ if ( Llb_ObjBddVar(vOrder, pObj) < 0 )
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ );
+// assert( Counter == Aig_ManObjNum(pAig) - 1 ); // no dangling nodes
+ if ( pCounter )
+ *pCounter = Counter - Aig_ManPiNum(pAig) - Aig_ManPoNum(pAig);
+ return vOrder;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs BDD sweep on the netlist.]
+
+ Description [Returns AIG with internal cut points labeled with fMarkA.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Llb4_Nonlin4SweepCutpoints( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nBddLimit, int fVerbose )
+{
+ DdManager * dd;
+ DdNode * bFunc0, * bFunc1, * bFunc;
+ Aig_Obj_t * pObj;
+ int i, Counter = 0, Counter1 = 0;
+ dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ // assign elementary variables
+ Aig_ManCleanData( pAig );
+ Aig_ManForEachPi( pAig, pObj, i )
+ pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+ // sweep internal nodes
+ Aig_ManForEachNode( pAig, pObj, i )
+ {
+/*
+ if ( pObj->nRefs >= 4 )
+ {
+ bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); Cudd_Ref( bFunc );
+ pObj->pData = bFunc;
+ Counter1++;
+ continue;
+ }
+*/
+ bFunc0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bFunc1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+ bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
+ if ( Cudd_DagSize(bFunc) > nBddLimit )
+ {
+// if ( fVerbose )
+// printf( "Node %5d : Beg =%5d. ", i, Cudd_DagSize(bFunc) );
+
+ // add cutpoint at a larger one
+ Cudd_RecursiveDeref( dd, bFunc );
+ if ( Cudd_DagSize(bFunc0) >= Cudd_DagSize(bFunc1) )
+ {
+ Cudd_RecursiveDeref( dd, (DdNode *)Aig_ObjFanin0(pObj)->pData );
+ bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, Aig_ObjFanin0(pObj)) );
+ Aig_ObjFanin0(pObj)->pData = bFunc; Cudd_Ref( bFunc );
+ Aig_ObjFanin0(pObj)->fMarkA = 1;
+
+// if ( fVerbose )
+// printf( "Ref =%3d ", Aig_ObjFanin0(pObj)->nRefs );
+ }
+ else
+ {
+ Cudd_RecursiveDeref( dd, (DdNode *)Aig_ObjFanin1(pObj)->pData );
+ bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, Aig_ObjFanin1(pObj)) );
+ Aig_ObjFanin1(pObj)->pData = bFunc; Cudd_Ref( bFunc );
+ Aig_ObjFanin1(pObj)->fMarkA = 1;
+
+// if ( fVerbose )
+// printf( "Ref =%3d ", Aig_ObjFanin1(pObj)->nRefs );
+ }
+ // perform new operation
+ bFunc0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) );
+ bFunc1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) );
+ bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
+// assert( Cudd_DagSize(bFunc) <= nBddLimit );
+
+// if ( fVerbose )
+// printf( "End =%5d.\n", Cudd_DagSize(bFunc) );
+ Counter++;
+ }
+ pObj->pData = bFunc;
+//printf( "%d ", Cudd_DagSize(bFunc) );
+ }
+//printf( "\n" );
+ // clean up
+ Aig_ManForEachNode( pAig, pObj, i )
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+ Extra_StopManager( dd );
+// Aig_ManCleanMarkA( pAig );
+ if ( fVerbose )
+ printf( "Added %d cut points. Used %d high fanout points.\n", Counter, Counter1 );
+ return Counter + Counter1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives BDDs for the partitions.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb_Nonlin4SweepPartitions_rec( DdManager * dd, Aig_Obj_t * pObj, Vec_Int_t * vOrder, Vec_Ptr_t * vRoots )
+{
+ DdNode * bBdd, * bBdd0, * bBdd1, * bPart, * vVar;
+ if ( Aig_ObjIsConst1(pObj) )
+ return Cudd_ReadOne(dd);
+ if ( Aig_ObjIsPi(pObj) )
+ return Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+ if ( pObj->pData )
+ return (DdNode *)pObj->pData;
+ if ( Aig_ObjIsPo(pObj) )
+ {
+ bBdd0 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) );
+ bPart = Cudd_bddXnor( dd, Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ), bBdd0 ); Cudd_Ref( bPart );
+ Vec_PtrPush( vRoots, bPart );
+ return NULL;
+ }
+ bBdd0 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) );
+ bBdd1 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin1(pObj), vOrder, vRoots), Aig_ObjFaninC1(pObj) );
+ bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bBdd );
+ if ( Llb_ObjBddVar(vOrder, pObj) >= 0 )
+ {
+ vVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+ bPart = Cudd_bddXnor( dd, vVar, bBdd ); Cudd_Ref( bPart );
+ Vec_PtrPush( vRoots, bPart );
+ Cudd_RecursiveDeref( dd, bBdd );
+ bBdd = vVar; Cudd_Ref( vVar );
+ }
+ pObj->pData = bBdd;
+ return bBdd;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives BDDs for the partitions.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Llb_Nonlin4SweepPartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fTransition )
+{
+ Vec_Ptr_t * vRoots;
+ Aig_Obj_t * pObj;
+ int i;
+ Aig_ManCleanData( pAig );
+ vRoots = Vec_PtrAlloc( 100 );
+ if ( fTransition )
+ {
+ Saig_ManForEachLi( pAig, pObj, i )
+ Llb_Nonlin4SweepPartitions_rec( dd, pObj, vOrder, vRoots );
+ }
+ else
+ {
+ Saig_ManForEachPo( pAig, pObj, i )
+ Llb_Nonlin4SweepPartitions_rec( dd, pObj, vOrder, vRoots );
+ }
+ Aig_ManForEachNode( pAig, pObj, i )
+ if ( pObj->pData )
+ Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData );
+ return vRoots;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Get bad state monitor.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdNode * Llb4_Nonlin4SweepBadMonitor( Aig_Man_t * pAig, Vec_Int_t * vOrder, DdManager * dd )
+{
+ Aig_Obj_t * pObj;
+ DdNode * bRes, * bVar, * bTemp;
+ int i, TimeStop;
+ TimeStop = dd->TimeStop; dd->TimeStop = 0;
+ bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes );
+ Saig_ManForEachPo( pAig, pObj, i )
+ {
+ bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) );
+ bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes );
+ Cudd_RecursiveDeref( dd, bTemp );
+ }
+ Cudd_Deref( bRes );
+ dd->TimeStop = TimeStop;
+ return Cudd_Not(bRes);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates quantifiable variables for both types of traversal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Llb_Nonlin4SweepVars2Q( Aig_Man_t * pAig, Vec_Int_t * vOrder, int fAddLis )
+{
+ Vec_Int_t * vVars2Q;
+ Aig_Obj_t * pObj;
+ int i;
+ vVars2Q = Vec_IntAlloc( 0 );
+ Vec_IntFill( vVars2Q, Aig_ManObjNumMax(pAig), 1 );
+ // add flop outputs
+ Saig_ManForEachLo( pAig, pObj, i )
+ Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 );
+ // add flop inputs
+ if ( fAddLis )
+ Saig_ManForEachLi( pAig, pObj, i )
+ Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 );
+ return vVars2Q;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Multiply every partition by the cube.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4SweepDeref( DdManager * dd, Vec_Ptr_t * vParts )
+{
+ DdNode * bFunc;
+ int i;
+ Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i )
+ Cudd_RecursiveDeref( dd, bFunc );
+ Vec_PtrFree( vParts );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Multiply every partition by the cube.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4SweepPrint( Vec_Ptr_t * vFuncs )
+{
+ DdNode * bFunc;
+ int i;
+ printf( "(%d) ", Vec_PtrSize(vFuncs) );
+ Vec_PtrForEachEntry( DdNode *, vFuncs, bFunc, i )
+ printf( "%d ", Cudd_DagSize(bFunc) );
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes bad states.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdManager * Llb4_Nonlin4SweepBadStates( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nVars )
+{
+ DdManager * dd;
+ Vec_Ptr_t * vParts;
+ Vec_Int_t * vVars2Q;
+ DdNode * bMonitor, * bImage;
+ // get quantifiable variables
+ vVars2Q = Llb_Nonlin4SweepVars2Q( pAig, vOrder, 0 );
+ // start BDD manager and create partitions
+ dd = Cudd_Init( nVars, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ vParts = Llb_Nonlin4SweepPartitions( dd, pAig, vOrder, 0 );
+//printf( "Outputs: " );
+//Llb_Nonlin4SweepPrint( vParts );
+ // compute image of the partitions
+ bMonitor = Llb4_Nonlin4SweepBadMonitor( pAig, vOrder, dd ); Cudd_Ref( bMonitor );
+ Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+ bImage = Llb_Nonlin4Image( dd, vParts, bMonitor, vVars2Q ); Cudd_Ref( bImage );
+ Cudd_RecursiveDeref( dd, bMonitor );
+ Llb_Nonlin4SweepDeref( dd, vParts );
+ Vec_IntFree( vVars2Q );
+ // save image and return
+ dd->bFunc = bImage;
+ return dd;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes clusters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+DdManager * Llb4_Nonlin4SweepGroups( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nVars, Vec_Ptr_t ** pvGroups, int nBddLimitClp, int fVerbose )
+{
+ DdManager * dd;
+ Vec_Ptr_t * vParts;
+ Vec_Int_t * vVars2Q;
+ // get quantifiable variables
+ vVars2Q = Llb_Nonlin4SweepVars2Q( pAig, vOrder, 1 );
+ // start BDD manager and create partitions
+ dd = Cudd_Init( nVars, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
+ vParts = Llb_Nonlin4SweepPartitions( dd, pAig, vOrder, 1 );
+//printf( "Transitions: " );
+//Llb_Nonlin4SweepPrint( vParts );
+ // compute image of the partitions
+
+ Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
+ *pvGroups = Llb_Nonlin4Group( dd, vParts, vVars2Q, nBddLimitClp );
+ Llb_Nonlin4SweepDeref( dd, vParts );
+// *pvGroups = vParts;
+
+if ( fVerbose )
+{
+printf( "Groups: " );
+Llb_Nonlin4SweepPrint( *pvGroups );
+}
+
+ Vec_IntFree( vVars2Q );
+ return dd;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Creates quantifiable variables for both types of traversal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb_Nonlin4SweepPrintSuppProfile( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups, int fVerbose )
+{
+ Aig_Obj_t * pObj;
+ int i, * pSupp;
+ int nSuppAll = 0, nSuppPi = 0, nSuppPo = 0, nSuppLi = 0, nSuppLo = 0, nSuppAnd = 0;
+
+ pSupp = ABC_CALLOC( int, Cudd_ReadSize(dd) );
+ Extra_VectorSupportArray( dd, (DdNode **)Vec_PtrArray(vGroups), Vec_PtrSize(vGroups), pSupp );
+
+ Aig_ManForEachObj( pAig, pObj, i )
+ {
+ if ( Llb_ObjBddVar(vOrder, pObj) < 0 )
+ continue;
+ // remove variables that do not participate
+ if ( pSupp[Llb_ObjBddVar(vOrder, pObj)] == 0 )
+ {
+ if ( Aig_ObjIsNode(pObj) )
+ Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), -1 );
+ continue;
+ }
+ nSuppAll++;
+ if ( Saig_ObjIsPi(pAig, pObj) )
+ nSuppPi++;
+ else if ( Saig_ObjIsLo(pAig, pObj) )
+ nSuppLo++;
+ else if ( Saig_ObjIsPo(pAig, pObj) )
+ nSuppPo++;
+ else if ( Saig_ObjIsLi(pAig, pObj) )
+ nSuppLi++;
+ else
+ nSuppAnd++;
+ }
+ ABC_FREE( pSupp );
+
+ if ( fVerbose )
+ {
+ printf( "Groups =%3d ", Vec_PtrSize(vGroups) );
+ printf( "Variables: all =%4d ", nSuppAll );
+ printf( "pi =%4d ", nSuppPi );
+ printf( "po =%4d ", nSuppPo );
+ printf( "lo =%4d ", nSuppLo );
+ printf( "li =%4d ", nSuppLi );
+ printf( "and =%4d", nSuppAnd );
+ printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs BDD sweep on the netlist.]
+
+ Description [Returns BDD manager, ordering, clusters, and bad states
+ inside dd->bFunc.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb4_Nonlin4Sweep( Aig_Man_t * pAig, int nSweepMax, int nClusterMax, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int fVerbose )
+{
+ DdManager * ddBad, * ddWork;
+ Vec_Ptr_t * vGroups;
+ Vec_Int_t * vOrder;
+ int Counter, nCutPoints;
+
+ // get the original ordering
+ Aig_ManCleanMarkA( pAig );
+ vOrder = Llb_Nonlin4SweepOrder( pAig, &Counter, 1 );
+ assert( Counter == Aig_ManNodeNum(pAig) );
+ // mark the nodes
+ nCutPoints = Llb4_Nonlin4SweepCutpoints( pAig, vOrder, nSweepMax, fVerbose );
+ Vec_IntFree( vOrder );
+ // get better ordering
+ vOrder = Llb_Nonlin4SweepOrder( pAig, &Counter, 0 );
+ assert( Counter == nCutPoints );
+ Aig_ManCleanMarkA( pAig );
+ // compute the BAD states
+ ddBad = Llb4_Nonlin4SweepBadStates( pAig, vOrder, nCutPoints + Aig_ManPiNum(pAig) + Aig_ManPoNum(pAig) );
+ // compute the clusters
+ ddWork = Llb4_Nonlin4SweepGroups( pAig, vOrder, nCutPoints + Aig_ManPiNum(pAig) + Aig_ManPoNum(pAig), &vGroups, nClusterMax, fVerbose );
+ // transfer the result from the Bad manager
+//printf( "Bad before = %d.\n", Cudd_DagSize(ddBad->bFunc) );
+ ddWork->bFunc = Cudd_bddTransfer( ddBad, ddWork, ddBad->bFunc ); Cudd_Ref( ddWork->bFunc );
+ Cudd_RecursiveDeref( ddBad, ddBad->bFunc ); ddBad->bFunc = NULL;
+ Extra_StopManager( ddBad );
+ // update ordering to exclude quantified variables
+//printf( "Bad after = %d.\n", Cudd_DagSize(ddWork->bFunc) );
+
+ Llb_Nonlin4SweepPrintSuppProfile( ddWork, pAig, vOrder, vGroups, fVerbose );
+
+ // return the result
+ *pdd = ddWork;
+ *pvOrder = vOrder;
+ *pvGroups = vGroups;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs BDD sweep on the netlist.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Llb4_Nonlin4SweepExperiment( Aig_Man_t * pAig )
+{
+ DdManager * dd;
+ Vec_Int_t * vOrder;
+ Vec_Ptr_t * vGroups;
+ Llb4_Nonlin4Sweep( pAig, 100, 500, &dd, &vOrder, &vGroups, 1 );
+
+ Llb_Nonlin4SweepDeref( dd, vGroups );
+
+ Cudd_RecursiveDeref( dd, dd->bFunc );
+ Extra_StopManager( dd );
+ Vec_IntFree( vOrder );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/llb/llbInt.h b/src/proof/llb/llbInt.h
new file mode 100644
index 00000000..d81aadcf
--- /dev/null
+++ b/src/proof/llb/llbInt.h
@@ -0,0 +1,211 @@
+/**CFile****************************************************************
+
+ FileName [llbInt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [BDD-based reachability.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 8, 2010.]
+
+ Revision [$Id: llbInt.h,v 1.00 2010/05/08 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__llb__llbInt_h
+#define ABC__aig__llb__llbInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "src/aig/aig/aig.h"
+#include "src/aig/saig/saig.h"
+#include "src/proof/ssw/ssw.h"
+#include "src/misc/extra/extraBdd.h"
+#include "llb.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Llb_Man_t_ Llb_Man_t;
+typedef struct Llb_Mtr_t_ Llb_Mtr_t;
+typedef struct Llb_Grp_t_ Llb_Grp_t;
+
+struct Llb_Man_t_
+{
+ Gia_ParLlb_t * pPars; // parameters
+ Aig_Man_t * pAigGlo; // initial AIG manager (owned by the caller)
+ Aig_Man_t * pAig; // derived AIG manager (created in this package)
+ DdManager * dd; // BDD manager
+ DdManager * ddG; // BDD manager
+ DdManager * ddR; // BDD manager
+ Vec_Int_t * vObj2Var; // mapping AIG ObjId into BDD var index
+ Vec_Int_t * vVar2Obj; // mapping BDD var index into AIG ObjId
+ Vec_Ptr_t * vGroups; // group Id into group pointer
+ Llb_Mtr_t * pMatrix; // dependency matrix
+ // image computation
+ Vec_Ptr_t * vRings; // onion rings
+ Vec_Int_t * vVarBegs; // the first group where the var appears
+ Vec_Int_t * vVarEnds; // the last group where the var appears
+ // variable mapping
+ Vec_Int_t * vNs2Glo; // next state variables into global variables
+ Vec_Int_t * vCs2Glo; // next state variables into global variables
+ Vec_Int_t * vGlo2Cs; // global variables into current state variables
+ Vec_Int_t * vGlo2Ns; // global variables into current state variables
+ // flow computation
+// Vec_Int_t * vMem;
+// Vec_Ptr_t * vTops;
+// Vec_Ptr_t * vBots;
+// Vec_Ptr_t * vCuts;
+};
+
+struct Llb_Mtr_t_
+{
+ int nPis; // number of primary inputs
+ int nFfs; // number of flip-flops
+ int nRows; // number of rows
+ int nCols; // number of columns
+ int * pColSums; // sum of values in a column
+ Llb_Grp_t ** pColGrps; // group structure for each col
+ int * pRowSums; // sum of values in a row
+ char ** pMatrix; // dependency matrix
+ Llb_Man_t * pMan; // manager
+ // partial product
+ char * pProdVars; // variables in the partial product
+ int * pProdNums; // var counts in the remaining partitions
+};
+
+struct Llb_Grp_t_
+{
+ int Id; // group ID
+ Vec_Ptr_t * vIns; // input AIG objs
+ Vec_Ptr_t * vOuts; // output AIG objs
+ Vec_Ptr_t * vNodes; // internal AIG objs
+ Llb_Man_t * pMan; // manager
+ Llb_Grp_t * pPrev; // previous group
+ Llb_Grp_t * pNext; // next group
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int Llb_ObjBddVar( Vec_Int_t * vOrder, Aig_Obj_t * pObj ) { return Vec_IntEntry(vOrder, Aig_ObjId(pObj)); }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== llbConstr.c ======================================================*/
+extern Vec_Int_t * Llb_ManDeriveConstraints( Aig_Man_t * p );
+extern void Llb_ManPrintEntries( Aig_Man_t * p, Vec_Int_t * vCands );
+/*=== llbCore.c ======================================================*/
+extern int Llb_ManModelCheckAig( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars, Vec_Int_t * vHints, DdManager ** pddGlo );
+/*=== llbCluster.c ======================================================*/
+extern void Llb_ManCluster( Llb_Mtr_t * p );
+/*=== llbDump.c ======================================================*/
+extern void Llb_ManDumpReached( DdManager * ddG, DdNode * bReached, char * pModel, char * pFileName );
+/*=== llbFlow.c ======================================================*/
+extern Vec_Ptr_t * Llb_ManFlow( Aig_Man_t * p, Vec_Ptr_t * vSources, int * pnFlow );
+/*=== llbHint.c ======================================================*/
+extern int Llb_ManReachabilityWithHints( Llb_Man_t * p );
+extern int Llb_ManModelCheckAigWithHints( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars );
+/*=== llbMan.c =======================================================*/
+extern void Llb_ManPrepareVarMap( Llb_Man_t * p );
+extern Llb_Man_t * Llb_ManStart( Aig_Man_t * pAigGlo, Aig_Man_t * pAig, Gia_ParLlb_t * pPars );
+extern void Llb_ManStop( Llb_Man_t * p );
+/*=== llbMatrix.c ====================================================*/
+extern void Llb_MtrVerifyMatrix( Llb_Mtr_t * p );
+extern Llb_Mtr_t * Llb_MtrCreate( Llb_Man_t * p );
+extern void Llb_MtrFree( Llb_Mtr_t * p );
+extern void Llb_MtrPrint( Llb_Mtr_t * p, int fOrder );
+extern void Llb_MtrPrintMatrixStats( Llb_Mtr_t * p );
+/*=== llbPart.c ======================================================*/
+extern Llb_Grp_t * Llb_ManGroupAlloc( Llb_Man_t * pMan );
+extern void Llb_ManGroupStop( Llb_Grp_t * p );
+extern void Llb_ManPrepareGroups( Llb_Man_t * pMan );
+extern Llb_Grp_t * Llb_ManGroupsCombine( Llb_Grp_t * p1, Llb_Grp_t * p2 );
+extern Llb_Grp_t * Llb_ManGroupCreateFromCuts( Llb_Man_t * pMan, Vec_Int_t * vCut1, Vec_Int_t * vCut2 );
+extern void Llb_ManPrepareVarLimits( Llb_Man_t * p );
+/*=== llbPivot.c =====================================================*/
+extern int Llb_ManTracePaths( Aig_Man_t * p, Aig_Obj_t * pPivot );
+extern Vec_Int_t * Llb_ManMarkPivotNodes( Aig_Man_t * p, int fUseInternal );
+/*=== llbReach.c =====================================================*/
+extern int Llb_ManReachability( Llb_Man_t * p, Vec_Int_t * vHints, DdManager ** pddGlo );
+/*=== llbSched.c =====================================================*/
+extern void Llb_MtrSchedule( Llb_Mtr_t * p );
+
+/*=== llb2Bad.c ======================================================*/
+extern DdNode * Llb_BddComputeBad( Aig_Man_t * pInit, DdManager * dd, int TimeOut );
+extern DdNode * Llb_BddQuantifyPis( Aig_Man_t * pInit, DdManager * dd, DdNode * bFunc );
+/*=== llb2Core.c ======================================================*/
+extern DdNode * Llb_CoreComputeCube( DdManager * dd, Vec_Int_t * vVars, int fUseVarIndex, char * pValues );
+extern int Llb_CoreExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, int TimeTarget );
+/*=== llb2Driver.c ======================================================*/
+extern Vec_Int_t * Llb_DriverCountRefs( Aig_Man_t * p );
+extern Vec_Int_t * Llb_DriverCollectNs( Aig_Man_t * pAig, Vec_Int_t * vDriRefs );
+extern Vec_Int_t * Llb_DriverCollectCs( Aig_Man_t * pAig );
+extern DdNode * Llb_DriverPhaseCube( Aig_Man_t * pAig, Vec_Int_t * vDriRefs, DdManager * dd );
+extern DdManager * Llb_DriverLastPartition( Aig_Man_t * p, Vec_Int_t * vVarsNs, int TimeTarget );
+/*=== llb2Image.c ======================================================*/
+extern Vec_Ptr_t * Llb_ImgSupports( Aig_Man_t * p, Vec_Ptr_t * vDdMans, Vec_Int_t * vStart, Vec_Int_t * vStop, int fAddPis, int fVerbose );
+extern void Llb_ImgSchedule( Vec_Ptr_t * vSupps, Vec_Ptr_t ** pvQuant0, Vec_Ptr_t ** pvQuant1, int fVerbose );
+extern DdManager * Llb_ImgPartition( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, int TimeTarget );
+extern void Llb_ImgQuantifyFirst( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, Vec_Ptr_t * vQuant0, int fVerbose );
+extern void Llb_ImgQuantifyReset( Vec_Ptr_t * vDdMans );
+extern DdNode * Llb_ImgComputeImage( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, DdManager * dd, DdNode * bInit,
+ Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1, Vec_Int_t * vDriRefs,
+ int TimeTarget, int fBackward, int fReorder, int fVerbose );
+
+extern DdManager * Llb_NonlinImageStart( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, int * pOrder, int fFirst, int TimeTarget );
+extern DdNode * Llb_NonlinImageCompute( DdNode * bCurrent, int fReorder, int fDrop, int fVerbose, int * pOrder );
+extern void Llb_NonlinImageQuit();
+
+/*=== llb3Image.c =======================================================*/
+extern DdNode * Llb_NonlinImage( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q,
+ DdManager * dd, DdNode * bCurrent, int fReorder, int fVerbose, int * pOrder, int Limit, int TimeTarget );
+/*=== llb3Nonlin.c ======================================================*/
+extern DdNode * Llb_NonlinComputeInitState( Aig_Man_t * pAig, DdManager * dd );
+
+
+/*=== llb4Cex.c =======================================================*/
+extern Abc_Cex_t * Llb4_Nonlin4TransformCex( Aig_Man_t * pAig, Vec_Ptr_t * vStates, int iCexPo, int fVerbose );
+/*=== llb4Cluster.c =======================================================*/
+//extern void Llb_Nonlin4Cluster( Aig_Man_t * pAig, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int nBddMax, int fVerbose );
+/*=== llb4Image.c =======================================================*/
+extern DdNode * Llb_Nonlin4Image( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q );
+extern Vec_Ptr_t * Llb_Nonlin4Group( DdManager * dd, Vec_Ptr_t * vParts, Vec_Int_t * vVars2Q, int nSizeMax );
+/*=== llb4Map.c =========================================================*/
+//extern Vec_Int_t * Llb_AigMap( Aig_Man_t * pAig, int nLutSize, int nLutMin );
+/*=== llb4Nonlin.c ======================================================*/
+//extern int Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars );
+/*=== llb4Sweep.c ======================================================*/
+extern void Llb4_Nonlin4Sweep( Aig_Man_t * pAig, int nSweepMax, int nClusterMax, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int fVerbose );
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/proof/llb/module.make b/src/proof/llb/module.make
new file mode 100644
index 00000000..849a9e0e
--- /dev/null
+++ b/src/proof/llb/module.make
@@ -0,0 +1,23 @@
+SRC += src/proof/llb/llb.c \
+ src/proof/llb/llb1Cluster.c \
+ src/proof/llb/llb1Constr.c \
+ src/proof/llb/llb1Core.c \
+ src/proof/llb/llb1Group.c \
+ src/proof/llb/llb1Hint.c \
+ src/proof/llb/llb1Man.c \
+ src/proof/llb/llb1Matrix.c \
+ src/proof/llb/llb1Pivot.c \
+ src/proof/llb/llb1Reach.c \
+ src/proof/llb/llb1Sched.c \
+ src/proof/llb/llb2Bad.c \
+ src/proof/llb/llb2Core.c \
+ src/proof/llb/llb2Driver.c \
+ src/proof/llb/llb2Dump.c \
+ src/proof/llb/llb2Flow.c \
+ src/proof/llb/llb2Image.c \
+ src/proof/llb/llb3Image.c \
+ src/proof/llb/llb3Nonlin.c \
+ src/proof/llb/llb4Cex.c \
+ src/proof/llb/llb4Image.c \
+ src/proof/llb/llb4Nonlin.c \
+ src/proof/llb/llb4Sweep.c
diff --git a/src/proof/pdr/module.make b/src/proof/pdr/module.make
new file mode 100644
index 00000000..93fd8071
--- /dev/null
+++ b/src/proof/pdr/module.make
@@ -0,0 +1,8 @@
+SRC += src/proof/pdr/pdr.c \
+ src/proof/pdr/pdrCnf.c \
+ src/proof/pdr/pdrCore.c \
+ src/proof/pdr/pdrInv.c \
+ src/proof/pdr/pdrMan.c \
+ src/proof/pdr/pdrSat.c \
+ src/proof/pdr/pdrTsim.c \
+ src/proof/pdr/pdrUtil.c
diff --git a/src/proof/pdr/pdr.c b/src/proof/pdr/pdr.c
new file mode 100644
index 00000000..6bdf75b5
--- /dev/null
+++ b/src/proof/pdr/pdr.c
@@ -0,0 +1,53 @@
+/**CFile****************************************************************
+
+ FileName [pdr.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Netlist representation.]
+
+ Synopsis []
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - November 20, 2010.]
+
+ Revision [$Id: pdr.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "pdrInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/pdr/pdr.h b/src/proof/pdr/pdr.h
new file mode 100644
index 00000000..4f0f769e
--- /dev/null
+++ b/src/proof/pdr/pdr.h
@@ -0,0 +1,79 @@
+/**CFile****************************************************************
+
+ FileName [pdr.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Property driven reachability.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - November 20, 2010.]
+
+ Revision [$Id: pdr.h,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__sat__pdr__pdr_h
+#define ABC__sat__pdr__pdr_h
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Pdr_Par_t_ Pdr_Par_t;
+struct Pdr_Par_t_
+{
+ int iOutput; // zero-based number of primary output to solve
+ int nRecycle; // limit on vars for recycling
+ int nFrameMax; // limit on frame count
+ int nConfLimit; // limit on SAT solver conflicts
+ int nTimeOut; // timeout in seconds
+ int fTwoRounds; // use two rounds for generalization
+ int fMonoCnf; // monolythic CNF
+ int fDumpInv; // dump inductive invariant
+ int fShortest; // forces bug traces to be shortest
+ int fSkipGeneral; // skips expensive generalization step
+ int fVerbose; // verbose output
+ int fVeryVerbose; // very verbose output
+ int iFrame; // explored up to this frame
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== pdrCore.c ==========================================================*/
+extern void Pdr_ManSetDefaultParams( Pdr_Par_t * pPars );
+extern int Pdr_ManSolve( Aig_Man_t * p, Pdr_Par_t * pPars, Abc_Cex_t ** ppCex );
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/proof/pdr/pdrClass.c b/src/proof/pdr/pdrClass.c
new file mode 100644
index 00000000..519384c5
--- /dev/null
+++ b/src/proof/pdr/pdrClass.c
@@ -0,0 +1,223 @@
+/**CFile****************************************************************
+
+ FileName [pdrClass.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Property driven reachability.]
+
+ Synopsis [Equivalence classes of register outputs.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - November 20, 2010.]
+
+ Revision [$Id: pdrClass.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "pdrInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs duplication with the variable map.]
+
+ Description [Var map contains -1 if const0 and <reg_num> otherwise.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Pdr_ManRehashWithMap( Aig_Man_t * pAig, Vec_Int_t * vMap )
+{
+ Aig_Man_t * pFrames;
+ Aig_Obj_t * pObj;
+ int i, iReg;
+ assert( Vec_IntSize(vMap) == Aig_ManRegNum(pAig) );
+ // start the fraig package
+ pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) );
+ pFrames->pName = Abc_UtilStrsav( pAig->pName );
+ pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec );
+ // create CI mapping
+ Aig_ManCleanData( pAig );
+ Aig_ManConst1(pAig)->pData = Aig_ManConst1(pFrames);
+ Aig_ManForEachPi( pAig, pObj, i )
+ pObj->pData = Aig_ObjCreatePi(pFrames);
+ Saig_ManForEachLo( pAig, pObj, i )
+ {
+ iReg = Vec_IntEntry(vMap, i);
+ if ( iReg == -1 )
+ pObj->pData = Aig_ManConst0(pFrames);
+ else
+ pObj->pData = Saig_ManLo(pAig, iReg)->pData;
+ }
+ // add internal nodes of this frame
+ Aig_ManForEachNode( pAig, pObj, i )
+ pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
+ // add output nodes
+ Aig_ManForEachPo( pAig, pObj, i )
+ pObj->pData = Aig_ObjCreatePo( pFrames, Aig_ObjChild0Copy(pObj) );
+ // finish off
+ Aig_ManCleanup( pFrames );
+ Aig_ManSetRegNum( pFrames, Aig_ManRegNum(pAig) );
+ return pFrames;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates mapping of registers.]
+
+ Description [Var map contains -1 if const0 and <reg_num> otherwise.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Pdr_ManCreateMap( Aig_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ Vec_Int_t * vMap;
+ int * pLit2Id, Lit, i;
+ pLit2Id = ABC_ALLOC( int, Aig_ManObjNumMax(p) * 2 );
+ for ( i = 0; i < Aig_ManObjNumMax(p) * 2; i++ )
+ pLit2Id[i] = -1;
+ vMap = Vec_IntAlloc( Aig_ManRegNum(p) );
+ Saig_ManForEachLi( p, pObj, i )
+ {
+ if ( Aig_ObjChild0(pObj) == Aig_ManConst0(p) )
+ {
+ Vec_IntPush( vMap, -1 );
+ continue;
+ }
+ Lit = 2 * Aig_ObjFaninId0(pObj) + Aig_ObjFaninC0(pObj);
+ if ( pLit2Id[Lit] < 0 ) // the first time
+ pLit2Id[Lit] = i;
+ Vec_IntPush( vMap, pLit2Id[Lit] );
+ }
+ ABC_FREE( pLit2Id );
+ return vMap;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts reduced registers.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pdr_ManCountMap( Vec_Int_t * vMap )
+{
+ int i, Entry, Counter = 0;
+ Vec_IntForEachEntry( vMap, Entry, i )
+ if ( Entry != i )
+ Counter++;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts reduced registers.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pdr_ManPrintMap( Vec_Int_t * vMap )
+{
+ Vec_Int_t * vMarks;
+ int f, i, iClass, Entry, Counter = 0;
+ printf( " Consts: " );
+ Vec_IntForEachEntry( vMap, Entry, i )
+ if ( Entry == -1 )
+ printf( "%d ", i );
+ printf( "\n" );
+ vMarks = Vec_IntAlloc( 100 );
+ Vec_IntForEachEntry( vMap, iClass, f )
+ {
+ if ( iClass == -1 )
+ continue;
+ if ( iClass == f )
+ continue;
+ // check previous classes
+ if ( Vec_IntFind( vMarks, iClass ) >= 0 )
+ continue;
+ Vec_IntPush( vMarks, iClass );
+ // print class
+ printf( " Class %d : ", iClass );
+ Vec_IntForEachEntry( vMap, Entry, i )
+ if ( Entry == iClass )
+ printf( "%d ", i );
+ printf( "\n" );
+ }
+ Vec_IntFree( vMarks );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pdr_ManEquivClasses( Aig_Man_t * pAig )
+{
+ Vec_Int_t * vMap;
+ Aig_Man_t * pTemp;
+ int f, nFrames = 100;
+ assert( Saig_ManRegNum(pAig) > 0 );
+ // start the map
+ vMap = Vec_IntAlloc( 0 );
+ Vec_IntFill( vMap, Aig_ManRegNum(pAig), -1 );
+ // iterate and print changes
+ for ( f = 0; f < nFrames; f++ )
+ {
+ // implement variable map
+ pTemp = Pdr_ManRehashWithMap( pAig, vMap );
+ // report the result
+ printf( "F =%4d : Total = %6d. Nodes = %6d. RedRegs = %6d. Prop = %s\n",
+ f+1, Aig_ManNodeNum(pAig), Aig_ManNodeNum(pTemp), Pdr_ManCountMap(vMap),
+ Aig_ObjChild0(Aig_ManPo(pTemp,0)) == Aig_ManConst0(pTemp) ? "proof" : "unknown" );
+ // recreate the map
+ Pdr_ManPrintMap( vMap );
+ Vec_IntFree( vMap );
+ vMap = Pdr_ManCreateMap( pTemp );
+ Aig_ManStop( pTemp );
+ if ( Pdr_ManCountMap(vMap) == 0 )
+ break;
+ }
+ Vec_IntFree( vMap );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/pdr/pdrCnf.c b/src/proof/pdr/pdrCnf.c
new file mode 100644
index 00000000..fddd292b
--- /dev/null
+++ b/src/proof/pdr/pdrCnf.c
@@ -0,0 +1,357 @@
+/**CFile****************************************************************
+
+ FileName [pdrCnf.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Property driven reachability.]
+
+ Synopsis [CNF computation on demand.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - November 20, 2010.]
+
+ Revision [$Id: pdrCnf.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "pdrInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*
+ The CNF (p->pCnf2) is expressed in terms of object IDs.
+ Each node in the CNF is marked if it has clauses (p->pCnf2->pObj2Count[Id] > 0).
+ Each node in the CNF has the first clause (p->pCnf2->pObj2Clause)
+ and the number of clauses (p->pCnf2->pObj2Count).
+ Each node used in a CNF of any timeframe has its SAT var recorded.
+ Each frame has a reserve mapping of SAT variables into ObjIds.
+*/
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Returns SAT variable of the given object.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Pdr_ObjSatVar1( Pdr_Man_t * p, int k, Aig_Obj_t * pObj )
+{
+ return p->pCnf1->pVarNums[ Aig_ObjId(pObj) ];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns SAT variable of the given object.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Pdr_ObjSatVar2FindOrAdd( Pdr_Man_t * p, int k, Aig_Obj_t * pObj )
+{
+ assert( p->pCnf2->pObj2Count[Aig_ObjId(pObj)] >= 0 );
+ if ( p->pvId2Vars[Aig_ObjId(pObj)] == NULL )
+ p->pvId2Vars[Aig_ObjId(pObj)] = Vec_IntStart( 16 );
+ if ( Vec_IntGetEntry( p->pvId2Vars[Aig_ObjId(pObj)], k ) == 0 )
+ {
+ sat_solver * pSat = Pdr_ManSolver(p, k);
+ Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry(p->vVar2Ids, k);
+ int iVarNew = Vec_IntSize( vVar2Ids );
+ assert( iVarNew > 0 );
+ Vec_IntPush( vVar2Ids, Aig_ObjId(pObj) );
+ Vec_IntWriteEntry( p->pvId2Vars[Aig_ObjId(pObj)], k, iVarNew );
+ sat_solver_setnvars( pSat, iVarNew + 1 );
+ if ( k == 0 && Saig_ObjIsLo(p->pAig, pObj) ) // initialize the register output
+ {
+ int Lit = toLitCond( iVarNew, 1 );
+ int RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 );
+ assert( RetValue == 1 );
+ sat_solver_compress( pSat );
+ }
+ }
+ return Vec_IntEntry( p->pvId2Vars[Aig_ObjId(pObj)], k );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively adds CNF for the given object.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pdr_ObjSatVar2( Pdr_Man_t * p, int k, Aig_Obj_t * pObj )
+{
+ sat_solver * pSat;
+ Vec_Int_t * vLits;
+ Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry(p->vVar2Ids, k);
+ int nVarCount = Vec_IntSize(vVar2Ids);
+ int iVarThis = Pdr_ObjSatVar2FindOrAdd( p, k, pObj );
+ int * pLit, i, iVar, nClauses, iFirstClause, RetValue;
+ if ( nVarCount == Vec_IntSize(vVar2Ids) )
+ return iVarThis;
+ assert( nVarCount + 1 == Vec_IntSize(vVar2Ids) );
+ if ( Aig_ObjIsPi(pObj) )
+ return iVarThis;
+ nClauses = p->pCnf2->pObj2Count[Aig_ObjId(pObj)];
+ iFirstClause = p->pCnf2->pObj2Clause[Aig_ObjId(pObj)];
+ assert( nClauses > 0 );
+ pSat = Pdr_ManSolver(p, k);
+ vLits = Vec_IntAlloc( 16 );
+ for ( i = iFirstClause; i < iFirstClause + nClauses; i++ )
+ {
+ Vec_IntClear( vLits );
+ for ( pLit = p->pCnf2->pClauses[i]; pLit < p->pCnf2->pClauses[i+1]; pLit++ )
+ {
+ iVar = Pdr_ObjSatVar2( p, k, Aig_ManObj(p->pAig, lit_var(*pLit)) );
+ Vec_IntPush( vLits, toLitCond( iVar, lit_sign(*pLit) ) );
+ }
+ RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits)+Vec_IntSize(vLits) );
+ assert( RetValue );
+ }
+ Vec_IntFree( vLits );
+ return iVarThis;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns SAT variable of the given object.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pdr_ObjSatVar( Pdr_Man_t * p, int k, Aig_Obj_t * pObj )
+{
+ if ( p->pPars->fMonoCnf )
+ return Pdr_ObjSatVar1( p, k, pObj );
+ else
+ return Pdr_ObjSatVar2( p, k, pObj );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns register number for the given SAT variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Pdr_ObjRegNum1( Pdr_Man_t * p, int k, int iSatVar )
+{
+ int RegId;
+ assert( iSatVar >= 0 );
+ // consider the case of auxiliary variable
+ if ( iSatVar >= p->pCnf1->nVars )
+ return -1;
+ // consider the case of register output
+ RegId = Vec_IntEntry( p->vVar2Reg, iSatVar );
+ assert( RegId >= 0 && RegId < Aig_ManRegNum(p->pAig) );
+ return RegId;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns register number for the given SAT variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Pdr_ObjRegNum2( Pdr_Man_t * p, int k, int iSatVar )
+{
+ Aig_Obj_t * pObj;
+ int ObjId;
+ Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry(p->vVar2Ids, k);
+ assert( iSatVar > 0 && iSatVar < Vec_IntSize(vVar2Ids) );
+ ObjId = Vec_IntEntry( vVar2Ids, iSatVar );
+ if ( ObjId == -1 ) // activation variable
+ return -1;
+ pObj = Aig_ManObj( p->pAig, ObjId );
+ if ( Saig_ObjIsLi( p->pAig, pObj ) )
+ return Aig_ObjPioNum(pObj)-Saig_ManPoNum(p->pAig);
+ assert( 0 ); // should be called for register inputs only
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns register number for the given SAT variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pdr_ObjRegNum( Pdr_Man_t * p, int k, int iSatVar )
+{
+ if ( p->pPars->fMonoCnf )
+ return Pdr_ObjRegNum1( p, k, iSatVar );
+ else
+ return Pdr_ObjRegNum2( p, k, iSatVar );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns the index of unused SAT variable.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pdr_ManFreeVar( Pdr_Man_t * p, int k )
+{
+ if ( p->pPars->fMonoCnf )
+ return sat_solver_nvars( Pdr_ManSolver(p, k) );
+ else
+ {
+ Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry( p->vVar2Ids, k );
+ Vec_IntPush( vVar2Ids, -1 );
+ return Vec_IntSize( vVar2Ids ) - 1;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline sat_solver * Pdr_ManNewSolver1( sat_solver * pSat, Pdr_Man_t * p, int k, int fInit )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ assert( pSat );
+ if ( p->pCnf1 == NULL )
+ {
+ int nRegs = p->pAig->nRegs;
+ p->pAig->nRegs = Aig_ManPoNum(p->pAig);
+ p->pCnf1 = Cnf_Derive( p->pAig, Aig_ManPoNum(p->pAig) );
+ p->pAig->nRegs = nRegs;
+ assert( p->vVar2Reg == NULL );
+ p->vVar2Reg = Vec_IntStartFull( p->pCnf1->nVars );
+ Saig_ManForEachLi( p->pAig, pObj, i )
+ Vec_IntWriteEntry( p->vVar2Reg, Pdr_ObjSatVar(p, k, pObj), i );
+ }
+ pSat = (sat_solver *)Cnf_DataWriteIntoSolverInt( pSat, p->pCnf1, 1, fInit );
+ sat_solver_set_runtime_limit( pSat, p->timeToStop );
+ return pSat;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline sat_solver * Pdr_ManNewSolver2( sat_solver * pSat, Pdr_Man_t * p, int k, int fInit )
+{
+ Vec_Int_t * vVar2Ids;
+ int i, Entry;
+ assert( pSat );
+ if ( p->pCnf2 == NULL )
+ {
+ p->pCnf2 = Cnf_DeriveOther( p->pAig );
+ p->pvId2Vars = ABC_CALLOC( Vec_Int_t *, Aig_ManObjNumMax(p->pAig) );
+ p->vVar2Ids = Vec_PtrAlloc( 256 );
+ }
+ // update the variable mapping
+ vVar2Ids = (Vec_Int_t *)Vec_PtrGetEntry( p->vVar2Ids, k );
+ if ( vVar2Ids == NULL )
+ {
+ vVar2Ids = Vec_IntAlloc( 500 );
+ Vec_PtrWriteEntry( p->vVar2Ids, k, vVar2Ids );
+ }
+ Vec_IntForEachEntry( vVar2Ids, Entry, i )
+ {
+ if ( Entry == -1 )
+ continue;
+ assert( Vec_IntEntry( p->pvId2Vars[Entry], k ) > 0 );
+ Vec_IntWriteEntry( p->pvId2Vars[Entry], k, 0 );
+ }
+ Vec_IntClear( vVar2Ids );
+ Vec_IntPush( vVar2Ids, -1 );
+ // start the SAT solver
+// pSat = sat_solver_new();
+ sat_solver_setnvars( pSat, 500 );
+ sat_solver_set_runtime_limit( pSat, p->timeToStop );
+ return pSat;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+sat_solver * Pdr_ManNewSolver( sat_solver * pSat, Pdr_Man_t * p, int k, int fInit )
+{
+ assert( pSat != NULL );
+ if ( p->pPars->fMonoCnf )
+ return Pdr_ManNewSolver1( pSat, p, k, fInit );
+ else
+ return Pdr_ManNewSolver2( pSat, p, k, fInit );
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/pdr/pdrCore.c b/src/proof/pdr/pdrCore.c
new file mode 100644
index 00000000..025ada06
--- /dev/null
+++ b/src/proof/pdr/pdrCore.c
@@ -0,0 +1,722 @@
+/**CFile****************************************************************
+
+ FileName [pdrCore.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Property driven reachability.]
+
+ Synopsis [Core procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - November 20, 2010.]
+
+ Revision [$Id: pdrCore.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "pdrInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the state could be blocked.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pdr_ManSetDefaultParams( Pdr_Par_t * pPars )
+{
+ memset( pPars, 0, sizeof(Pdr_Par_t) );
+ pPars->iOutput = -1; // zero-based output number
+ pPars->nRecycle = 300; // limit on vars for recycling
+ pPars->nFrameMax = 5000; // limit on number of timeframes
+ pPars->nTimeOut = 0; // timeout in seconds
+ pPars->nConfLimit = 100000; // limit on SAT solver conflicts
+ pPars->fTwoRounds = 0; // use two rounds for generalization
+ pPars->fMonoCnf = 0; // monolythic CNF
+ pPars->fDumpInv = 0; // dump inductive invariant
+ pPars->fShortest = 0; // forces bug traces to be shortest
+ pPars->fVerbose = 0; // verbose output
+ pPars->fVeryVerbose = 0; // very verbose output
+ pPars->iFrame = -1; // explored up to this frame
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reduces clause using analyzeFinal.]
+
+ Description [Assumes that the SAT solver just terminated an UNSAT call.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Pdr_Set_t * Pdr_ManReduceClause( Pdr_Man_t * p, int k, Pdr_Set_t * pCube )
+{
+ Pdr_Set_t * pCubeMin;
+ Vec_Int_t * vLits;
+ int i, Entry, nCoreLits, * pCoreLits;
+ // get relevant SAT literals
+ nCoreLits = sat_solver_final(Pdr_ManSolver(p, k), &pCoreLits);
+ // translate them into register literals and remove auxiliary
+ vLits = Pdr_ManLitsToCube( p, k, pCoreLits, nCoreLits );
+ // skip if there is no improvement
+ if ( Vec_IntSize(vLits) == pCube->nLits )
+ return NULL;
+ assert( Vec_IntSize(vLits) < pCube->nLits );
+ // if the cube overlaps with init, add any literal
+ Vec_IntForEachEntry( vLits, Entry, i )
+ if ( lit_sign(Entry) == 0 ) // positive literal
+ break;
+ if ( i == Vec_IntSize(vLits) ) // only negative literals
+ {
+ // add the first positive literal
+ for ( i = 0; i < pCube->nLits; i++ )
+ if ( lit_sign(pCube->Lits[i]) == 0 ) // positive literal
+ {
+ Vec_IntPush( vLits, pCube->Lits[i] );
+ break;
+ }
+ assert( i < pCube->nLits );
+ }
+ // generate a starting cube
+ pCubeMin = Pdr_SetCreateSubset( pCube, Vec_IntArray(vLits), Vec_IntSize(vLits) );
+ assert( !Pdr_SetIsInit(pCubeMin, -1) );
+/*
+ // make sure the cube works
+ {
+ int RetValue;
+ RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, 0 );
+ assert( RetValue );
+ }
+*/
+ return pCubeMin;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the state could be blocked.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pdr_ManPushClauses( Pdr_Man_t * p )
+{
+ Pdr_Set_t * pTemp, * pCubeK, * pCubeK1;
+ Vec_Ptr_t * vArrayK, * vArrayK1;
+ int i, j, k, m, RetValue = 0, RetValue2, kMax = Vec_PtrSize(p->vSolvers)-1;
+ int Counter = 0;
+ int clk = clock();
+ Vec_VecForEachLevelStartStop( p->vClauses, vArrayK, k, 1, kMax )
+ {
+ Vec_PtrSort( vArrayK, (int (*)(void))Pdr_SetCompare );
+ vArrayK1 = Vec_VecEntry( p->vClauses, k+1 );
+ Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCubeK, j )
+ {
+ Counter++;
+
+ // remove cubes in the same frame that are contained by pCubeK
+ Vec_PtrForEachEntryStart( Pdr_Set_t *, vArrayK, pTemp, m, j+1 )
+ {
+ if ( !Pdr_SetContains( pTemp, pCubeK ) ) // pCubeK contains pTemp
+ continue;
+ Pdr_SetDeref( pTemp );
+ Vec_PtrWriteEntry( vArrayK, m, Vec_PtrEntryLast(vArrayK) );
+ Vec_PtrPop(vArrayK);
+ m--;
+ }
+
+ // check if the clause can be moved to the next frame
+ RetValue2 = Pdr_ManCheckCube( p, k, pCubeK, NULL, 0 );
+ if ( RetValue2 == -1 )
+ return -1;
+ if ( !RetValue2 )
+ continue;
+
+ {
+ Pdr_Set_t * pCubeMin;
+ pCubeMin = Pdr_ManReduceClause( p, k, pCubeK );
+ if ( pCubeMin != NULL )
+ {
+// printf( "%d ", pCubeK->nLits - pCubeMin->nLits );
+ Pdr_SetDeref( pCubeK );
+ pCubeK = pCubeMin;
+ }
+ }
+
+ // if it can be moved, add it to the next frame
+ Pdr_ManSolverAddClause( p, k+1, pCubeK );
+ // check if the clause subsumes others
+ Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK1, pCubeK1, i )
+ {
+ if ( !Pdr_SetContains( pCubeK1, pCubeK ) ) // pCubeK contains pCubeK1
+ continue;
+ Pdr_SetDeref( pCubeK1 );
+ Vec_PtrWriteEntry( vArrayK1, i, Vec_PtrEntryLast(vArrayK1) );
+ Vec_PtrPop(vArrayK1);
+ i--;
+ }
+ // add the last clause
+ Vec_PtrPush( vArrayK1, pCubeK );
+ Vec_PtrWriteEntry( vArrayK, j, Vec_PtrEntryLast(vArrayK) );
+ Vec_PtrPop(vArrayK);
+ j--;
+ }
+ if ( Vec_PtrSize(vArrayK) == 0 )
+ RetValue = 1;
+ }
+
+ // clean up the last one
+ vArrayK = Vec_VecEntry( p->vClauses, kMax );
+ Vec_PtrSort( vArrayK, (int (*)(void))Pdr_SetCompare );
+ Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCubeK, j )
+ {
+ // remove cubes in the same frame that are contained by pCubeK
+ Vec_PtrForEachEntryStart( Pdr_Set_t *, vArrayK, pTemp, m, j+1 )
+ {
+ if ( !Pdr_SetContains( pTemp, pCubeK ) ) // pCubeK contains pTemp
+ continue;
+/*
+ printf( "===\n" );
+ Pdr_SetPrint( stdout, pCubeK, Aig_ManRegNum(p->pAig), NULL );
+ printf( "\n" );
+ Pdr_SetPrint( stdout, pTemp, Aig_ManRegNum(p->pAig), NULL );
+ printf( "\n" );
+*/
+ Pdr_SetDeref( pTemp );
+ Vec_PtrWriteEntry( vArrayK, m, Vec_PtrEntryLast(vArrayK) );
+ Vec_PtrPop(vArrayK);
+ m--;
+ }
+ }
+ p->tPush += clock() - clk;
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the clause is contained in higher clauses.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pdr_ManCheckContainment( Pdr_Man_t * p, int k, Pdr_Set_t * pSet )
+{
+ Pdr_Set_t * pThis;
+ Vec_Ptr_t * vArrayK;
+ int i, j, kMax = Vec_PtrSize(p->vSolvers)-1;
+ Vec_VecForEachLevelStartStop( p->vClauses, vArrayK, i, k, kMax+1 )
+ Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pThis, j )
+ if ( Pdr_SetContains( pSet, pThis ) )
+ return 1;
+ return 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Sorts literals by priority.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int * Pdr_ManSortByPriority( Pdr_Man_t * p, Pdr_Set_t * pCube )
+{
+ int * pPrios = Vec_IntArray(p->vPrio);
+ int * pArray = p->pOrder;
+ int temp, i, j, best_i, nSize = pCube->nLits;
+ // initialize variable order
+ for ( i = 0; i < nSize; i++ )
+ pArray[i] = i;
+ for ( i = 0; i < nSize-1; i++ )
+ {
+ best_i = i;
+ for ( j = i+1; j < nSize; j++ )
+// if ( pArray[j] < pArray[best_i] )
+ if ( pPrios[pCube->Lits[pArray[j]]>>1] < pPrios[pCube->Lits[pArray[best_i]]>>1] )
+ best_i = j;
+ temp = pArray[i];
+ pArray[i] = pArray[best_i];
+ pArray[best_i] = temp;
+ }
+/*
+ for ( i = 0; i < pCube->nLits; i++ )
+ printf( "%2d : %5d %5d %5d\n", i, pArray[i], pCube->Lits[pArray[i]]>>1, pPrios[pCube->Lits[pArray[i]]>>1] );
+ printf( "\n" );
+*/
+ return pArray;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the state could be blocked.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pdr_ManGeneralize( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, Pdr_Set_t ** ppPred, Pdr_Set_t ** ppCubeMin )
+{
+ Pdr_Set_t * pCubeMin, * pCubeTmp = NULL;
+ int i, j, n, Lit, RetValue, clk = clock();
+ int * pOrder;
+ // if there is no induction, return
+ *ppCubeMin = NULL;
+ RetValue = Pdr_ManCheckCube( p, k, pCube, ppPred, p->pPars->nConfLimit );
+ if ( RetValue == -1 )
+ return -1;
+ if ( RetValue == 0 )
+ {
+ p->tGeneral += clock() - clk;
+ return 0;
+ }
+
+ // reduce clause using assumptions
+// pCubeMin = Pdr_SetDup( pCube );
+ pCubeMin = Pdr_ManReduceClause( p, k, pCube );
+ if ( pCubeMin == NULL )
+ pCubeMin = Pdr_SetDup( pCube );
+
+ // perform generalization
+ if ( !p->pPars->fSkipGeneral )
+ {
+ // sort literals by their occurences
+ pOrder = Pdr_ManSortByPriority( p, pCubeMin );
+ // try removing literals
+ for ( j = 0; j < pCubeMin->nLits; j++ )
+ {
+ // use ordering
+ // i = j;
+ i = pOrder[j];
+
+ // check init state
+ assert( pCubeMin->Lits[i] != -1 );
+ if ( Pdr_SetIsInit(pCubeMin, i) )
+ continue;
+ // try removing this literal
+ Lit = pCubeMin->Lits[i]; pCubeMin->Lits[i] = -1;
+ RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, p->pPars->nConfLimit );
+ if ( RetValue == -1 )
+ {
+ Pdr_SetDeref( pCubeMin );
+ return -1;
+ }
+ pCubeMin->Lits[i] = Lit;
+ if ( RetValue == 0 )
+ continue;
+
+ // remove j-th entry
+ for ( n = j; n < pCubeMin->nLits-1; n++ )
+ pOrder[n] = pOrder[n+1];
+ j--;
+
+ // success - update the cube
+ pCubeMin = Pdr_SetCreateFrom( pCubeTmp = pCubeMin, i );
+ Pdr_SetDeref( pCubeTmp );
+ assert( pCubeMin->nLits > 0 );
+ i--;
+
+ // get the ordering by decreasing priorit
+ pOrder = Pdr_ManSortByPriority( p, pCubeMin );
+ }
+
+ if ( p->pPars->fTwoRounds )
+ for ( j = 0; j < pCubeMin->nLits; j++ )
+ {
+ // use ordering
+ // i = j;
+ i = pOrder[j];
+
+ // check init state
+ assert( pCubeMin->Lits[i] != -1 );
+ if ( Pdr_SetIsInit(pCubeMin, i) )
+ continue;
+ // try removing this literal
+ Lit = pCubeMin->Lits[i]; pCubeMin->Lits[i] = -1;
+ RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, p->pPars->nConfLimit );
+ if ( RetValue == -1 )
+ {
+ Pdr_SetDeref( pCubeMin );
+ return -1;
+ }
+ pCubeMin->Lits[i] = Lit;
+ if ( RetValue == 0 )
+ continue;
+
+ // remove j-th entry
+ for ( n = j; n < pCubeMin->nLits-1; n++ )
+ pOrder[n] = pOrder[n+1];
+ j--;
+
+ // success - update the cube
+ pCubeMin = Pdr_SetCreateFrom( pCubeTmp = pCubeMin, i );
+ Pdr_SetDeref( pCubeTmp );
+ assert( pCubeMin->nLits > 0 );
+ i--;
+
+ // get the ordering by decreasing priorit
+ pOrder = Pdr_ManSortByPriority( p, pCubeMin );
+ }
+ }
+
+ assert( ppCubeMin != NULL );
+ *ppCubeMin = pCubeMin;
+ p->tGeneral += clock() - clk;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the state could be blocked.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pdr_ManBlockCube( Pdr_Man_t * p, Pdr_Set_t * pCube )
+{
+ Pdr_Obl_t * pThis;
+ Pdr_Set_t * pPred, * pCubeMin;
+ int i, k, RetValue, Prio = ABC_INFINITY, Counter = 0;
+ int kMax = Vec_PtrSize(p->vSolvers)-1, clk;
+ p->nBlocks++;
+ // create first proof obligation
+ assert( p->pQueue == NULL );
+ pThis = Pdr_OblStart( kMax, Prio--, pCube, NULL ); // consume ref
+ Pdr_QueuePush( p, pThis );
+ // try to solve it recursively
+ while ( !Pdr_QueueIsEmpty(p) )
+ {
+ Counter++;
+ pThis = Pdr_QueueHead( p );
+ if ( pThis->iFrame == 0 )
+ return 0; // SAT
+ pThis = Pdr_QueuePop( p );
+ assert( pThis->iFrame > 0 );
+ assert( !Pdr_SetIsInit(pThis->pState, -1) );
+
+ clk = clock();
+ if ( Pdr_ManCheckContainment( p, pThis->iFrame, pThis->pState ) )
+ {
+ p->tContain += clock() - clk;
+ Pdr_OblDeref( pThis );
+ continue;
+ }
+ p->tContain += clock() - clk;
+
+ // check if the cube is already contained
+ RetValue = Pdr_ManCheckCubeCs( p, pThis->iFrame, pThis->pState );
+ if ( RetValue == -1 ) // cube is blocked by clauses in this frame
+ {
+ Pdr_OblDeref( pThis );
+ return -1;
+ }
+ if ( RetValue ) // cube is blocked by clauses in this frame
+ {
+ Pdr_OblDeref( pThis );
+ continue;
+ }
+
+ // check if the cube holds with relative induction
+ pCubeMin = NULL;
+ RetValue = Pdr_ManGeneralize( p, pThis->iFrame-1, pThis->pState, &pPred, &pCubeMin );
+ if ( RetValue == -1 )
+ {
+ Pdr_OblDeref( pThis );
+ return -1;
+ }
+ if ( RetValue ) // cube is blocked inductively in this frame
+ {
+ assert( pCubeMin != NULL );
+
+ // k is the last frame where pCubeMin holds
+ k = pThis->iFrame;
+
+ // check other frames
+ assert( pPred == NULL );
+ for ( k = pThis->iFrame; k < kMax; k++ )
+ if ( !Pdr_ManCheckCube( p, k, pCubeMin, NULL, 0 ) )
+ break;
+
+ // add new clause
+ if ( p->pPars->fVeryVerbose )
+ {
+ printf( "Adding cube " );
+ Pdr_SetPrint( stdout, pCubeMin, Aig_ManRegNum(p->pAig), NULL );
+ printf( " to frame %d.\n", k );
+ }
+ // set priority flops
+ for ( i = 0; i < pCubeMin->nLits; i++ )
+ {
+ assert( pCubeMin->Lits[i] >= 0 );
+ assert( (pCubeMin->Lits[i] / 2) < Aig_ManRegNum(p->pAig) );
+ Vec_IntAddToEntry( p->vPrio, pCubeMin->Lits[i] / 2, 1 );
+ }
+
+ Vec_VecPush( p->vClauses, k, pCubeMin ); // consume ref
+ p->nCubes++;
+ // add clause
+ for ( i = 1; i <= k; i++ )
+ Pdr_ManSolverAddClause( p, i, pCubeMin );
+ // schedule proof obligation
+ if ( k < kMax && !p->pPars->fShortest )
+ {
+ pThis->iFrame = k+1;
+ pThis->prio = Prio--;
+ Pdr_QueuePush( p, pThis );
+ }
+ else
+ {
+ Pdr_OblDeref( pThis );
+ }
+ }
+ else
+ {
+ assert( pCubeMin == NULL );
+ assert( pPred != NULL );
+ pThis->prio = Prio--;
+ Pdr_QueuePush( p, pThis );
+
+ pThis = Pdr_OblStart( pThis->iFrame-1, Prio--, pPred, Pdr_OblRef(pThis) );
+ Pdr_QueuePush( p, pThis );
+ }
+
+ // check the timeout
+ if ( p->timeToStop && time(NULL) > p->timeToStop )
+ return -1;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pdr_ManSolveInt( Pdr_Man_t * p )
+{
+ int fPrintClauses = 0;
+ Pdr_Set_t * pCube;
+ int k, RetValue = -1;
+ int clkTotal = clock();
+ int clkStart = clock();
+ p->timeToStop = p->pPars->nTimeOut ? time(NULL) + p->pPars->nTimeOut : 0;
+ assert( Vec_PtrSize(p->vSolvers) == 0 );
+ // create the first timeframe
+ Pdr_ManCreateSolver( p, (k = 0) );
+ while ( 1 )
+ {
+ p->nFrames = k;
+ assert( k == Vec_PtrSize(p->vSolvers)-1 );
+ RetValue = Pdr_ManCheckCube( p, k, NULL, &pCube, p->pPars->nConfLimit );
+ if ( RetValue == -1 )
+ {
+ if ( p->pPars->fVerbose )
+ Pdr_ManPrintProgress( p, 1, clock() - clkStart );
+ printf( "Reached conflict limit (%d).\n", p->pPars->nConfLimit );
+ p->pPars->iFrame = k;
+ return -1;
+ }
+ if ( RetValue == 0 )
+ {
+ RetValue = Pdr_ManBlockCube( p, pCube );
+ if ( RetValue == -1 )
+ {
+ if ( p->pPars->fVerbose )
+ Pdr_ManPrintProgress( p, 1, clock() - clkStart );
+ printf( "Reached conflict limit (%d).\n", p->pPars->nConfLimit );
+ p->pPars->iFrame = k;
+ return -1;
+ }
+ if ( RetValue == 0 )
+ {
+ if ( fPrintClauses )
+ {
+ printf( "*** Clauses after frame %d:\n", k );
+ Pdr_ManPrintClauses( p, 0 );
+ }
+ if ( p->pPars->fVerbose )
+ Pdr_ManPrintProgress( p, 1, clock() - clkStart );
+ p->pPars->iFrame = k;
+ return 0; // SAT
+ }
+ }
+ else
+ {
+ if ( p->pPars->fVerbose )
+ Pdr_ManPrintProgress( p, 1, clock() - clkStart );
+ // open a new timeframe
+ assert( pCube == NULL );
+ Pdr_ManSetPropertyOutput( p, k );
+ Pdr_ManCreateSolver( p, ++k );
+ if ( fPrintClauses )
+ {
+ printf( "*** Clauses after frame %d:\n", k );
+ Pdr_ManPrintClauses( p, 0 );
+ }
+ // push clauses into this timeframe
+ RetValue = Pdr_ManPushClauses( p );
+ if ( RetValue == -1 )
+ {
+ if ( p->pPars->fVerbose )
+ Pdr_ManPrintProgress( p, 1, clock() - clkStart );
+ printf( "Reached conflict limit (%d).\n", p->pPars->nConfLimit );
+ p->pPars->iFrame = k;
+ return -1;
+ }
+ if ( RetValue )
+ {
+ if ( p->pPars->fVerbose )
+ Pdr_ManPrintProgress( p, 1, clock() - clkStart );
+ Pdr_ManReportInvariant( p );
+ Pdr_ManVerifyInvariant( p );
+ p->pPars->iFrame = k;
+ return 1; // UNSAT
+ }
+ if ( p->pPars->fVerbose )
+ Pdr_ManPrintProgress( p, 0, clock() - clkStart );
+ clkStart = clock();
+ }
+
+ // check the timeout
+ if ( p->timeToStop && time(NULL) > p->timeToStop )
+ {
+ if ( fPrintClauses )
+ {
+ printf( "*** Clauses after frame %d:\n", k );
+ Pdr_ManPrintClauses( p, 0 );
+ }
+ if ( p->pPars->fVerbose )
+ Pdr_ManPrintProgress( p, 1, clock() - clkStart );
+ printf( "Reached timeout (%d seconds).\n", p->pPars->nTimeOut );
+ p->pPars->iFrame = k;
+ return -1;
+ }
+ if ( p->pPars->nFrameMax && k >= p->pPars->nFrameMax )
+ {
+ if ( p->pPars->fVerbose )
+ Pdr_ManPrintProgress( p, 1, clock() - clkStart );
+ printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nFrameMax );
+ p->pPars->iFrame = k;
+ return -1;
+ }
+ }
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pdr_ManSolve_( Aig_Man_t * pAig, Pdr_Par_t * pPars, Vec_Int_t ** pvPrioInit, Abc_Cex_t ** ppCex )
+{
+ Pdr_Man_t * p;
+ int RetValue;
+ int clk = clock();
+ p = Pdr_ManStart( pAig, pPars, pvPrioInit? *pvPrioInit : NULL );
+ RetValue = Pdr_ManSolveInt( p );
+ *ppCex = RetValue ? NULL : Pdr_ManDeriveCex( p );
+ if ( p->pPars->fDumpInv )
+ Pdr_ManDumpClauses( p, (char *)"inv.pla", RetValue==1 );
+
+// if ( *ppCex && pPars->fVerbose )
+// printf( "Found counter-example in frame %d after exploring %d frames.\n",
+// (*ppCex)->iFrame, p->nFrames );
+ p->tTotal += clock() - clk;
+ if ( pvPrioInit )
+ {
+ *pvPrioInit = p->vPrio;
+ p->vPrio = NULL;
+ }
+ Pdr_ManStop( p );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pdr_ManSolve( Aig_Man_t * pAig, Pdr_Par_t * pPars, Abc_Cex_t ** ppCex )
+{
+/*
+ Vec_Int_t * vPrioInit = NULL;
+ int RetValue, nTimeOut;
+ if ( pPars->nTimeOut > 0 )
+ return Pdr_ManSolve_( pAig, pPars, NULL, ppCex );
+ nTimeOut = pPars->nTimeOut;
+ pPars->nTimeOut = 10;
+ RetValue = Pdr_ManSolve_( pAig, pPars, &vPrioInit, ppCex );
+ pPars->nTimeOut = nTimeOut;
+ if ( RetValue == -1 )
+ RetValue = Pdr_ManSolve_( pAig, pPars, &vPrioInit, ppCex );
+ Vec_IntFree( vPrioInit );
+ return RetValue;
+*/
+ return Pdr_ManSolve_( pAig, pPars, NULL, ppCex );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/pdr/pdrInt.h b/src/proof/pdr/pdrInt.h
new file mode 100644
index 00000000..baf4ca02
--- /dev/null
+++ b/src/proof/pdr/pdrInt.h
@@ -0,0 +1,198 @@
+/**CFile****************************************************************
+
+ FileName [pdrInt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Property driven reachability.]
+
+ Synopsis [Internal declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - November 20, 2010.]
+
+ Revision [$Id: pdrInt.h,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__sat__pdr__pdrInt_h
+#define ABC__sat__pdr__pdrInt_h
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include "src/aig/saig/saig.h"
+#include "src/sat/cnf/cnf.h"
+#include "src/sat/bsat/satSolver.h"
+#include "pdr.h"
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Pdr_Set_t_ Pdr_Set_t;
+struct Pdr_Set_t_
+{
+ word Sign; // signature
+ int nRefs; // ref counter
+ int nTotal; // total literals
+ int nLits; // num flop literals
+ int Lits[0];
+};
+
+typedef struct Pdr_Obl_t_ Pdr_Obl_t;
+struct Pdr_Obl_t_
+{
+ int iFrame; // time frame
+ int prio; // priority
+ int nRefs; // reference counter
+ Pdr_Set_t * pState; // state cube
+ Pdr_Obl_t * pNext; // next one
+ Pdr_Obl_t * pLink; // queue link
+};
+
+typedef struct Pdr_Man_t_ Pdr_Man_t;
+struct Pdr_Man_t_
+{
+ // input problem
+ Pdr_Par_t * pPars; // parameters
+ Aig_Man_t * pAig; // user's AIG
+ // static CNF representation
+ Cnf_Dat_t * pCnf1; // CNF for this AIG
+ Vec_Int_t * vVar2Reg; // mapping of SAT var into registers
+ // dynamic CNF representation
+ Cnf_Dat_t * pCnf2; // CNF for this AIG
+ Vec_Int_t** pvId2Vars; // for each used ObjId, maps frame into SAT var
+ Vec_Ptr_t * vVar2Ids; // for each used frame, maps SAT var into ObjId
+ // data representation
+ Vec_Ptr_t * vSolvers; // SAT solvers
+ Vec_Vec_t * vClauses; // clauses by timeframe
+ Pdr_Obl_t * pQueue; // proof obligations
+ int * pOrder; // ordering of the lits
+ Vec_Int_t * vActVars; // the counter of activation variables
+ // internal use
+ Vec_Int_t * vPrio; // priority flops
+ Vec_Int_t * vLits; // array of literals
+ Vec_Int_t * vCiObjs; // cone leaves
+ Vec_Int_t * vCoObjs; // cone roots
+ Vec_Int_t * vCiVals; // cone leaf values
+ Vec_Int_t * vCoVals; // cone root values
+ Vec_Int_t * vNodes; // cone nodes
+ Vec_Int_t * vUndo; // cone undos
+ Vec_Int_t * vVisits; // intermediate
+ Vec_Int_t * vCi2Rem; // CIs to be removed
+ Vec_Int_t * vRes; // final result
+ Vec_Int_t * vSuppLits; // support literals
+ Pdr_Set_t * pCubeJust; // justification
+ // statistics
+ int nBlocks; // the number of times blockState was called
+ int nObligs; // the number of proof obligations derived
+ int nCubes; // the number of cubes derived
+ int nCalls; // the number of SAT calls
+ int nCallsS; // the number of SAT calls (sat)
+ int nCallsU; // the number of SAT calls (unsat)
+ int nStarts; // the number of SAT solver restarts
+ int nFrames; // frames explored
+ int nCasesSS;
+ int nCasesSU;
+ int nCasesUS;
+ int nCasesUU;
+ // runtime
+ int timeStart;
+ int timeToStop;
+ // time stats
+ int tSat;
+ int tSatSat;
+ int tSatUnsat;
+ int tGeneral;
+ int tPush;
+ int tTsim;
+ int tContain;
+ int tCnf;
+ int tTotal;
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static inline sat_solver * Pdr_ManSolver( Pdr_Man_t * p, int k ) { return (sat_solver *)Vec_PtrEntry(p->vSolvers, k); }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== pdrCex.c ==========================================================*/
+extern Abc_Cex_t * Pdr_ManDeriveCex( Pdr_Man_t * p );
+/*=== pdrCnf.c ==========================================================*/
+extern int Pdr_ObjSatVar( Pdr_Man_t * p, int k, Aig_Obj_t * pObj );
+extern int Pdr_ObjRegNum( Pdr_Man_t * p, int k, int iSatVar );
+extern int Pdr_ManFreeVar( Pdr_Man_t * p, int k );
+extern sat_solver * Pdr_ManNewSolver( sat_solver * pSat, Pdr_Man_t * p, int k, int fInit );
+/*=== pdrCore.c ==========================================================*/
+extern int Pdr_ManCheckContainment( Pdr_Man_t * p, int k, Pdr_Set_t * pSet );
+/*=== pdrInv.c ==========================================================*/
+extern void Pdr_ManPrintProgress( Pdr_Man_t * p, int fClose, int Time );
+extern void Pdr_ManPrintClauses( Pdr_Man_t * p, int kStart );
+extern void Pdr_ManDumpClauses( Pdr_Man_t * p, char * pFileName, int fProved );
+extern void Pdr_ManReportInvariant( Pdr_Man_t * p );
+extern void Pdr_ManVerifyInvariant( Pdr_Man_t * p );
+/*=== pdrMan.c ==========================================================*/
+extern Pdr_Man_t * Pdr_ManStart( Aig_Man_t * pAig, Pdr_Par_t * pPars, Vec_Int_t * vPrioInit );
+extern void Pdr_ManStop( Pdr_Man_t * p );
+extern Abc_Cex_t * Pdr_ManDeriveCex( Pdr_Man_t * p );
+/*=== pdrSat.c ==========================================================*/
+extern sat_solver * Pdr_ManCreateSolver( Pdr_Man_t * p, int k );
+extern sat_solver * Pdr_ManFetchSolver( Pdr_Man_t * p, int k );
+extern void Pdr_ManSetPropertyOutput( Pdr_Man_t * p, int k );
+extern Vec_Int_t * Pdr_ManCubeToLits( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, int fCompl, int fNext );
+extern Vec_Int_t * Pdr_ManLitsToCube( Pdr_Man_t * p, int k, int * pArray, int nArray );
+extern void Pdr_ManSolverAddClause( Pdr_Man_t * p, int k, Pdr_Set_t * pCube );
+extern void Pdr_ManCollectValues( Pdr_Man_t * p, int k, Vec_Int_t * vObjIds, Vec_Int_t * vValues );
+extern int Pdr_ManCheckCubeCs( Pdr_Man_t * p, int k, Pdr_Set_t * pCube );
+extern int Pdr_ManCheckCube( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, Pdr_Set_t ** ppPred, int nConfLimit );
+/*=== pdrTsim.c ==========================================================*/
+extern Pdr_Set_t * Pdr_ManTernarySim( Pdr_Man_t * p, int k, Pdr_Set_t * pCube );
+/*=== pdrUtil.c ==========================================================*/
+extern Pdr_Set_t * Pdr_SetAlloc( int nSize );
+extern Pdr_Set_t * Pdr_SetCreate( Vec_Int_t * vLits, Vec_Int_t * vPiLits );
+extern Pdr_Set_t * Pdr_SetCreateFrom( Pdr_Set_t * pSet, int iRemove );
+extern Pdr_Set_t * Pdr_SetCreateSubset( Pdr_Set_t * pSet, int * pLits, int nLits );
+extern Pdr_Set_t * Pdr_SetDup( Pdr_Set_t * pSet );
+extern Pdr_Set_t * Pdr_SetRef( Pdr_Set_t * p );
+extern void Pdr_SetDeref( Pdr_Set_t * p );
+extern int Pdr_SetContains( Pdr_Set_t * pOld, Pdr_Set_t * pNew );
+extern int Pdr_SetContainsSimple( Pdr_Set_t * pOld, Pdr_Set_t * pNew );
+extern int Pdr_SetIsInit( Pdr_Set_t * p, int iRemove );
+extern void Pdr_SetPrint( FILE * pFile, Pdr_Set_t * p, int nRegs, Vec_Int_t * vFlopCounts );
+extern int Pdr_SetCompare( Pdr_Set_t ** pp1, Pdr_Set_t ** pp2 );
+extern Pdr_Obl_t * Pdr_OblStart( int k, int prio, Pdr_Set_t * pState, Pdr_Obl_t * pNext );
+extern Pdr_Obl_t * Pdr_OblRef( Pdr_Obl_t * p );
+extern void Pdr_OblDeref( Pdr_Obl_t * p );
+extern int Pdr_QueueIsEmpty( Pdr_Man_t * p );
+extern Pdr_Obl_t * Pdr_QueueHead( Pdr_Man_t * p );
+extern Pdr_Obl_t * Pdr_QueuePop( Pdr_Man_t * p );
+extern void Pdr_QueuePush( Pdr_Man_t * p, Pdr_Obl_t * pObl );
+extern void Pdr_QueuePrint( Pdr_Man_t * p );
+extern void Pdr_QueueStop( Pdr_Man_t * p );
+extern int Pdr_ManCubeJust( Pdr_Man_t * p, int k, Pdr_Set_t * pCube );
+
+ABC_NAMESPACE_HEADER_END
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/proof/pdr/pdrInv.c b/src/proof/pdr/pdrInv.c
new file mode 100644
index 00000000..30d1145d
--- /dev/null
+++ b/src/proof/pdr/pdrInv.c
@@ -0,0 +1,374 @@
+/**CFile****************************************************************
+
+ FileName [pdrInv.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Property driven reachability.]
+
+ Synopsis [Invariant computation, printing, verification.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - November 20, 2010.]
+
+ Revision [$Id: pdrInv.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "pdrInt.h"
+#include "src/base/abc/abc.h" // for Abc_NtkCollectCioNames()
+#include "src/base/main/main.h" // for Abc_FrameReadGlobalFrame()
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pdr_ManPrintProgress( Pdr_Man_t * p, int fClose, int Time )
+{
+ static int PastSize;
+ Vec_Ptr_t * vVec;
+ int i, ThisSize, Length, LengthStart;
+ if ( Vec_PtrSize(p->vSolvers) < 2 )
+ return;
+ // count the total length of the printout
+ Length = 0;
+ Vec_VecForEachLevel( p->vClauses, vVec, i )
+ Length += 1 + Abc_Base10Log(Vec_PtrSize(vVec)+1);
+ // determine the starting point
+ LengthStart = Abc_MaxInt( 0, Length - 70 );
+ printf( "%3d :", Vec_PtrSize(p->vSolvers)-1 );
+ ThisSize = 6;
+ if ( LengthStart > 0 )
+ {
+ printf( " ..." );
+ ThisSize += 4;
+ }
+ Length = 0;
+ Vec_VecForEachLevel( p->vClauses, vVec, i )
+ {
+ if ( Length < LengthStart )
+ {
+ Length += 1 + Abc_Base10Log(Vec_PtrSize(vVec)+1);
+ continue;
+ }
+ printf( " %d", Vec_PtrSize(vVec) );
+ Length += 1 + Abc_Base10Log(Vec_PtrSize(vVec)+1);
+ ThisSize += 1 + Abc_Base10Log(Vec_PtrSize(vVec)+1);
+ }
+ if ( fClose )
+ {
+ for ( i = 0; i < PastSize - ThisSize; i++ )
+ printf( " " );
+ printf( "\n" );
+ }
+ else
+ {
+ printf( "\r" );
+ PastSize = ThisSize;
+ }
+// printf(" %.2f sec", (float)(Time)/(float)(CLOCKS_PER_SEC));
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts how many times each flop appears in the set of cubes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Pdr_ManCountFlops( Pdr_Man_t * p, Vec_Ptr_t * vCubes )
+{
+ Vec_Int_t * vFlopCount;
+ Pdr_Set_t * pCube;
+ int i, n;
+ vFlopCount = Vec_IntStart( Aig_ManRegNum(p->pAig) );
+ Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i )
+ for ( n = 0; n < pCube->nLits; n++ )
+ {
+ assert( pCube->Lits[n] >= 0 && pCube->Lits[n] < 2*Aig_ManRegNum(p->pAig) );
+ Vec_IntAddToEntry( vFlopCount, pCube->Lits[n] >> 1, 1 );
+ }
+ return vFlopCount;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pdr_ManFindInvariantStart( Pdr_Man_t * p )
+{
+ Vec_Ptr_t * vArrayK;
+ int k, kMax = Vec_PtrSize(p->vSolvers)-1;
+ Vec_VecForEachLevelStartStop( p->vClauses, vArrayK, k, 1, kMax+1 )
+ if ( Vec_PtrSize(vArrayK) == 0 )
+ return k;
+// return -1;
+ // if there is no starting point (as in case of SAT or undecided), return the last frame
+// printf( "The last timeframe contains %d clauses.\n", Vec_PtrSize(Vec_VecEntry(p->vClauses, kMax)) );
+ return kMax;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of variables used in the clauses.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Pdr_ManCollectCubes( Pdr_Man_t * p, int kStart )
+{
+ Vec_Ptr_t * vResult;
+ Vec_Ptr_t * vArrayK;
+ Pdr_Set_t * pSet;
+ int i, j;
+ vResult = Vec_PtrAlloc( 100 );
+ Vec_VecForEachLevelStart( p->vClauses, vArrayK, i, kStart )
+ Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pSet, j )
+ Vec_PtrPush( vResult, pSet );
+ return vResult;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of variables used in the clauses.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pdr_ManCountVariables( Pdr_Man_t * p, int kStart )
+{
+ Vec_Int_t * vFlopCounts;
+ Vec_Ptr_t * vCubes;
+ int i, Entry, Counter = 0;
+ vCubes = Pdr_ManCollectCubes( p, kStart );
+ vFlopCounts = Pdr_ManCountFlops( p, vCubes );
+ Vec_IntForEachEntry( vFlopCounts, Entry, i )
+ Counter += (Entry > 0);
+ Vec_IntFreeP( &vFlopCounts );
+ Vec_PtrFree( vCubes );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pdr_ManPrintClauses( Pdr_Man_t * p, int kStart )
+{
+ Vec_Ptr_t * vArrayK;
+ Pdr_Set_t * pCube;
+ int i, k, Counter = 0;
+ Vec_VecForEachLevelStart( p->vClauses, vArrayK, k, kStart )
+ {
+ Vec_PtrSort( vArrayK, (int (*)(void))Pdr_SetCompare );
+ Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCube, i )
+ {
+ printf( "C=%4d. F=%4d ", Counter++, k );
+ Pdr_SetPrint( stdout, pCube, Aig_ManRegNum(p->pAig), NULL );
+ printf( "\n" );
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pdr_ManDumpClauses( Pdr_Man_t * p, char * pFileName, int fProved )
+{
+ int fUseSupp = 1;
+ FILE * pFile;
+ Vec_Int_t * vFlopCounts;
+ Vec_Ptr_t * vCubes;
+ Pdr_Set_t * pCube;
+ char ** pNamesCi;
+ int i, kStart;
+ // create file
+ pFile = fopen( pFileName, "w" );
+ if ( pFile == NULL )
+ {
+ printf( "Cannot open file \"%s\" for writing invariant.\n", pFileName );
+ return;
+ }
+ // collect cubes
+ kStart = Pdr_ManFindInvariantStart( p );
+ vCubes = Pdr_ManCollectCubes( p, kStart );
+ Vec_PtrSort( vCubes, (int (*)(void))Pdr_SetCompare );
+ // collect variable appearances
+ vFlopCounts = fUseSupp ? Pdr_ManCountFlops( p, vCubes ) : NULL;
+ // output the header
+ if ( fProved )
+ fprintf( pFile, "# Inductive invariant for \"%s\"\n", p->pAig->pName );
+ else
+ fprintf( pFile, "# Clauses of the last timeframe for \"%s\"\n", p->pAig->pName );
+ fprintf( pFile, "# generated by PDR in ABC on %s\n", Aig_TimeStamp() );
+ fprintf( pFile, ".i %d\n", fUseSupp ? Pdr_ManCountVariables(p, kStart) : Aig_ManRegNum(p->pAig) );
+ fprintf( pFile, ".o 1\n" );
+ fprintf( pFile, ".p %d\n", Vec_PtrSize(vCubes) );
+ // output flop names
+ pNamesCi = Abc_NtkCollectCioNames( Abc_FrameReadNtk( Abc_FrameReadGlobalFrame() ), 0 );
+ if ( pNamesCi )
+ {
+ fprintf( pFile, ".ilb" );
+ for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ )
+ if ( !fUseSupp || Vec_IntEntry( vFlopCounts, i ) )
+ fprintf( pFile, " %s", pNamesCi[Saig_ManPiNum(p->pAig) + i] );
+ fprintf( pFile, "\n" );
+ ABC_FREE( pNamesCi );
+ fprintf( pFile, ".ob inv\n" );
+ }
+ // output cubes
+ Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i )
+ {
+ Pdr_SetPrint( pFile, pCube, Aig_ManRegNum(p->pAig), vFlopCounts );
+ fprintf( pFile, " 1\n" );
+ }
+ fprintf( pFile, ".e\n\n" );
+ fclose( pFile );
+ Vec_IntFreeP( &vFlopCounts );
+ Vec_PtrFree( vCubes );
+ if ( fProved )
+ printf( "Inductive invariant was written into file \"%s\".\n", pFileName );
+ else
+ printf( "Clauses of the last timeframe were written into file \"%s\".\n", pFileName );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pdr_ManReportInvariant( Pdr_Man_t * p )
+{
+ Vec_Ptr_t * vCubes;
+ int kStart = Pdr_ManFindInvariantStart( p );
+ vCubes = Pdr_ManCollectCubes( p, kStart );
+ printf( "Invariant F[%d] : %d clauses with %d flops (out of %d)\n",
+ kStart, Vec_PtrSize(vCubes), Pdr_ManCountVariables(p, kStart), Aig_ManRegNum(p->pAig) );
+ Vec_PtrFree( vCubes );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pdr_ManVerifyInvariant( Pdr_Man_t * p )
+{
+ sat_solver * pSat;
+ Vec_Int_t * vLits;
+ Vec_Ptr_t * vCubes;
+ Pdr_Set_t * pCube;
+ int i, kStart, kThis, RetValue, Counter = 0, clk = clock();
+ // collect cubes used in the inductive invariant
+ kStart = Pdr_ManFindInvariantStart( p );
+ vCubes = Pdr_ManCollectCubes( p, kStart );
+ // create solver with the cubes
+ kThis = Vec_PtrSize(p->vSolvers);
+ pSat = Pdr_ManCreateSolver( p, kThis );
+ // add the property output
+ Pdr_ManSetPropertyOutput( p, kThis );
+ // add the clauses
+ Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i )
+ {
+ vLits = Pdr_ManCubeToLits( p, kThis, pCube, 1, 0 );
+ RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) );
+ assert( RetValue );
+ sat_solver_compress( pSat );
+ }
+ // check each clause
+ Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i )
+ {
+ vLits = Pdr_ManCubeToLits( p, kThis, pCube, 0, 1 );
+ RetValue = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), 0, 0, 0, 0 );
+ if ( RetValue != l_False )
+ {
+ printf( "Verification of clause %d failed.\n", i );
+ Counter++;
+ }
+ }
+ if ( Counter )
+ printf( "Verification of %d clauses has failed.\n", Counter );
+ else
+ {
+ printf( "Verification of invariant with %d clauses was successful. ", Vec_PtrSize(vCubes) );
+ Abc_PrintTime( 1, "Time", clock() - clk );
+ }
+// sat_solver_delete( pSat );
+ Vec_PtrFree( vCubes );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/pdr/pdrMan.c b/src/proof/pdr/pdrMan.c
new file mode 100644
index 00000000..33c94d40
--- /dev/null
+++ b/src/proof/pdr/pdrMan.c
@@ -0,0 +1,194 @@
+/**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"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**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->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 );
+ // internal use
+ p->vPrio = vPrioInit ? vPrioInit : Vec_IntStart( Aig_ManRegNum(pAig) ); // priority flops
+ 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->vSuppLits= Vec_IntAlloc( 100 ); // support literals
+ p->pCubeJust= Pdr_SetAlloc( Saig_ManRegNum(pAig) );
+ // 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) );
+ p->timeStart = clock();
+ 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;
+ Aig_ManCleanMarkAB( p->pAig );
+ if ( p->pPars->fVerbose )
+ {
+ printf( "Block =%5d Oblig =%6d Clause =%6d Call =%6d (sat=%.1f%%) Start =%4d\n",
+ p->nBlocks, p->nObligs, p->nCubes, p->nCalls, 100.0 * p->nCallsS / p->nCalls, 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( "TOTAL ", p->tTotal, p->tTotal );
+ }
+// printf( "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++ )
+ Vec_IntFreeP( &p->pvId2Vars[i] );
+ ABC_FREE( p->pvId2Vars );
+ Vec_VecFreeP( (Vec_Vec_t **)&p->vVar2Ids );
+ // 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_IntFree( p->vSuppLits ); // support literals
+ ABC_FREE( p->pCubeJust );
+ // 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->pPars->iOutput==-1)? 0 : p->pPars->iOutput;
+ 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 ( lit_sign(Lit) )
+ continue;
+ assert( lit_var(Lit) < pCex->nPis );
+ Abc_InfoSetBit( pCex->pData, pCex->nRegs + f * pCex->nPis + lit_var(Lit) );
+ }
+ assert( f == nFrames );
+ return pCex;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/pdr/pdrSat.c b/src/proof/pdr/pdrSat.c
new file mode 100644
index 00000000..c191654a
--- /dev/null
+++ b/src/proof/pdr/pdrSat.c
@@ -0,0 +1,373 @@
+/**CFile****************************************************************
+
+ FileName [pdrSat.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Property driven reachability.]
+
+ Synopsis [SAT solver procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - November 20, 2010.]
+
+ Revision [$Id: pdrSat.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "pdrInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Creates new SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+sat_solver * Pdr_ManCreateSolver( Pdr_Man_t * p, int k )
+{
+ sat_solver * pSat;
+ assert( Vec_PtrSize(p->vSolvers) == k );
+ assert( Vec_VecSize(p->vClauses) == k );
+ assert( Vec_IntSize(p->vActVars) == k );
+ // create new solver
+ pSat = sat_solver_new();
+ pSat = Pdr_ManNewSolver( pSat, p, k, (int)(k == 0) );
+ Vec_PtrPush( p->vSolvers, pSat );
+ Vec_VecExpand( p->vClauses, k );
+ Vec_IntPush( p->vActVars, 0 );
+ // add property cone
+ Pdr_ObjSatVar( p, k, Aig_ManPo(p->pAig, (p->pPars->iOutput==-1)?0:p->pPars->iOutput ) );
+ return pSat;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns old or restarted solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+sat_solver * Pdr_ManFetchSolver( Pdr_Man_t * p, int k )
+{
+ sat_solver * pSat;
+ Vec_Ptr_t * vArrayK;
+ Pdr_Set_t * pCube;
+ int i, j;
+ pSat = Pdr_ManSolver(p, k);
+ if ( Vec_IntEntry(p->vActVars, k) < p->pPars->nRecycle )
+ return pSat;
+ assert( k < Vec_PtrSize(p->vSolvers) - 1 );
+ p->nStarts++;
+// sat_solver_delete( pSat );
+// pSat = sat_solver_new();
+ sat_solver_rollback( pSat );
+ // create new SAT solver
+ pSat = Pdr_ManNewSolver( pSat, p, k, (int)(k == 0) );
+ // write new SAT solver
+ Vec_PtrWriteEntry( p->vSolvers, k, pSat );
+ Vec_IntWriteEntry( p->vActVars, k, 0 );
+ // set the property output
+ Pdr_ManSetPropertyOutput( p, k );
+ // add the clauses
+ Vec_VecForEachLevelStart( p->vClauses, vArrayK, i, k )
+ Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCube, j )
+ Pdr_ManSolverAddClause( p, k, pCube );
+ return pSat;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts SAT variables into register IDs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Pdr_ManLitsToCube( Pdr_Man_t * p, int k, int * pArray, int nArray )
+{
+ int i, RegId;
+ Vec_IntClear( p->vLits );
+ for ( i = 0; i < nArray; i++ )
+ {
+ RegId = Pdr_ObjRegNum( p, k, lit_var(pArray[i]) );
+ if ( RegId == -1 )
+ continue;
+ assert( RegId >= 0 && RegId < Aig_ManRegNum(p->pAig) );
+ Vec_IntPush( p->vLits, toLitCond(RegId, !lit_sign(pArray[i])) );
+ }
+ assert( Vec_IntSize(p->vLits) >= 0 && Vec_IntSize(p->vLits) <= nArray );
+ return p->vLits;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts the cube in terms of RO numbers into array of CNF literals.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Pdr_ManCubeToLits( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, int fCompl, int fNext )
+{
+ Aig_Obj_t * pObj;
+ int i, iVar, iVarMax = 0;
+ int clk = clock();
+ Vec_IntClear( p->vLits );
+ for ( i = 0; i < pCube->nLits; i++ )
+ {
+ if ( pCube->Lits[i] == -1 )
+ continue;
+ if ( fNext )
+ pObj = Saig_ManLi( p->pAig, lit_var(pCube->Lits[i]) );
+ else
+ pObj = Saig_ManLo( p->pAig, lit_var(pCube->Lits[i]) );
+ iVar = Pdr_ObjSatVar( p, k, pObj ); assert( iVar >= 0 );
+ iVarMax = Abc_MaxInt( iVarMax, iVar );
+ Vec_IntPush( p->vLits, toLitCond( iVar, fCompl ^ lit_sign(pCube->Lits[i]) ) );
+ }
+// sat_solver_setnvars( Pdr_ManSolver(p, k), iVarMax + 1 );
+ p->tCnf += clock() - clk;
+ return p->vLits;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sets the property output to 0 (sat) forever.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pdr_ManSetPropertyOutput( Pdr_Man_t * p, int k )
+{
+ sat_solver * pSat;
+ int Lit, RetValue;
+ pSat = Pdr_ManSolver(p, k);
+ Lit = toLitCond( Pdr_ObjSatVar(p, k, Aig_ManPo(p->pAig, (p->pPars->iOutput==-1)?0:p->pPars->iOutput)), 1 ); // neg literal
+ RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 );
+ assert( RetValue == 1 );
+ sat_solver_compress( pSat );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Adds one clause in terms of ROs to the k-th SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pdr_ManSolverAddClause( Pdr_Man_t * p, int k, Pdr_Set_t * pCube )
+{
+ sat_solver * pSat;
+ Vec_Int_t * vLits;
+ int RetValue;
+ pSat = Pdr_ManSolver(p, k);
+ vLits = Pdr_ManCubeToLits( p, k, pCube, 1, 0 );
+ RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) );
+ assert( RetValue == 1 );
+ sat_solver_compress( pSat );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects values of the RO/RI variables in k-th SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pdr_ManCollectValues( Pdr_Man_t * p, int k, Vec_Int_t * vObjIds, Vec_Int_t * vValues )
+{
+ sat_solver * pSat;
+ Aig_Obj_t * pObj;
+ int iVar, i;
+ Vec_IntClear( vValues );
+ pSat = Pdr_ManSolver(p, k);
+ Aig_ManForEachObjVec( vObjIds, p->pAig, pObj, i )
+ {
+ iVar = Pdr_ObjSatVar( p, k, pObj ); assert( iVar >= 0 );
+ Vec_IntPush( vValues, sat_solver_var_value(pSat, iVar) );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks if the cube holds (UNSAT) in the given timeframe.]
+
+ Description [Return 1/0 if cube or property are proved to hold/fail
+ in k-th timeframe. Returns the predecessor bad state in ppPred.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pdr_ManCheckCubeCs( Pdr_Man_t * p, int k, Pdr_Set_t * pCube )
+{
+ sat_solver * pSat;
+ Vec_Int_t * vLits;
+ int RetValue;
+ pSat = Pdr_ManFetchSolver( p, k );
+ vLits = Pdr_ManCubeToLits( p, k, pCube, 0, 0 );
+ RetValue = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), 0, 0, 0, 0 );
+ if ( RetValue == l_Undef )
+ return -1;
+ return (RetValue == l_False);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks if the cube holds (UNSAT) in the given timeframe.]
+
+ Description [Return 1/0 if cube or property are proved to hold/fail
+ in k-th timeframe. Returns the predecessor bad state in ppPred.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pdr_ManCheckCube( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, Pdr_Set_t ** ppPred, int nConfLimit )
+{
+ int fUseLit = 1;
+ int fLitUsed = 0;
+ sat_solver * pSat;
+ Vec_Int_t * vLits;
+ int Lit, RetValue, clk;
+ p->nCalls++;
+ pSat = Pdr_ManFetchSolver( p, k );
+ if ( pCube == NULL ) // solve the property
+ {
+ clk = clock();
+ Lit = toLit( Pdr_ObjSatVar(p, k, Aig_ManPo(p->pAig, (p->pPars->iOutput==-1)?0:p->pPars->iOutput)) ); // pos literal (property fails)
+ RetValue = sat_solver_solve( pSat, &Lit, &Lit + 1, nConfLimit, 0, 0, 0 );
+ if ( RetValue == l_Undef )
+ return -1;
+ }
+ else // check relative containment in terms of next states
+ {
+ if ( fUseLit )
+ {
+ fLitUsed = 1;
+ Vec_IntAddToEntry( p->vActVars, k, 1 );
+ // add the cube in terms of current state variables
+ vLits = Pdr_ManCubeToLits( p, k, pCube, 1, 0 );
+ // add activation literal
+ Lit = toLit( Pdr_ManFreeVar(p, k) );
+ // add activation literal
+ Vec_IntPush( vLits, Lit );
+ RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) );
+ assert( RetValue == 1 );
+ sat_solver_compress( pSat );
+ // create assumptions
+ vLits = Pdr_ManCubeToLits( p, k, pCube, 0, 1 );
+ // add activation literal
+ Vec_IntPush( vLits, lit_neg(Lit) );
+ }
+ else
+ vLits = Pdr_ManCubeToLits( p, k, pCube, 0, 1 );
+
+ // solve
+ clk = clock();
+ RetValue = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), nConfLimit, 0, 0, 0 );
+ if ( RetValue == l_Undef )
+ return -1;
+/*
+ if ( RetValue == l_True )
+ {
+ int RetValue2 = Pdr_ManCubeJust( p, k, pCube );
+ if ( RetValue2 )
+ p->nCasesSS++;
+ else
+ p->nCasesSU++;
+ }
+ else
+ {
+ int RetValue2 = Pdr_ManCubeJust( p, k, pCube );
+ if ( RetValue2 )
+ p->nCasesUS++;
+ else
+ p->nCasesUU++;
+ }
+*/
+ }
+ clk = clock() - clk;
+ p->tSat += clk;
+ assert( RetValue != l_Undef );
+ if ( RetValue == l_False )
+ {
+ p->tSatUnsat += clk;
+ p->nCallsU++;
+ if ( ppPred )
+ *ppPred = NULL;
+ RetValue = 1;
+ }
+ else // if ( RetValue == l_True )
+ {
+ p->tSatSat += clk;
+ p->nCallsS++;
+ if ( ppPred )
+ *ppPred = Pdr_ManTernarySim( p, k, pCube );
+ RetValue = 0;
+ }
+
+/* // for some reason, it does not work...
+ if ( fLitUsed )
+ {
+ int RetValue;
+ Lit = lit_neg(Lit);
+ RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 );
+ assert( RetValue == 1 );
+ sat_solver_compress( pSat );
+ }
+*/
+ return RetValue;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/pdr/pdrTsim.c b/src/proof/pdr/pdrTsim.c
new file mode 100644
index 00000000..6fec1605
--- /dev/null
+++ b/src/proof/pdr/pdrTsim.c
@@ -0,0 +1,450 @@
+/**CFile****************************************************************
+
+ FileName [pdrTsim.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Property driven reachability.]
+
+ Synopsis [Ternary simulation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - November 20, 2010.]
+
+ Revision [$Id: pdrTsim.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "pdrInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define PDR_ZER 1
+#define PDR_ONE 2
+#define PDR_UND 3
+
+static inline int Pdr_ManSimInfoNot( int Value )
+{
+ if ( Value == PDR_ZER )
+ return PDR_ONE;
+ if ( Value == PDR_ONE )
+ return PDR_ZER;
+ return PDR_UND;
+}
+
+static inline int Pdr_ManSimInfoAnd( int Value0, int Value1 )
+{
+ if ( Value0 == PDR_ZER || Value1 == PDR_ZER )
+ return PDR_ZER;
+ if ( Value0 == PDR_ONE && Value1 == PDR_ONE )
+ return PDR_ONE;
+ return PDR_UND;
+}
+
+static inline int Pdr_ManSimInfoGet( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+ return 3 & (p->pTerSimData[Aig_ObjId(pObj) >> 4] >> ((Aig_ObjId(pObj) & 15) << 1));
+}
+
+static inline void Pdr_ManSimInfoSet( Aig_Man_t * p, Aig_Obj_t * pObj, int Value )
+{
+ assert( Value >= PDR_ZER && Value <= PDR_UND );
+ Value ^= Pdr_ManSimInfoGet( p, pObj );
+ p->pTerSimData[Aig_ObjId(pObj) >> 4] ^= (Value << ((Aig_ObjId(pObj) & 15) << 1));
+}
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Marks the TFI cone and collects CIs and nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pdr_ManCollectCone_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vCiObjs, Vec_Int_t * vNodes )
+{
+ assert( !Aig_IsComplement(pObj) );
+ if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+ return;
+ Aig_ObjSetTravIdCurrent(pAig, pObj);
+ if ( Aig_ObjIsPi(pObj) )
+ {
+ Vec_IntPush( vCiObjs, Aig_ObjId(pObj) );
+ return;
+ }
+ Pdr_ManCollectCone_rec( pAig, Aig_ObjFanin0(pObj), vCiObjs, vNodes );
+ if ( Aig_ObjIsPo(pObj) )
+ return;
+ Pdr_ManCollectCone_rec( pAig, Aig_ObjFanin1(pObj), vCiObjs, vNodes );
+ Vec_IntPush( vNodes, Aig_ObjId(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks the TFI cone and collects CIs and nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pdr_ManCollectCone( Aig_Man_t * pAig, Vec_Int_t * vCoObjs, Vec_Int_t * vCiObjs, Vec_Int_t * vNodes )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Vec_IntClear( vCiObjs );
+ Vec_IntClear( vNodes );
+ Aig_ManIncrementTravId( pAig );
+ Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) );
+ Aig_ManForEachObjVec( vCoObjs, pAig, pObj, i )
+ Pdr_ManCollectCone_rec( pAig, pObj, vCiObjs, vNodes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs ternary simulation for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pdr_ManExtendOneEval( Aig_Man_t * pAig, Aig_Obj_t * pObj )
+{
+ int Value0, Value1, Value;
+ Value0 = Pdr_ManSimInfoGet( pAig, Aig_ObjFanin0(pObj) );
+ if ( Aig_ObjFaninC0(pObj) )
+ Value0 = Pdr_ManSimInfoNot( Value0 );
+ if ( Aig_ObjIsPo(pObj) )
+ {
+ Pdr_ManSimInfoSet( pAig, pObj, Value0 );
+ return Value0;
+ }
+ assert( Aig_ObjIsNode(pObj) );
+ Value1 = Pdr_ManSimInfoGet( pAig, Aig_ObjFanin1(pObj) );
+ if ( Aig_ObjFaninC1(pObj) )
+ Value1 = Pdr_ManSimInfoNot( Value1 );
+ Value = Pdr_ManSimInfoAnd( Value0, Value1 );
+ Pdr_ManSimInfoSet( pAig, pObj, Value );
+ return Value;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs ternary simulation for one design.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pdr_ManSimDataInit( Aig_Man_t * pAig,
+ Vec_Int_t * vCiObjs, Vec_Int_t * vCiVals, Vec_Int_t * vNodes,
+ Vec_Int_t * vCoObjs, Vec_Int_t * vCoVals, Vec_Int_t * vCi2Rem )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ // set the CI values
+ Pdr_ManSimInfoSet( pAig, Aig_ManConst1(pAig), PDR_ONE );
+ Aig_ManForEachObjVec( vCiObjs, pAig, pObj, i )
+ Pdr_ManSimInfoSet( pAig, pObj, (Vec_IntEntry(vCiVals, i)?PDR_ONE:PDR_ZER) );
+ // set the FOs to remove
+ if ( vCi2Rem != NULL )
+ Aig_ManForEachObjVec( vCi2Rem, pAig, pObj, i )
+ Pdr_ManSimInfoSet( pAig, pObj, PDR_UND );
+ // perform ternary simulation
+ Aig_ManForEachObjVec( vNodes, pAig, pObj, i )
+ Pdr_ManExtendOneEval( pAig, pObj );
+ // transfer results to the output
+ Aig_ManForEachObjVec( vCoObjs, pAig, pObj, i )
+ Pdr_ManExtendOneEval( pAig, pObj );
+ // check the results
+ Aig_ManForEachObjVec( vCoObjs, pAig, pObj, i )
+ if ( Pdr_ManSimInfoGet( pAig, pObj ) != (Vec_IntEntry(vCoVals, i)?PDR_ONE:PDR_ZER) )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Tries to assign ternary value to one of the CIs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pdr_ManExtendOne( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vUndo, Vec_Int_t * vVis )
+{
+ Aig_Obj_t * pFanout;
+ int i, k, iFanout, Value, Value2;
+ assert( Saig_ObjIsLo(pAig, pObj) );
+ assert( Aig_ObjIsTravIdCurrent(pAig, pObj) );
+ // save original value
+ Value = Pdr_ManSimInfoGet( pAig, pObj );
+ assert( Value == PDR_ZER || Value == PDR_ONE );
+ Vec_IntPush( vUndo, Aig_ObjId(pObj) );
+ Vec_IntPush( vUndo, Value );
+ // update original value
+ Pdr_ManSimInfoSet( pAig, pObj, PDR_UND );
+ // traverse
+ Vec_IntClear( vVis );
+ Vec_IntPush( vVis, Aig_ObjId(pObj) );
+ Aig_ManForEachObjVec( vVis, pAig, pObj, i )
+ {
+ Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, k )
+ {
+ if ( !Aig_ObjIsTravIdCurrent(pAig, pFanout) )
+ continue;
+ assert( Aig_ObjId(pObj) < Aig_ObjId(pFanout) );
+ Value = Pdr_ManSimInfoGet( pAig, pFanout );
+ if ( Value == PDR_UND )
+ continue;
+ Value2 = Pdr_ManExtendOneEval( pAig, pFanout );
+ if ( Value2 == Value )
+ continue;
+ assert( Value2 == PDR_UND );
+ Vec_IntPush( vUndo, Aig_ObjId(pFanout) );
+ Vec_IntPush( vUndo, Value );
+ if ( Aig_ObjIsPo(pFanout) )
+ return 0;
+ assert( Aig_ObjIsNode(pFanout) );
+ Vec_IntPushOrder( vVis, Aig_ObjId(pFanout) );
+ }
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Undoes the partial results of ternary simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pdr_ManExtendUndo( Aig_Man_t * pAig, Vec_Int_t * vUndo )
+{
+ Aig_Obj_t * pObj;
+ int i, Value;
+ Aig_ManForEachObjVec( vUndo, pAig, pObj, i )
+ {
+ Value = Vec_IntEntry(vUndo, ++i);
+ assert( Pdr_ManSimInfoGet(pAig, pObj) == PDR_UND );
+ Pdr_ManSimInfoSet( pAig, pObj, Value );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the resulting cube.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pdr_ManDeriveResult( Aig_Man_t * pAig, Vec_Int_t * vCiObjs, Vec_Int_t * vCiVals, Vec_Int_t * vCi2Rem, Vec_Int_t * vRes, Vec_Int_t * vPiLits )
+{
+ Aig_Obj_t * pObj;
+ int i, Lit;
+ // mark removed flop outputs
+ Aig_ManIncrementTravId( pAig );
+ Aig_ManForEachObjVec( vCi2Rem, pAig, pObj, i )
+ {
+ assert( Saig_ObjIsLo( pAig, pObj ) );
+ Aig_ObjSetTravIdCurrent(pAig, pObj);
+ }
+ // collect flop outputs that are not marked
+ Vec_IntClear( vRes );
+ Vec_IntClear( vPiLits );
+ Aig_ManForEachObjVec( vCiObjs, pAig, pObj, i )
+ {
+ if ( Saig_ObjIsPi(pAig, pObj) )
+ {
+ Lit = toLitCond( Aig_ObjPioNum(pObj), (Vec_IntEntry(vCiVals, i) == 0) );
+ Vec_IntPush( vPiLits, Lit );
+ continue;
+ }
+ assert( Saig_ObjIsLo(pAig, pObj) );
+ if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
+ continue;
+ Lit = toLitCond( Aig_ObjPioNum(pObj) - Saig_ManPiNum(pAig), (Vec_IntEntry(vCiVals, i) == 0) );
+ Vec_IntPush( vRes, Lit );
+ }
+ if ( Vec_IntSize(vRes) == 0 )
+ Vec_IntPush(vRes, 0);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the resulting cube.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pdr_ManPrintCex( Aig_Man_t * pAig, Vec_Int_t * vCiObjs, Vec_Int_t * vCiVals, Vec_Int_t * vCi2Rem )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ char * pBuff = ABC_ALLOC( char, Aig_ManPiNum(pAig)+1 );
+ for ( i = 0; i < Aig_ManPiNum(pAig); i++ )
+ pBuff[i] = '-';
+ pBuff[i] = 0;
+ Aig_ManForEachObjVec( vCiObjs, pAig, pObj, i )
+ pBuff[Aig_ObjPioNum(pObj)] = (Vec_IntEntry(vCiVals, i)? '1':'0');
+ if ( vCi2Rem )
+ Aig_ManForEachObjVec( vCi2Rem, pAig, pObj, i )
+ pBuff[Aig_ObjPioNum(pObj)] = 'x';
+ printf( "%s\n", pBuff );
+ ABC_FREE( pBuff );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Shrinks values using ternary simulation.]
+
+ Description [The cube contains the set of flop index literals which,
+ when converted into a clause and applied to the combinational outputs,
+ led to a satisfiable SAT run in frame k (values stored in the SAT solver).
+ If the cube is NULL, it is assumed that the first property output was
+ asserted and failed.
+ The resulting array is a set of flop index literals that asserts the COs.
+ Priority contains 0 for i-th entry if the i-th FF is desirable to remove.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Pdr_Set_t * Pdr_ManTernarySim( Pdr_Man_t * p, int k, Pdr_Set_t * pCube )
+{
+ Vec_Int_t * vPrio = p->vPrio; // priority flops (flop indices)
+ Vec_Int_t * vPiLits = p->vLits; // array of literals (0/1 PI values)
+ Vec_Int_t * vCiObjs = p->vCiObjs; // cone leaves (CI obj IDs)
+ Vec_Int_t * vCoObjs = p->vCoObjs; // cone roots (CO obj IDs)
+ Vec_Int_t * vCiVals = p->vCiVals; // cone leaf values (0/1 CI values)
+ Vec_Int_t * vCoVals = p->vCoVals; // cone root values (0/1 CO values)
+ Vec_Int_t * vNodes = p->vNodes; // cone nodes (node obj IDs)
+ Vec_Int_t * vUndo = p->vUndo; // cone undos (node obj IDs)
+ Vec_Int_t * vVisits = p->vVisits; // intermediate (obj IDs)
+ Vec_Int_t * vCi2Rem = p->vCi2Rem; // CIs to be removed (CI obj IDs)
+ Vec_Int_t * vRes = p->vRes; // final result (flop literals)
+ Aig_Obj_t * pObj;
+ int i, Entry, RetValue;
+ int clk = clock();
+
+ // collect CO objects
+ Vec_IntClear( vCoObjs );
+ if ( pCube == NULL ) // the target is the property output
+ Vec_IntPush( vCoObjs, Aig_ObjId(Aig_ManPo(p->pAig, (p->pPars->iOutput==-1)?0:p->pPars->iOutput)) );
+ else // the target is the cube
+ {
+ for ( i = 0; i < pCube->nLits; i++ )
+ {
+ if ( pCube->Lits[i] == -1 )
+ continue;
+ pObj = Saig_ManLi(p->pAig, (pCube->Lits[i] >> 1));
+ Vec_IntPush( vCoObjs, Aig_ObjId(pObj) );
+ }
+ }
+if ( p->pPars->fVeryVerbose )
+{
+printf( "Trying to justify cube " );
+if ( pCube )
+ Pdr_SetPrint( stdout, pCube, Aig_ManRegNum(p->pAig), NULL );
+else
+ printf( "<prop=fail>" );
+printf( " in frame %d.\n", k );
+}
+
+ // collect CI objects
+ Pdr_ManCollectCone( p->pAig, vCoObjs, vCiObjs, vNodes );
+ // collect values
+ Pdr_ManCollectValues( p, k, vCiObjs, vCiVals );
+ Pdr_ManCollectValues( p, k, vCoObjs, vCoVals );
+ // simulate for the first time
+if ( p->pPars->fVeryVerbose )
+Pdr_ManPrintCex( p->pAig, vCiObjs, vCiVals, NULL );
+ RetValue = Pdr_ManSimDataInit( p->pAig, vCiObjs, vCiVals, vNodes, vCoObjs, vCoVals, NULL );
+ assert( RetValue );
+
+ // try removing high-priority flops
+ Vec_IntClear( vCi2Rem );
+ Aig_ManForEachObjVec( vCiObjs, p->pAig, pObj, i )
+ {
+ if ( !Saig_ObjIsLo( p->pAig, pObj ) )
+ continue;
+ Entry = Aig_ObjPioNum(pObj) - Saig_ManPiNum(p->pAig);
+ if ( vPrio != NULL && Vec_IntEntry( vPrio, Entry ) != 0 )
+ continue;
+ Vec_IntClear( vUndo );
+ if ( Pdr_ManExtendOne( p->pAig, pObj, vUndo, vVisits ) )
+ Vec_IntPush( vCi2Rem, Aig_ObjId(pObj) );
+ else
+ Pdr_ManExtendUndo( p->pAig, vUndo );
+ }
+ // try removing low-priority flops
+ Aig_ManForEachObjVec( vCiObjs, p->pAig, pObj, i )
+ {
+ if ( !Saig_ObjIsLo( p->pAig, pObj ) )
+ continue;
+ Entry = Aig_ObjPioNum(pObj) - Saig_ManPiNum(p->pAig);
+ if ( vPrio == NULL || Vec_IntEntry( vPrio, Entry ) == 0 )
+ continue;
+ Vec_IntClear( vUndo );
+ if ( Pdr_ManExtendOne( p->pAig, pObj, vUndo, vVisits ) )
+ Vec_IntPush( vCi2Rem, Aig_ObjId(pObj) );
+ else
+ Pdr_ManExtendUndo( p->pAig, vUndo );
+ }
+if ( p->pPars->fVeryVerbose )
+Pdr_ManPrintCex( p->pAig, vCiObjs, vCiVals, vCi2Rem );
+ RetValue = Pdr_ManSimDataInit( p->pAig, vCiObjs, vCiVals, vNodes, vCoObjs, vCoVals, vCi2Rem );
+ assert( RetValue );
+
+ // derive the set of resulting registers
+ Pdr_ManDeriveResult( p->pAig, vCiObjs, vCiVals, vCi2Rem, vRes, vPiLits );
+ assert( Vec_IntSize(vRes) > 0 );
+ p->tTsim += clock() - clk;
+ return Pdr_SetCreate( vRes, vPiLits );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/pdr/pdrUtil.c b/src/proof/pdr/pdrUtil.c
new file mode 100644
index 00000000..17383425
--- /dev/null
+++ b/src/proof/pdr/pdrUtil.c
@@ -0,0 +1,719 @@
+/**CFile****************************************************************
+
+ FileName [pdrUtil.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Property driven reachability.]
+
+ Synopsis [Various utilities.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - November 20, 2010.]
+
+ Revision [$Id: pdrUtil.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "pdrInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Pdr_Set_t * Pdr_SetAlloc( int nSize )
+{
+ Pdr_Set_t * p;
+ assert( nSize >= 0 && nSize < (1<<30) );
+ p = (Pdr_Set_t *)ABC_CALLOC( char, sizeof(Pdr_Set_t) + nSize * sizeof(int) );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Pdr_Set_t * Pdr_SetCreate( Vec_Int_t * vLits, Vec_Int_t * vPiLits )
+{
+ Pdr_Set_t * p;
+ int i;
+ assert( Vec_IntSize(vLits) + Vec_IntSize(vPiLits) < (1<<30) );
+ p = (Pdr_Set_t *)ABC_ALLOC( char, sizeof(Pdr_Set_t) + (Vec_IntSize(vLits) + Vec_IntSize(vPiLits)) * sizeof(int) );
+ p->nLits = Vec_IntSize(vLits);
+ p->nTotal = Vec_IntSize(vLits) + Vec_IntSize(vPiLits);
+ p->nRefs = 1;
+ p->Sign = 0;
+ for ( i = 0; i < p->nLits; i++ )
+ {
+ p->Lits[i] = Vec_IntEntry(vLits, i);
+ p->Sign |= ((word)1 << (p->Lits[i] % 63));
+ }
+ Vec_IntSelectSort( p->Lits, p->nLits );
+/*
+ for ( i = 0; i < p->nLits; i++ )
+ printf( "%d ", p->Lits[i] );
+ printf( "\n" );
+*/
+ // remember PI literals
+ for ( i = p->nLits; i < p->nTotal; i++ )
+ p->Lits[i] = Vec_IntEntry(vPiLits, i-p->nLits);
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Pdr_Set_t * Pdr_SetCreateFrom( Pdr_Set_t * pSet, int iRemove )
+{
+ Pdr_Set_t * p;
+ int i, k = 0;
+ assert( iRemove >= 0 && iRemove < pSet->nLits );
+ p = (Pdr_Set_t *)ABC_ALLOC( char, sizeof(Pdr_Set_t) + (pSet->nTotal - 1) * sizeof(int) );
+ p->nLits = pSet->nLits - 1;
+ p->nTotal = pSet->nTotal - 1;
+ p->nRefs = 1;
+ p->Sign = 0;
+ for ( i = 0; i < pSet->nTotal; i++ )
+ {
+ if ( i == iRemove )
+ continue;
+ p->Lits[k++] = pSet->Lits[i];
+ if ( i >= pSet->nLits )
+ continue;
+ p->Sign |= ((word)1 << (pSet->Lits[i] % 63));
+ }
+ assert( k == p->nTotal );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Pdr_Set_t * Pdr_SetCreateSubset( Pdr_Set_t * pSet, int * pLits, int nLits )
+{
+ Pdr_Set_t * p;
+ int i, k = 0;
+ assert( nLits >= 0 && nLits <= pSet->nLits );
+ p = (Pdr_Set_t *)ABC_ALLOC( char, sizeof(Pdr_Set_t) + (nLits + pSet->nTotal - pSet->nLits) * sizeof(int) );
+ p->nLits = nLits;
+ p->nTotal = nLits + pSet->nTotal - pSet->nLits;
+ p->nRefs = 1;
+ p->Sign = 0;
+ for ( i = 0; i < nLits; i++ )
+ {
+ assert( pLits[i] >= 0 );
+ p->Lits[k++] = pLits[i];
+ p->Sign |= ((word)1 << (pLits[i] % 63));
+ }
+ Vec_IntSelectSort( p->Lits, p->nLits );
+ for ( i = pSet->nLits; i < pSet->nTotal; i++ )
+ p->Lits[k++] = pSet->Lits[i];
+ assert( k == p->nTotal );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Pdr_Set_t * Pdr_SetDup( Pdr_Set_t * pSet )
+{
+ Pdr_Set_t * p;
+ int i;
+ p = (Pdr_Set_t *)ABC_ALLOC( char, sizeof(Pdr_Set_t) + pSet->nTotal * sizeof(int) );
+ p->nLits = pSet->nLits;
+ p->nTotal = pSet->nTotal;
+ p->nRefs = 1;
+ p->Sign = pSet->Sign;
+ for ( i = 0; i < pSet->nTotal; i++ )
+ p->Lits[i] = pSet->Lits[i];
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Pdr_Set_t * Pdr_SetRef( Pdr_Set_t * p )
+{
+ p->nRefs++;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pdr_SetDeref( Pdr_Set_t * p )
+{
+ if ( --p->nRefs == 0 )
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pdr_SetPrint( FILE * pFile, Pdr_Set_t * p, int nRegs, Vec_Int_t * vFlopCounts )
+{
+ char * pBuff;
+ int i, k, Entry;
+ pBuff = ABC_ALLOC( char, nRegs + 1 );
+ for ( i = 0; i < nRegs; i++ )
+ pBuff[i] = '-';
+ pBuff[i] = 0;
+ for ( i = 0; i < p->nLits; i++ )
+ {
+ if ( p->Lits[i] == -1 )
+ continue;
+ pBuff[lit_var(p->Lits[i])] = (lit_sign(p->Lits[i])? '0':'1');
+ }
+ if ( vFlopCounts )
+ {
+ // skip some literals
+ k = 0;
+ Vec_IntForEachEntry( vFlopCounts, Entry, i )
+ if ( Entry )
+ pBuff[k++] = pBuff[i];
+ pBuff[k] = 0;
+ }
+ fprintf( pFile, "%s", pBuff );
+ ABC_FREE( pBuff );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Return 1 if pOld set-theoretically contains pNew.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pdr_SetContains( Pdr_Set_t * pOld, Pdr_Set_t * pNew )
+{
+ int * pOldInt, * pNewInt;
+ assert( pOld->nLits > 0 );
+ assert( pNew->nLits > 0 );
+ if ( pOld->nLits < pNew->nLits )
+ return 0;
+ if ( (pOld->Sign & pNew->Sign) != pNew->Sign )
+ return 0;
+ pOldInt = pOld->Lits + pOld->nLits - 1;
+ pNewInt = pNew->Lits + pNew->nLits - 1;
+ while ( pNew->Lits <= pNewInt )
+ {
+ if ( pOld->Lits > pOldInt )
+ return 0;
+ assert( *pNewInt != -1 );
+ assert( *pOldInt != -1 );
+ if ( *pNewInt == *pOldInt )
+ pNewInt--, pOldInt--;
+ else if ( *pNewInt < *pOldInt )
+ pOldInt--;
+ else
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Return 1 if pOld set-theoretically contains pNew.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pdr_SetContainsSimple( Pdr_Set_t * pOld, Pdr_Set_t * pNew )
+{
+ int * pOldInt, * pNewInt;
+ assert( pOld->nLits > 0 );
+ assert( pNew->nLits > 0 );
+ pOldInt = pOld->Lits + pOld->nLits - 1;
+ pNewInt = pNew->Lits + pNew->nLits - 1;
+ while ( pNew->Lits <= pNewInt )
+ {
+ assert( *pOldInt != -1 );
+ if ( *pNewInt == -1 )
+ {
+ pNewInt--;
+ continue;
+ }
+ if ( pOld->Lits > pOldInt )
+ return 0;
+ assert( *pNewInt != -1 );
+ assert( *pOldInt != -1 );
+ if ( *pNewInt == *pOldInt )
+ pNewInt--, pOldInt--;
+ else if ( *pNewInt < *pOldInt )
+ pOldInt--;
+ else
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Return 1 if the state cube contains init state (000...0).]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pdr_SetIsInit( Pdr_Set_t * pCube, int iRemove )
+{
+ int i;
+ for ( i = 0; i < pCube->nLits; i++ )
+ {
+ assert( pCube->Lits[i] != -1 );
+ if ( i == iRemove )
+ continue;
+ if ( lit_sign( pCube->Lits[i] ) == 0 )
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pdr_SetCompare( Pdr_Set_t ** pp1, Pdr_Set_t ** pp2 )
+{
+ Pdr_Set_t * p1 = *pp1;
+ Pdr_Set_t * p2 = *pp2;
+ int i;
+ for ( i = 0; i < p1->nLits && i < p2->nLits; i++ )
+ {
+ if ( p1->Lits[i] > p2->Lits[i] )
+ return -1;
+ if ( p1->Lits[i] < p2->Lits[i] )
+ return 1;
+ }
+ if ( i == p1->nLits && i < p2->nLits )
+ return -1;
+ if ( i < p1->nLits && i == p2->nLits )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Pdr_Obl_t * Pdr_OblStart( int k, int prio, Pdr_Set_t * pState, Pdr_Obl_t * pNext )
+{
+ Pdr_Obl_t * p;
+ p = ABC_ALLOC( Pdr_Obl_t, 1 );
+ p->iFrame = k;
+ p->prio = prio;
+ p->nRefs = 1;
+ p->pState = pState;
+ p->pNext = pNext;
+ p->pLink = NULL;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Pdr_Obl_t * Pdr_OblRef( Pdr_Obl_t * p )
+{
+ p->nRefs++;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pdr_OblDeref( Pdr_Obl_t * p )
+{
+ if ( --p->nRefs == 0 )
+ {
+ if ( p->pNext )
+ Pdr_OblDeref( p->pNext );
+ Pdr_SetDeref( p->pState );
+ ABC_FREE( p );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pdr_QueueIsEmpty( Pdr_Man_t * p )
+{
+ return p->pQueue == NULL;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Pdr_Obl_t * Pdr_QueueHead( Pdr_Man_t * p )
+{
+ return p->pQueue;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Pdr_Obl_t * Pdr_QueuePop( Pdr_Man_t * p )
+{
+ Pdr_Obl_t * pRes = p->pQueue;
+ if ( p->pQueue == NULL )
+ return NULL;
+ p->pQueue = p->pQueue->pLink;
+ Pdr_OblDeref( pRes );
+ return pRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pdr_QueuePush( Pdr_Man_t * p, Pdr_Obl_t * pObl )
+{
+ Pdr_Obl_t * pTemp, ** ppPrev;
+ p->nObligs++;
+ Pdr_OblRef( pObl );
+ if ( p->pQueue == NULL )
+ {
+ p->pQueue = pObl;
+ return;
+ }
+ for ( ppPrev = &p->pQueue, pTemp = p->pQueue; pTemp; ppPrev = &pTemp->pLink, pTemp = pTemp->pLink )
+ if ( pTemp->iFrame > pObl->iFrame || (pTemp->iFrame == pObl->iFrame && pTemp->prio > pObl->prio) )
+ break;
+ *ppPrev = pObl;
+ pObl->pLink = pTemp;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pdr_QueuePrint( Pdr_Man_t * p )
+{
+ Pdr_Obl_t * pObl;
+ for ( pObl = p->pQueue; pObl; pObl = pObl->pLink )
+ printf( "Frame = %2d. Prio = %8d.\n", pObl->iFrame, pObl->prio );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Pdr_QueueStop( Pdr_Man_t * p )
+{
+ Pdr_Obl_t * pObl;
+ while ( !Pdr_QueueIsEmpty(p) )
+ {
+ pObl = Pdr_QueuePop(p);
+ Pdr_OblDeref( pObl );
+ }
+ p->pQueue = NULL;
+}
+
+
+#define PDR_VAL0 1
+#define PDR_VAL1 2
+#define PDR_VALX 3
+
+/**Function*************************************************************
+
+ Synopsis [Returns value (0 or 1) or X if unassigned.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Pdr_ObjSatValue( Aig_Man_t * pAig, Aig_Obj_t * pNode, int fCompl )
+{
+ if ( Aig_ObjIsTravIdCurrent(pAig, pNode) )
+ return (pNode->fMarkA ^ fCompl) ? PDR_VAL1 : PDR_VAL0;
+ return PDR_VALX;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recursively searched for a satisfying assignment.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pdr_NtkFindSatAssign_rec( Aig_Man_t * pAig, Aig_Obj_t * pNode, int Value, Pdr_Set_t * pCube, int Heur )
+{
+ int Value0, Value1;
+ if ( Aig_ObjIsConst1(pNode) )
+ return 1;
+ if ( Aig_ObjIsTravIdCurrent(pAig, pNode) )
+ return ((int)pNode->fMarkA == Value);
+ Aig_ObjSetTravIdCurrent(pAig, pNode);
+ pNode->fMarkA = Value;
+ if ( Aig_ObjIsPi(pNode) )
+ {
+// if ( vSuppLits )
+// Vec_IntPush( vSuppLits, Abc_Var2Lit( Aig_ObjPioNum(pNode), !Value ) );
+ if ( Saig_ObjIsLo(pAig, pNode) )
+ {
+// pCube->Lits[pCube->nLits++] = Abc_Var2Lit( Aig_ObjPioNum(pNode) - Saig_ManPiNum(pAig), !Value );
+ pCube->Lits[pCube->nLits++] = Abc_Var2Lit( Aig_ObjPioNum(pNode) - Saig_ManPiNum(pAig), Value );
+ pCube->Sign |= ((word)1 << (pCube->Lits[pCube->nLits-1] % 63));
+ }
+ return 1;
+ }
+ assert( Aig_ObjIsNode(pNode) );
+ // propagation
+ if ( Value )
+ {
+ if ( !Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin0(pNode), !Aig_ObjFaninC0(pNode), pCube, Heur) )
+ return 0;
+ return Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin1(pNode), !Aig_ObjFaninC1(pNode), pCube, Heur);
+ }
+ // justification
+ Value0 = Pdr_ObjSatValue( pAig, Aig_ObjFanin0(pNode), Aig_ObjFaninC0(pNode) );
+ if ( Value0 == PDR_VAL0 )
+ return 1;
+ Value1 = Pdr_ObjSatValue( pAig, Aig_ObjFanin1(pNode), Aig_ObjFaninC1(pNode) );
+ if ( Value1 == PDR_VAL0 )
+ return 1;
+ if ( Value0 == PDR_VAL1 && Value1 == PDR_VAL1 )
+ return 0;
+ if ( Value0 == PDR_VAL1 )
+ return Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin1(pNode), Aig_ObjFaninC1(pNode), pCube, Heur);
+ if ( Value1 == PDR_VAL1 )
+ return Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin0(pNode), Aig_ObjFaninC0(pNode), pCube, Heur);
+ assert( Value0 == PDR_VALX && Value1 == PDR_VALX );
+ // decision making
+// if ( rand() % 10 == Heur )
+ if ( Aig_ObjId(pNode) % 4 == Heur )
+ return Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin1(pNode), Aig_ObjFaninC1(pNode), pCube, Heur);
+ else
+ return Pdr_NtkFindSatAssign_rec(pAig, Aig_ObjFanin0(pNode), Aig_ObjFaninC0(pNode), pCube, Heur);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if SAT assignment is found; 0 otherwise.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Pdr_ManCubeJust( Pdr_Man_t * p, int k, Pdr_Set_t * pCube )
+{
+ Aig_Obj_t * pNode;
+ int i, v, fCompl;
+// return 0;
+ for ( i = 0; i < 4; i++ )
+ {
+ // derive new assignment
+ p->pCubeJust->nLits = 0;
+ p->pCubeJust->Sign = 0;
+ Aig_ManIncrementTravId( p->pAig );
+ for ( v = 0; v < pCube->nLits; v++ )
+ {
+ if ( pCube->Lits[v] == -1 )
+ continue;
+ pNode = Saig_ManLi( p->pAig, lit_var(pCube->Lits[v]) );
+ fCompl = lit_sign(pCube->Lits[v]) ^ Aig_ObjFaninC0(pNode);
+ if ( !Pdr_NtkFindSatAssign_rec( p->pAig, Aig_ObjFanin0(pNode), !fCompl, p->pCubeJust, i ) )
+ break;
+ }
+ if ( v < pCube->nLits )
+ continue;
+ // figure this out!!!
+ if ( p->pCubeJust->nLits == 0 )
+ continue;
+ // successfully derived new assignment
+ Vec_IntSelectSort( p->pCubeJust->Lits, p->pCubeJust->nLits );
+ // check assignment against this cube
+ if ( Pdr_SetContainsSimple( p->pCubeJust, pCube ) )
+ continue;
+//printf( "\n" );
+//Pdr_SetPrint( stdout, pCube, Saig_ManRegNum(p->pAig), NULL ); printf( "\n" );
+//Pdr_SetPrint( stdout, p->pCubeJust, Saig_ManRegNum(p->pAig), NULL ); printf( "\n" );
+ // check assignment against the clauses
+ if ( Pdr_ManCheckContainment( p, k, p->pCubeJust ) )
+ continue;
+ // find good assignment
+ return 1;
+ }
+ return 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/ssw/module.make b/src/proof/ssw/module.make
new file mode 100644
index 00000000..58345a1b
--- /dev/null
+++ b/src/proof/ssw/module.make
@@ -0,0 +1,20 @@
+SRC += src/proof/ssw/sswAig.c \
+ src/proof/ssw/sswBmc.c \
+ src/proof/ssw/sswClass.c \
+ src/proof/ssw/sswCnf.c \
+ src/proof/ssw/sswConstr.c \
+ src/proof/ssw/sswCore.c \
+ src/proof/ssw/sswDyn.c \
+ src/proof/ssw/sswFilter.c \
+ src/proof/ssw/sswIslands.c \
+ src/proof/ssw/sswLcorr.c \
+ src/proof/ssw/sswMan.c \
+ src/proof/ssw/sswPart.c \
+ src/proof/ssw/sswPairs.c \
+ src/proof/ssw/sswRarity.c \
+ src/proof/ssw/sswSat.c \
+ src/proof/ssw/sswSemi.c \
+ src/proof/ssw/sswSim.c \
+ src/proof/ssw/sswSimSat.c \
+ src/proof/ssw/sswSweep.c \
+ src/proof/ssw/sswUnique.c
diff --git a/src/proof/ssw/ssw.h b/src/proof/ssw/ssw.h
new file mode 100644
index 00000000..4680f6fb
--- /dev/null
+++ b/src/proof/ssw/ssw.h
@@ -0,0 +1,142 @@
+/**CFile****************************************************************
+
+ FileName [ssw.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Inductive prover with constraints.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 1, 2008.]
+
+ Revision [$Id: ssw.h,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__ssw__ssw_h
+#define ABC__aig__ssw__ssw_h
+
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+ABC_NAMESPACE_HEADER_START
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+// choicing parameters
+typedef struct Ssw_Pars_t_ Ssw_Pars_t;
+struct Ssw_Pars_t_
+{
+ int nPartSize; // size of the partition
+ int nOverSize; // size of the overlap between partitions
+ int nFramesK; // the induction depth
+ int nFramesAddSim; // the number of additional frames to simulate
+ int fConstrs; // treat the last nConstrs POs as seq constraints
+ int fMergeFull; // enables full merge when constraints are used
+ int nMaxLevs; // the max number of levels of nodes to consider
+ int nBTLimit; // conflict limit at a node
+ int nBTLimitGlobal;// conflict limit for multiple runs
+ int nMinDomSize; // min clock domain considered for optimization
+ int nItersStop; // stop after the given number of iterations
+ int fDumpSRInit; // dumps speculative reduction
+ int nResimDelta; // the number of nodes to resimulate
+ int nStepsMax; // (scorr only) the max number of induction steps
+ int TimeLimit; // time out in seconds
+ int fPolarFlip; // uses polarity adjustment
+ int fLatchCorr; // perform register correspondence
+ int fConstCorr; // perform constant correspondence
+ int fOutputCorr; // perform 'PO correspondence'
+ int fSemiFormal; // enable semiformal filtering
+// int fUniqueness; // enable uniqueness constraints
+ int fDynamic; // enable dynamic addition of constraints
+ int fLocalSim; // enable local simulation simulation
+ int fPartSigCorr; // uses partial signal correspondence
+ int nIsleDist; // extends islands by the given distance
+ int fScorrGia; // new signal correspondence implementation
+ int fUseCSat; // new SAT solver using when fScorrGia is selected
+ int fVerbose; // verbose stats
+ int fFlopVerbose; // verbose printout of redundant flops
+ int fEquivDump; // enables dumping equivalences
+ // optimized latch correspondence
+ int fLatchCorrOpt; // perform register correspondence (optimized)
+ int nSatVarMax; // max number of SAT vars before recycling SAT solver (optimized latch corr only)
+ int nRecycleCalls; // calls to perform before recycling SAT solver (optimized latch corr only)
+ // optimized signal correspondence
+ int nSatVarMax2; // max number of SAT vars before recycling SAT solver (optimized latch corr only)
+ int nRecycleCalls2;// calls to perform before recycling SAT solver (optimized latch corr only)
+ // internal parameters
+ int nIters; // the number of iterations performed
+ int nConflicts; // the total number of conflicts performed
+ // callback
+ void * pData;
+ void * pFunc;
+};
+
+typedef struct Ssw_Sml_t_ Ssw_Sml_t; // sequential simulation manager
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== sswBmc.c ==========================================================*/
+extern int Ssw_BmcDynamic( Aig_Man_t * pAig, int nFramesMax, int nConfLimit, int fVerbose, int * piFrame );
+/*=== sswConstr.c ==========================================================*/
+extern int Ssw_ManSetConstrPhases( Aig_Man_t * p, int nFrames, Vec_Int_t ** pvInits );
+/*=== sswCore.c ==========================================================*/
+extern void Ssw_ManSetDefaultParams( Ssw_Pars_t * p );
+extern void Ssw_ManSetDefaultParamsLcorr( Ssw_Pars_t * p );
+extern Aig_Man_t * Ssw_SignalCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars );
+extern Aig_Man_t * Ssw_LatchCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars );
+/*=== sswIslands.c ==========================================================*/
+extern int Ssw_SecWithSimilarityPairs( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs, Ssw_Pars_t * pPars );
+extern int Ssw_SecWithSimilarity( Aig_Man_t * p0, Aig_Man_t * p1, Ssw_Pars_t * pPars );
+/*=== sswMiter.c ===================================================*/
+/*=== sswPart.c ==========================================================*/
+extern Aig_Man_t * Ssw_SignalCorrespondencePart( Aig_Man_t * pAig, Ssw_Pars_t * pPars );
+/*=== sswPairs.c ===================================================*/
+extern int Ssw_MiterStatus( Aig_Man_t * p, int fVerbose );
+extern int Ssw_SecWithPairs( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vIds1, Vec_Int_t * vIds2, Ssw_Pars_t * pPars );
+extern int Ssw_SecGeneral( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Ssw_Pars_t * pPars );
+extern int Ssw_SecGeneralMiter( Aig_Man_t * pMiter, Ssw_Pars_t * pPars );
+/*=== sswRarity.c ===================================================*/
+extern int Ssw_RarSignalFilter( Aig_Man_t * pAig, int nFrames, int nWords, int nBinSize, int nRounds, int nRandSeed, int TimeOut, int fMiter, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose );
+extern int Ssw_RarSimulate( Aig_Man_t * pAig, int nFrames, int nWords, int nBinSize, int nRounds, int nRandSeed, int TimeOut, int fVerbose );
+/*=== sswSim.c ===================================================*/
+extern Ssw_Sml_t * Ssw_SmlSimulateComb( Aig_Man_t * pAig, int nWords );
+extern Ssw_Sml_t * Ssw_SmlSimulateSeq( Aig_Man_t * pAig, int nPref, int nFrames, int nWords );
+extern void Ssw_SmlUnnormalize( Ssw_Sml_t * p );
+extern void Ssw_SmlStop( Ssw_Sml_t * p );
+extern int Ssw_SmlNumFrames( Ssw_Sml_t * p );
+extern int Ssw_SmlNumWordsTotal( Ssw_Sml_t * p );
+extern unsigned * Ssw_SmlSimInfo( Ssw_Sml_t * p, Aig_Obj_t * pObj );
+extern int Ssw_SmlObjsAreEqualWord( Ssw_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 );
+extern void Ssw_SmlInitializeSpecial( Ssw_Sml_t * p, Vec_Int_t * vInit );
+extern int Ssw_SmlCheckNonConstOutputs( Ssw_Sml_t * p );
+extern Vec_Ptr_t * Ssw_SmlSimDataPointers( Ssw_Sml_t * p );
+
+
+ABC_NAMESPACE_HEADER_END
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/proof/ssw/sswAig.c b/src/proof/ssw/sswAig.c
new file mode 100644
index 00000000..8ab99f83
--- /dev/null
+++ b/src/proof/ssw/sswAig.c
@@ -0,0 +1,259 @@
+/**CFile****************************************************************
+
+ FileName [sswAig.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Inductive prover with constraints.]
+
+ Synopsis [AIG manipulation.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 1, 2008.]
+
+ Revision [$Id: sswAig.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Starts the SAT manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ssw_Frm_t * Ssw_FrmStart( Aig_Man_t * pAig )
+{
+ Ssw_Frm_t * p;
+ p = ABC_ALLOC( Ssw_Frm_t, 1 );
+ memset( p, 0, sizeof(Ssw_Frm_t) );
+ p->pAig = pAig;
+ p->nObjs = Aig_ManObjNumMax( pAig );
+ p->nFrames = 0;
+ p->pFrames = NULL;
+ p->vAig2Frm = Vec_PtrAlloc( 0 );
+ Vec_PtrFill( p->vAig2Frm, 2 * p->nObjs, NULL );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the SAT manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_FrmStop( Ssw_Frm_t * p )
+{
+ if ( p->pFrames )
+ Aig_ManStop( p->pFrames );
+ Vec_PtrFree( p->vAig2Frm );
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs speculative reduction for one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Ssw_FramesConstrainNode( Ssw_Man_t * p, Aig_Man_t * pFrames, Aig_Man_t * pAig, Aig_Obj_t * pObj, int iFrame, int fTwoPos )
+{
+ Aig_Obj_t * pObjNew, * pObjNew2, * pObjRepr, * pObjReprNew, * pMiter;
+ // skip nodes without representative
+ pObjRepr = Aig_ObjRepr(pAig, pObj);
+ if ( pObjRepr == NULL )
+ return;
+ p->nConstrTotal++;
+ assert( pObjRepr->Id < pObj->Id );
+ // get the new node
+ pObjNew = Ssw_ObjFrame( p, pObj, iFrame );
+ // get the new node of the representative
+ pObjReprNew = Ssw_ObjFrame( p, pObjRepr, iFrame );
+ // if this is the same node, no need to add constraints
+ if ( pObj->fPhase == pObjRepr->fPhase )
+ {
+ assert( pObjNew != Aig_Not(pObjReprNew) );
+ if ( pObjNew == pObjReprNew )
+ return;
+ }
+ else
+ {
+ assert( pObjNew != pObjReprNew );
+ if ( pObjNew == Aig_Not(pObjReprNew) )
+ return;
+ }
+ p->nConstrReduced++;
+ // these are different nodes - perform speculative reduction
+ pObjNew2 = Aig_NotCond( pObjReprNew, pObj->fPhase ^ pObjRepr->fPhase );
+ // set the new node
+ Ssw_ObjSetFrame( p, pObj, iFrame, pObjNew2 );
+ // add the constraint
+ if ( fTwoPos )
+ {
+ Aig_ObjCreatePo( pFrames, pObjNew2 );
+ Aig_ObjCreatePo( pFrames, pObjNew );
+ }
+ else
+ {
+ pMiter = Aig_Exor( pFrames, pObjNew, pObjNew2 );
+ Aig_ObjCreatePo( pFrames, Aig_NotCond(pMiter, Aig_ObjPhaseReal(pMiter)) );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the inductive case with speculative reduction.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Ssw_FramesWithClasses( Ssw_Man_t * p )
+{
+ Aig_Man_t * pFrames;
+ Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew;
+ int i, f, iLits;
+ assert( p->pFrames == NULL );
+ assert( Aig_ManRegNum(p->pAig) > 0 );
+ assert( Aig_ManRegNum(p->pAig) < Aig_ManPiNum(p->pAig) );
+ p->nConstrTotal = p->nConstrReduced = 0;
+
+ // start the fraig package
+ pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->nFrames );
+ // create latches for the first frame
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ Ssw_ObjSetFrame( p, pObj, 0, Aig_ObjCreatePi(pFrames) );
+ // add timeframes
+ iLits = 0;
+ for ( f = 0; f < p->pPars->nFramesK; f++ )
+ {
+ // map constants and PIs
+ Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(pFrames) );
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ {
+ pObjNew = Aig_ObjCreatePi(pFrames);
+ pObjNew->fPhase = (p->vInits != NULL) && Vec_IntEntry(p->vInits, iLits++);
+ Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+ }
+ // set the constraints on the latch outputs
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ Ssw_FramesConstrainNode( p, pFrames, p->pAig, pObj, f, 1 );
+ // add internal nodes of this frame
+ Aig_ManForEachNode( p->pAig, pObj, i )
+ {
+ pObjNew = Aig_And( pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) );
+ Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+ Ssw_FramesConstrainNode( p, pFrames, p->pAig, pObj, f, 1 );
+ }
+ // transfer to the primary outputs
+ Aig_ManForEachPo( p->pAig, pObj, i )
+ Ssw_ObjSetFrame( p, pObj, f, Ssw_ObjChild0Fra(p, pObj,f) );
+ // transfer latch input to the latch outputs
+ Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+ Ssw_ObjSetFrame( p, pObjLo, f+1, Ssw_ObjFrame(p, pObjLi,f) );
+ }
+ assert( p->vInits == NULL || Vec_IntSize(p->vInits) == iLits + Saig_ManPiNum(p->pAig) );
+ // add the POs for the latch outputs of the last frame
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ Aig_ObjCreatePo( pFrames, Ssw_ObjFrame( p, pObj, p->pPars->nFramesK ) );
+
+ // remove dangling nodes
+ Aig_ManCleanup( pFrames );
+ // make sure the satisfying assignment is node assigned
+ assert( pFrames->pData == NULL );
+//Aig_ManShow( pFrames, 0, NULL );
+ return pFrames;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prepares the inductive case with speculative reduction.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Ssw_SpeculativeReduction( Ssw_Man_t * p )
+{
+ Aig_Man_t * pFrames;
+ Aig_Obj_t * pObj, * pObjNew;
+ int i;
+ assert( p->pFrames == NULL );
+ assert( Aig_ManRegNum(p->pAig) > 0 );
+ assert( Aig_ManRegNum(p->pAig) < Aig_ManPiNum(p->pAig) );
+ p->nConstrTotal = p->nConstrReduced = 0;
+
+ // start the fraig package
+ pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->nFrames );
+ pFrames->pName = Abc_UtilStrsav( p->pAig->pName );
+ // map constants and PIs
+ Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), 0, Aig_ManConst1(pFrames) );
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ Ssw_ObjSetFrame( p, pObj, 0, Aig_ObjCreatePi(pFrames) );
+ // create latches for the first frame
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ Ssw_ObjSetFrame( p, pObj, 0, Aig_ObjCreatePi(pFrames) );
+ // set the constraints on the latch outputs
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ Ssw_FramesConstrainNode( p, pFrames, p->pAig, pObj, 0, 0 );
+ // add internal nodes of this frame
+ Aig_ManForEachNode( p->pAig, pObj, i )
+ {
+ pObjNew = Aig_And( pFrames, Ssw_ObjChild0Fra(p, pObj, 0), Ssw_ObjChild1Fra(p, pObj, 0) );
+ Ssw_ObjSetFrame( p, pObj, 0, pObjNew );
+ Ssw_FramesConstrainNode( p, pFrames, p->pAig, pObj, 0, 0 );
+ }
+ // add the POs for the latch outputs of the last frame
+ Saig_ManForEachLi( p->pAig, pObj, i )
+ Aig_ObjCreatePo( pFrames, Ssw_ObjChild0Fra(p, pObj,0) );
+ // remove dangling nodes
+ Aig_ManCleanup( pFrames );
+ Aig_ManSetRegNum( pFrames, Aig_ManRegNum(p->pAig) );
+// printf( "SpecRed: Total constraints = %d. Reduced constraints = %d.\n",
+// p->nConstrTotal, p->nConstrReduced );
+ return pFrames;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/ssw/sswBmc.c b/src/proof/ssw/sswBmc.c
new file mode 100644
index 00000000..8cb14f4a
--- /dev/null
+++ b/src/proof/ssw/sswBmc.c
@@ -0,0 +1,224 @@
+/**CFile****************************************************************
+
+ FileName [sswBmc.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Inductive prover with constraints.]
+
+ Synopsis [Bounded model checker using dynamic unrolling.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 1, 2008.]
+
+ Revision [$Id: sswBmc.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Incrementally unroll the timeframes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Obj_t * Ssw_BmcUnroll_rec( Ssw_Frm_t * pFrm, Aig_Obj_t * pObj, int f )
+{
+ Aig_Obj_t * pRes, * pRes0, * pRes1;
+ if ( (pRes = Ssw_ObjFrame_(pFrm, pObj, f)) )
+ return pRes;
+ if ( Aig_ObjIsConst1(pObj) )
+ pRes = Aig_ManConst1( pFrm->pFrames );
+ else if ( Saig_ObjIsPi(pFrm->pAig, pObj) )
+ pRes = Aig_ObjCreatePi( pFrm->pFrames );
+ else if ( Aig_ObjIsPo(pObj) )
+ {
+ Ssw_BmcUnroll_rec( pFrm, Aig_ObjFanin0(pObj), f );
+ pRes = Ssw_ObjChild0Fra_( pFrm, pObj, f );
+ }
+ else if ( Saig_ObjIsLo(pFrm->pAig, pObj) )
+ {
+ if ( f == 0 )
+ pRes = Aig_ManConst0( pFrm->pFrames );
+ else
+ pRes = Ssw_BmcUnroll_rec( pFrm, Saig_ObjLoToLi(pFrm->pAig, pObj), f-1 );
+ }
+ else
+ {
+ assert( Aig_ObjIsNode(pObj) );
+ Ssw_BmcUnroll_rec( pFrm, Aig_ObjFanin0(pObj), f );
+ Ssw_BmcUnroll_rec( pFrm, Aig_ObjFanin1(pObj), f );
+ pRes0 = Ssw_ObjChild0Fra_( pFrm, pObj, f );
+ pRes1 = Ssw_ObjChild1Fra_( pFrm, pObj, f );
+ pRes = Aig_And( pFrm->pFrames, pRes0, pRes1 );
+ }
+ Ssw_ObjSetFrame_( pFrm, pObj, f, pRes );
+ return pRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives counter-example.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Cex_t * Ssw_BmcGetCounterExample( Ssw_Frm_t * pFrm, Ssw_Sat_t * pSat, int iPo, int iFrame )
+{
+ Abc_Cex_t * pCex;
+ Aig_Obj_t * pObj, * pObjFrames;
+ int f, i, nShift;
+ assert( Saig_ManRegNum(pFrm->pAig) > 0 );
+ // allocate the counter example
+ pCex = Abc_CexAlloc( Saig_ManRegNum(pFrm->pAig), Saig_ManPiNum(pFrm->pAig), iFrame + 1 );
+ pCex->iPo = iPo;
+ pCex->iFrame = iFrame;
+ // create data-bits
+ nShift = Saig_ManRegNum(pFrm->pAig);
+ for ( f = 0; f <= iFrame; f++, nShift += Saig_ManPiNum(pFrm->pAig) )
+ Saig_ManForEachPi( pFrm->pAig, pObj, i )
+ {
+ pObjFrames = Ssw_ObjFrame_(pFrm, pObj, f);
+ if ( pObjFrames == NULL )
+ continue;
+ if ( Ssw_CnfGetNodeValue( pSat, pObjFrames ) )
+ Abc_InfoSetBit( pCex->pData, nShift + i );
+ }
+ return pCex;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs BMC for the given AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_BmcDynamic( Aig_Man_t * pAig, int nFramesMax, int nConfLimit, int fVerbose, int * piFrame )
+{
+ Ssw_Frm_t * pFrm;
+ Ssw_Sat_t * pSat;
+ Aig_Obj_t * pObj, * pObjFrame;
+ int status, clkPart, Lit, i, f, RetValue;
+
+ // start managers
+ assert( Saig_ManRegNum(pAig) > 0 );
+ Aig_ManSetPioNumbers( pAig );
+ pSat = Ssw_SatStart( 0 );
+ pFrm = Ssw_FrmStart( pAig );
+ pFrm->pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * 3 );
+ // report statistics
+ if ( fVerbose )
+ {
+ printf( "AIG: PI/PO/Reg = %d/%d/%d. Node = %6d. Lev = %5d.\n",
+ Saig_ManPiNum(pAig), Saig_ManPoNum(pAig), Saig_ManRegNum(pAig),
+ Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig) );
+ fflush( stdout );
+ }
+ // perform dynamic unrolling
+ RetValue = -1;
+ for ( f = 0; f < nFramesMax; f++ )
+ {
+ clkPart = clock();
+ Saig_ManForEachPo( pAig, pObj, i )
+ {
+ // unroll the circuit for this output
+ Ssw_BmcUnroll_rec( pFrm, pObj, f );
+ pObjFrame = Ssw_ObjFrame_( pFrm, pObj, f );
+ Ssw_CnfNodeAddToSolver( pSat, Aig_Regular(pObjFrame) );
+ status = sat_solver_simplify(pSat->pSat);
+ assert( status );
+ // solve
+ Lit = toLitCond( Ssw_ObjSatNum(pSat,pObjFrame), Aig_IsComplement(pObjFrame) );
+ if ( fVerbose )
+ {
+ printf( "Solving output %2d of frame %3d ... \r",
+ i % Saig_ManPoNum(pAig), i / Saig_ManPoNum(pAig) );
+ }
+ status = sat_solver_solve( pSat->pSat, &Lit, &Lit + 1, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+ if ( status == l_False )
+ {
+/*
+ Lit = lit_neg( Lit );
+ RetValue = sat_solver_addclause( pSat->pSat, &Lit, &Lit + 1 );
+ assert( RetValue );
+ if ( pSat->pSat->qtail != pSat->pSat->qhead )
+ {
+ RetValue = sat_solver_simplify(pSat->pSat);
+ assert( RetValue );
+ }
+*/
+ RetValue = 1;
+ continue;
+ }
+ else if ( status == l_True )
+ {
+ pAig->pSeqModel = Ssw_BmcGetCounterExample( pFrm, pSat, i, f );
+ if ( piFrame )
+ *piFrame = f;
+ RetValue = 0;
+ break;
+ }
+ else
+ {
+ if ( piFrame )
+ *piFrame = f;
+ RetValue = -1;
+ break;
+ }
+ }
+ if ( fVerbose )
+ {
+ printf( "Solved %2d outputs of frame %3d. ", Saig_ManPoNum(pAig), f );
+ printf( "Conf =%8.0f. Var =%8d. AIG=%9d. ",
+ (double)pSat->pSat->stats.conflicts,
+ pSat->nSatVars, Aig_ManNodeNum(pFrm->pFrames) );
+ ABC_PRT( "T", clock() - clkPart );
+ clkPart = clock();
+ fflush( stdout );
+ }
+ if ( RetValue != 1 )
+ break;
+ }
+
+ Ssw_SatStop( pSat );
+ Ssw_FrmStop( pFrm );
+ return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/ssw/sswClass.c b/src/proof/ssw/sswClass.c
new file mode 100644
index 00000000..dd075f44
--- /dev/null
+++ b/src/proof/ssw/sswClass.c
@@ -0,0 +1,1170 @@
+/**CFile****************************************************************
+
+ FileName [sswClass.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Inductive prover with constraints.]
+
+ Synopsis [Representation of candidate equivalence classes.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 1, 2008.]
+
+ Revision [$Id: sswClass.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+/*
+ The candidate equivalence classes are stored as a vector of pointers
+ to the array of pointers to the nodes in each class.
+ The first node of the class is its representative node.
+ The representative has the smallest topological order among the class nodes.
+ The nodes inside each class are ordered according to their topological order.
+ The classes are ordered according to the topo order of their representatives.
+*/
+
+// internal representation of candidate equivalence classes
+struct Ssw_Cla_t_
+{
+ // class information
+ Aig_Man_t * pAig; // original AIG manager
+ Aig_Obj_t *** pId2Class; // non-const classes by ID of repr node
+ int * pClassSizes; // sizes of each equivalence class
+ int fConstCorr;
+ // statistics
+ int nClasses; // the total number of non-const classes
+ int nCands1; // the total number of const candidates
+ int nLits; // the number of literals in all classes
+ // memory
+ Aig_Obj_t ** pMemClasses; // memory allocated for equivalence classes
+ Aig_Obj_t ** pMemClassesFree; // memory allocated for equivalence classes to be used
+ // temporary data
+ Vec_Ptr_t * vClassOld; // old equivalence class after splitting
+ Vec_Ptr_t * vClassNew; // new equivalence class(es) after splitting
+ Vec_Ptr_t * vRefined; // the nodes refined since the last iteration
+ // procedures used for class refinement
+ void * pManData;
+ unsigned (*pFuncNodeHash) (void *,Aig_Obj_t *); // returns hash key of the node
+ int (*pFuncNodeIsConst) (void *,Aig_Obj_t *); // returns 1 if the node is a constant
+ int (*pFuncNodesAreEqual) (void *,Aig_Obj_t *, Aig_Obj_t *); // returns 1 if nodes are equal up to a complement
+};
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static inline Aig_Obj_t * Ssw_ObjNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj ) { return ppNexts[pObj->Id]; }
+static inline void Ssw_ObjSetNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { ppNexts[pObj->Id] = pNext; }
+
+// iterator through the equivalence classes
+#define Ssw_ManForEachClass( p, ppClass, i ) \
+ for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ ) \
+ if ( ((ppClass) = p->pId2Class[i]) == NULL ) {} else
+// iterator through the nodes in one class
+#define Ssw_ClassForEachNode( p, pRepr, pNode, i ) \
+ for ( i = 0; i < p->pClassSizes[pRepr->Id]; i++ ) \
+ if ( ((pNode) = p->pId2Class[pRepr->Id][i]) == NULL ) {} else
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Creates one equivalence class.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Ssw_ObjAddClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, Aig_Obj_t ** pClass, int nSize )
+{
+ assert( p->pId2Class[pRepr->Id] == NULL );
+ assert( pClass[0] == pRepr );
+ p->pId2Class[pRepr->Id] = pClass;
+ assert( p->pClassSizes[pRepr->Id] == 0 );
+ assert( nSize > 1 );
+ p->pClassSizes[pRepr->Id] = nSize;
+ p->nClasses++;
+ p->nLits += nSize - 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes one equivalence class.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline Aig_Obj_t ** Ssw_ObjRemoveClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr )
+{
+ Aig_Obj_t ** pClass = p->pId2Class[pRepr->Id];
+ int nSize;
+ assert( pClass != NULL );
+ p->pId2Class[pRepr->Id] = NULL;
+ nSize = p->pClassSizes[pRepr->Id];
+ assert( nSize > 1 );
+ p->nClasses--;
+ p->nLits -= nSize - 1;
+ p->pClassSizes[pRepr->Id] = 0;
+ return pClass;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts representation of equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ssw_Cla_t * Ssw_ClassesStart( Aig_Man_t * pAig )
+{
+ Ssw_Cla_t * p;
+ p = ABC_ALLOC( Ssw_Cla_t, 1 );
+ memset( p, 0, sizeof(Ssw_Cla_t) );
+ p->pAig = pAig;
+ p->pId2Class = ABC_CALLOC( Aig_Obj_t **, Aig_ManObjNumMax(pAig) );
+ p->pClassSizes = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) );
+ p->vClassOld = Vec_PtrAlloc( 100 );
+ p->vClassNew = Vec_PtrAlloc( 100 );
+ p->vRefined = Vec_PtrAlloc( 1000 );
+ if ( pAig->pReprs == NULL )
+ Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts representation of equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ClassesSetData( Ssw_Cla_t * p, void * pManData,
+ unsigned (*pFuncNodeHash)(void *,Aig_Obj_t *), // returns hash key of the node
+ int (*pFuncNodeIsConst)(void *,Aig_Obj_t *), // returns 1 if the node is a constant
+ int (*pFuncNodesAreEqual)(void *,Aig_Obj_t *, Aig_Obj_t *) ) // returns 1 if nodes are equal up to a complement
+{
+ p->pManData = pManData;
+ p->pFuncNodeHash = pFuncNodeHash;
+ p->pFuncNodeIsConst = pFuncNodeIsConst;
+ p->pFuncNodesAreEqual = pFuncNodesAreEqual;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stop representation of equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ClassesStop( Ssw_Cla_t * p )
+{
+ if ( p->vClassNew ) Vec_PtrFree( p->vClassNew );
+ if ( p->vClassOld ) Vec_PtrFree( p->vClassOld );
+ Vec_PtrFree( p->vRefined );
+ ABC_FREE( p->pId2Class );
+ ABC_FREE( p->pClassSizes );
+ ABC_FREE( p->pMemClasses );
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stop representation of equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Ssw_ClassesReadAig( Ssw_Cla_t * p )
+{
+ return p->pAig;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Ssw_ClassesGetRefined( Ssw_Cla_t * p )
+{
+ return p->vRefined;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ClassesClearRefined( Ssw_Cla_t * p )
+{
+ Vec_PtrClear( p->vRefined );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stop representation of equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ClassesCand1Num( Ssw_Cla_t * p )
+{
+ return p->nCands1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stop representation of equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ClassesClassNum( Ssw_Cla_t * p )
+{
+ return p->nClasses;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stop representation of equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ClassesLitNum( Ssw_Cla_t * p )
+{
+ return p->nLits;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stop representation of equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Obj_t ** Ssw_ClassesReadClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, int * pnSize )
+{
+ if ( p->pId2Class[pRepr->Id] == NULL )
+ return NULL;
+ assert( p->pId2Class[pRepr->Id] != NULL );
+ assert( p->pClassSizes[pRepr->Id] > 1 );
+ *pnSize = p->pClassSizes[pRepr->Id];
+ return p->pId2Class[pRepr->Id];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stop representation of equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ClassesCollectClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, Vec_Ptr_t * vClass )
+{
+ int i;
+ Vec_PtrClear( vClass );
+ if ( p->pId2Class[pRepr->Id] == NULL )
+ return;
+ assert( p->pClassSizes[pRepr->Id] > 1 );
+ for ( i = 1; i < p->pClassSizes[pRepr->Id]; i++ )
+ Vec_PtrPush( vClass, p->pId2Class[pRepr->Id][i] );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks candidate equivalence classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ClassesCheck( Ssw_Cla_t * p )
+{
+ Aig_Obj_t * pObj, * pPrev, ** ppClass;
+ int i, k, nLits, nClasses, nCands1;
+ nClasses = nLits = 0;
+ Ssw_ManForEachClass( p, ppClass, k )
+ {
+ pPrev = NULL;
+ assert( p->pClassSizes[ppClass[0]->Id] >= 2 );
+ Ssw_ClassForEachNode( p, ppClass[0], pObj, i )
+ {
+ if ( i == 0 )
+ assert( Aig_ObjRepr(p->pAig, pObj) == NULL );
+ else
+ {
+ assert( Aig_ObjRepr(p->pAig, pObj) == ppClass[0] );
+ assert( pPrev->Id < pObj->Id );
+ nLits++;
+ }
+ pPrev = pObj;
+ }
+ nClasses++;
+ }
+ nCands1 = 0;
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ nCands1 += Ssw_ObjIsConst1Cand( p->pAig, pObj );
+ assert( p->nLits == nLits );
+ assert( p->nCands1 == nCands1 );
+ assert( p->nClasses == nClasses );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints simulation classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ClassesPrintOne( Ssw_Cla_t * p, Aig_Obj_t * pRepr )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ printf( "{ " );
+ Ssw_ClassForEachNode( p, pRepr, pObj, i )
+ printf( "%d(%d,%d,%d) ", pObj->Id, pObj->Level,
+ Aig_SupportSize(p->pAig,pObj), Aig_NodeMffcSupp(p->pAig,pObj,0,NULL) );
+ printf( "}\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints simulation classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ClassesPrint( Ssw_Cla_t * p, int fVeryVerbose )
+{
+ Aig_Obj_t ** ppClass;
+ Aig_Obj_t * pObj;
+ int i;
+ printf( "Equiv classes: Const1 = %5d. Class = %5d. Lit = %5d.\n",
+ p->nCands1, p->nClasses, p->nCands1+p->nLits );
+ if ( !fVeryVerbose )
+ return;
+ printf( "Constants { " );
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ if ( Ssw_ObjIsConst1Cand( p->pAig, pObj ) )
+ printf( "%d(%d,%d,%d) ", pObj->Id, pObj->Level,
+ Aig_SupportSize(p->pAig,pObj), Aig_NodeMffcSupp(p->pAig,pObj,0,NULL) );
+ printf( "}\n" );
+ Ssw_ManForEachClass( p, ppClass, i )
+ {
+ printf( "%3d (%3d) : ", i, p->pClassSizes[i] );
+ Ssw_ClassesPrintOne( p, ppClass[0] );
+ }
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints simulation classes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ClassesRemoveNode( Ssw_Cla_t * p, Aig_Obj_t * pObj )
+{
+ Aig_Obj_t * pRepr, * pTemp;
+ assert( p->pClassSizes[pObj->Id] == 0 );
+ assert( p->pId2Class[pObj->Id] == NULL );
+ pRepr = Aig_ObjRepr( p->pAig, pObj );
+ assert( pRepr != NULL );
+// Vec_PtrPush( p->vRefined, pObj );
+ if ( Ssw_ObjIsConst1Cand( p->pAig, pObj ) )
+ {
+ assert( p->pClassSizes[pRepr->Id] == 0 );
+ assert( p->pId2Class[pRepr->Id] == NULL );
+ Aig_ObjSetRepr( p->pAig, pObj, NULL );
+ p->nCands1--;
+ return;
+ }
+// Vec_PtrPush( p->vRefined, pRepr );
+ Aig_ObjSetRepr( p->pAig, pObj, NULL );
+ assert( p->pId2Class[pRepr->Id][0] == pRepr );
+ assert( p->pClassSizes[pRepr->Id] >= 2 );
+ if ( p->pClassSizes[pRepr->Id] == 2 )
+ {
+ p->pId2Class[pRepr->Id] = NULL;
+ p->nClasses--;
+ p->pClassSizes[pRepr->Id] = 0;
+ p->nLits--;
+ }
+ else
+ {
+ int i, k = 0;
+ // remove the entry from the class
+ Ssw_ClassForEachNode( p, pRepr, pTemp, i )
+ if ( pTemp != pObj )
+ p->pId2Class[pRepr->Id][k++] = pTemp;
+ assert( k + 1 == p->pClassSizes[pRepr->Id] );
+ // reduce the class
+ p->pClassSizes[pRepr->Id]--;
+ p->nLits--;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Takes the set of const1 cands and rehashes them using sim info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ClassesPrepareRehash( Ssw_Cla_t * p, Vec_Ptr_t * vCands, int fConstCorr )
+{
+ Aig_Man_t * pAig = p->pAig;
+ Aig_Obj_t ** ppTable, ** ppNexts, ** ppClassNew;
+ Aig_Obj_t * pObj, * pTemp, * pRepr;
+ int i, k, nTableSize, nNodes, iEntry, nEntries, nEntries2;
+
+ // allocate the hash table hashing simulation info into nodes
+ nTableSize = Abc_PrimeCudd( Vec_PtrSize(vCands)/2 );
+ ppTable = ABC_CALLOC( Aig_Obj_t *, nTableSize );
+ ppNexts = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) );
+
+ // sort through the candidates
+ nEntries = 0;
+ p->nCands1 = 0;
+ Vec_PtrForEachEntry( Aig_Obj_t *, vCands, pObj, i )
+ {
+ assert( p->pClassSizes[pObj->Id] == 0 );
+ Aig_ObjSetRepr( p->pAig, pObj, NULL );
+ // check if the node belongs to the class of constant 1
+ if ( p->pFuncNodeIsConst( p->pManData, pObj ) )
+ {
+ Ssw_ObjSetConst1Cand( p->pAig, pObj );
+ p->nCands1++;
+ continue;
+ }
+ if ( fConstCorr )
+ continue;
+ // hash the node by its simulation info
+ iEntry = p->pFuncNodeHash( p->pManData, pObj ) % nTableSize;
+ // add the node to the class
+ if ( ppTable[iEntry] == NULL )
+ {
+ ppTable[iEntry] = pObj;
+ }
+ else
+ {
+ // set the representative of this node
+ pRepr = ppTable[iEntry];
+ Aig_ObjSetRepr( p->pAig, pObj, pRepr );
+ // add node to the table
+ if ( Ssw_ObjNext( ppNexts, pRepr ) == NULL )
+ { // this will be the second entry
+ p->pClassSizes[pRepr->Id]++;
+ nEntries++;
+ }
+ // add the entry to the list
+ Ssw_ObjSetNext( ppNexts, pObj, Ssw_ObjNext( ppNexts, pRepr ) );
+ Ssw_ObjSetNext( ppNexts, pRepr, pObj );
+ p->pClassSizes[pRepr->Id]++;
+ nEntries++;
+ }
+ }
+
+ // copy the entries into storage in the topological order
+ nEntries2 = 0;
+ Vec_PtrForEachEntry( Aig_Obj_t *, vCands, pObj, i )
+ {
+ nNodes = p->pClassSizes[pObj->Id];
+ // skip the nodes that are not representatives of non-trivial classes
+ if ( nNodes == 0 )
+ continue;
+ assert( nNodes > 1 );
+ // add the nodes to the class in the topological order
+ ppClassNew = p->pMemClassesFree + nEntries2;
+ ppClassNew[0] = pObj;
+ for ( pTemp = Ssw_ObjNext(ppNexts, pObj), k = 1; pTemp;
+ pTemp = Ssw_ObjNext(ppNexts, pTemp), k++ )
+ {
+ ppClassNew[nNodes-k] = pTemp;
+ }
+ // add the class of nodes
+ p->pClassSizes[pObj->Id] = 0;
+ Ssw_ObjAddClass( p, pObj, ppClassNew, nNodes );
+ // increment the number of entries
+ nEntries2 += nNodes;
+ }
+ p->pMemClassesFree += nEntries2;
+ assert( nEntries == nEntries2 );
+ ABC_FREE( ppTable );
+ ABC_FREE( ppNexts );
+ // now it is time to refine the classes
+ return Ssw_ClassesRefine( p, 1 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates initial simulation classes.]
+
+ Description [Assumes that simulation info is assigned.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ssw_Cla_t * Ssw_ClassesPrepare( Aig_Man_t * pAig, int nFramesK, int fLatchCorr, int fConstCorr, int fOutputCorr, int nMaxLevs, int fVerbose )
+{
+// int nFrames = 4;
+// int nWords = 1;
+// int nIters = 16;
+
+// int nFrames = 32;
+// int nWords = 4;
+// int nIters = 0;
+
+ int nFrames = Abc_MaxInt( nFramesK, 4 );
+ int nWords = 2;
+ int nIters = 16;
+ Ssw_Cla_t * p;
+ Ssw_Sml_t * pSml;
+ Vec_Ptr_t * vCands;
+ Aig_Obj_t * pObj;
+ int i, k, RetValue, clk;
+
+ // start the classes
+ p = Ssw_ClassesStart( pAig );
+ p->fConstCorr = fConstCorr;
+
+ // perform sequential simulation
+clk = clock();
+ pSml = Ssw_SmlSimulateSeq( pAig, 0, nFrames, nWords );
+if ( fVerbose )
+{
+ printf( "Allocated %.2f Mb to store simulation information.\n",
+ 1.0*(sizeof(unsigned) * Aig_ManObjNumMax(pAig) * nFrames * nWords)/(1<<20) );
+ printf( "Initial simulation of %d frames with %d words. ", nFrames, nWords );
+ ABC_PRT( "Time", clock() - clk );
+}
+
+ // set comparison procedures
+clk = clock();
+ Ssw_ClassesSetData( p, pSml, (unsigned(*)(void *,Aig_Obj_t *))Ssw_SmlObjHashWord, (int(*)(void *,Aig_Obj_t *))Ssw_SmlObjIsConstWord, (int(*)(void *,Aig_Obj_t *,Aig_Obj_t *))Ssw_SmlObjsAreEqualWord );
+
+ // collect nodes to be considered as candidates
+ vCands = Vec_PtrAlloc( 1000 );
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ {
+ if ( fLatchCorr )
+ {
+ if ( !Saig_ObjIsLo(p->pAig, pObj) )
+ continue;
+ }
+ else
+ {
+ if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) )
+ continue;
+ // skip the node with more that the given number of levels
+ if ( nMaxLevs && (int)pObj->Level > nMaxLevs )
+ continue;
+ }
+ Vec_PtrPush( vCands, pObj );
+ }
+
+ // this change will consider all PO drivers
+ if ( fOutputCorr )
+ {
+ Vec_PtrClear( vCands );
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ pObj->fMarkB = 0;
+ Saig_ManForEachPo( p->pAig, pObj, i )
+ if ( Aig_ObjIsCand(Aig_ObjFanin0(pObj)) )
+ Aig_ObjFanin0(pObj)->fMarkB = 1;
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ if ( pObj->fMarkB )
+ Vec_PtrPush( vCands, pObj );
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ pObj->fMarkB = 0;
+ }
+
+ // allocate room for classes
+ p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, Vec_PtrSize(vCands) );
+ p->pMemClassesFree = p->pMemClasses;
+
+ // now it is time to refine the classes
+ Ssw_ClassesPrepareRehash( p, vCands, fConstCorr );
+if ( fVerbose )
+{
+ printf( "Collecting candidate equivalence classes. " );
+ABC_PRT( "Time", clock() - clk );
+}
+
+clk = clock();
+ // perform iterative refinement using simulation
+ for ( i = 1; i < nIters; i++ )
+ {
+ // collect const1 candidates
+ Vec_PtrClear( vCands );
+ Aig_ManForEachObj( p->pAig, pObj, k )
+ if ( Ssw_ObjIsConst1Cand( p->pAig, pObj ) )
+ Vec_PtrPush( vCands, pObj );
+ assert( Vec_PtrSize(vCands) == p->nCands1 );
+ // perform new round of simulation
+ Ssw_SmlResimulateSeq( pSml );
+ // check equivalence classes
+ RetValue = Ssw_ClassesPrepareRehash( p, vCands, fConstCorr );
+ if ( RetValue == 0 )
+ break;
+ }
+ Ssw_SmlStop( pSml );
+ Vec_PtrFree( vCands );
+if ( fVerbose )
+{
+ printf( "Simulation of %d frames with %d words (%2d rounds). ",
+ nFrames, nWords, i-1 );
+ ABC_PRT( "Time", clock() - clk );
+}
+ Ssw_ClassesCheck( p );
+// Ssw_ClassesPrint( p, 0 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates initial simulation classes.]
+
+ Description [Assumes that simulation info is assigned.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ssw_Cla_t * Ssw_ClassesPrepareSimple( Aig_Man_t * pAig, int fLatchCorr, int nMaxLevs )
+{
+ Ssw_Cla_t * p;
+ Aig_Obj_t * pObj;
+ int i;
+ // start the classes
+ p = Ssw_ClassesStart( pAig );
+ // go through the nodes
+ p->nCands1 = 0;
+ Aig_ManForEachObj( pAig, pObj, i )
+ {
+ if ( fLatchCorr )
+ {
+ if ( !Saig_ObjIsLo(pAig, pObj) )
+ continue;
+ }
+ else
+ {
+ if ( !Aig_ObjIsNode(pObj) && !Saig_ObjIsLo(pAig, pObj) )
+ continue;
+ // skip the node with more that the given number of levels
+ if ( nMaxLevs && (int)pObj->Level > nMaxLevs )
+ continue;
+ }
+ Ssw_ObjSetConst1Cand( pAig, pObj );
+ p->nCands1++;
+ }
+ // allocate room for classes
+ p->pMemClassesFree = p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, p->nCands1 );
+// Ssw_ClassesPrint( p, 0 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates initial simulation classes.]
+
+ Description [Assumes that simulation info is assigned.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ssw_Cla_t * Ssw_ClassesPrepareFromReprs( Aig_Man_t * pAig )
+{
+ Ssw_Cla_t * p;
+ Aig_Obj_t * pObj, * pRepr;
+ int * pClassSizes, nEntries, i;
+ // start the classes
+ p = Ssw_ClassesStart( pAig );
+ // allocate memory for classes
+ p->pMemClasses = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) );
+ // count classes
+ p->nCands1 = 0;
+ Aig_ManForEachObj( pAig, pObj, i )
+ {
+ if ( Ssw_ObjIsConst1Cand(pAig, pObj) )
+ {
+ p->nCands1++;
+ continue;
+ }
+ if ( (pRepr = Aig_ObjRepr(pAig, pObj)) )
+ {
+ if ( p->pClassSizes[pRepr->Id]++ == 0 )
+ p->pClassSizes[pRepr->Id]++;
+ }
+ }
+ // add nodes
+ nEntries = 0;
+ p->nClasses = 0;
+ pClassSizes = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) );
+ Aig_ManForEachObj( pAig, pObj, i )
+ {
+ if ( p->pClassSizes[i] )
+ {
+ p->pId2Class[i] = p->pMemClasses + nEntries;
+ nEntries += p->pClassSizes[i];
+ p->pId2Class[i][pClassSizes[i]++] = pObj;
+ p->nClasses++;
+ continue;
+ }
+ if ( Ssw_ObjIsConst1Cand(pAig, pObj) )
+ continue;
+ if ( (pRepr = Aig_ObjRepr(pAig, pObj)) )
+ p->pId2Class[pRepr->Id][pClassSizes[pRepr->Id]++] = pObj;
+ }
+ p->pMemClassesFree = p->pMemClasses + nEntries;
+ p->nLits = nEntries - p->nClasses;
+ assert( memcmp(pClassSizes, p->pClassSizes, sizeof(int)*Aig_ManObjNumMax(pAig)) == 0 );
+ ABC_FREE( pClassSizes );
+// printf( "After converting:\n" );
+// Ssw_ClassesPrint( p, 0 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates initial simulation classes.]
+
+ Description [Assumes that simulation info is assigned.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ssw_Cla_t * Ssw_ClassesPrepareTargets( Aig_Man_t * pAig )
+{
+ Ssw_Cla_t * p;
+ Aig_Obj_t * pObj;
+ int i;
+ // start the classes
+ p = Ssw_ClassesStart( pAig );
+ // go through the nodes
+ p->nCands1 = 0;
+ Saig_ManForEachPo( pAig, pObj, i )
+ {
+ Ssw_ObjSetConst1Cand( pAig, Aig_ObjFanin0(pObj) );
+ p->nCands1++;
+ }
+ // allocate room for classes
+ p->pMemClassesFree = p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, p->nCands1 );
+// Ssw_ClassesPrint( p, 0 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates classes from the temporary representation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ssw_Cla_t * Ssw_ClassesPreparePairs( Aig_Man_t * pAig, Vec_Int_t ** pvClasses )
+{
+ Ssw_Cla_t * p;
+ Aig_Obj_t ** ppClassNew;
+ Aig_Obj_t * pObj, * pRepr, * pPrev;
+ int i, k, nTotalObjs, nEntries, Entry;
+ // start the classes
+ p = Ssw_ClassesStart( pAig );
+ // count the number of entries in the classes
+ nTotalObjs = 0;
+ for ( i = 0; i < Aig_ManObjNumMax(pAig); i++ )
+ nTotalObjs += pvClasses[i] ? Vec_IntSize(pvClasses[i]) : 0;
+ // allocate memory for classes
+ p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, nTotalObjs );
+ // create constant-1 class
+ if ( pvClasses[0] )
+ Vec_IntForEachEntry( pvClasses[0], Entry, i )
+ {
+ assert( (i == 0) == (Entry == 0) );
+ if ( i == 0 )
+ continue;
+ pObj = Aig_ManObj( pAig, Entry );
+ Ssw_ObjSetConst1Cand( pAig, pObj );
+ p->nCands1++;
+ }
+ // create classes
+ nEntries = 0;
+ for ( i = 1; i < Aig_ManObjNumMax(pAig); i++ )
+ {
+ if ( pvClasses[i] == NULL )
+ continue;
+ // get room for storing the class
+ ppClassNew = p->pMemClasses + nEntries;
+ nEntries += Vec_IntSize( pvClasses[i] );
+ // store the nodes of the class
+ pPrev = pRepr = Aig_ManObj( pAig, Vec_IntEntry(pvClasses[i],0) );
+ ppClassNew[0] = pRepr;
+ Vec_IntForEachEntryStart( pvClasses[i], Entry, k, 1 )
+ {
+ pObj = Aig_ManObj( pAig, Entry );
+ assert( pPrev->Id < pObj->Id );
+ pPrev = pObj;
+ ppClassNew[k] = pObj;
+ Aig_ObjSetRepr( pAig, pObj, pRepr );
+ }
+ // create new class
+ Ssw_ObjAddClass( p, pRepr, ppClassNew, Vec_IntSize(pvClasses[i]) );
+ }
+ // prepare room for new classes
+ p->pMemClassesFree = p->pMemClasses + nEntries;
+ Ssw_ClassesCheck( p );
+// Ssw_ClassesPrint( p, 0 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates classes from the temporary representation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ssw_Cla_t * Ssw_ClassesPreparePairsSimple( Aig_Man_t * pMiter, Vec_Int_t * vPairs )
+{
+ Ssw_Cla_t * p;
+ Aig_Obj_t ** ppClassNew;
+ Aig_Obj_t * pObj, * pRepr;
+ int i;
+ // start the classes
+ p = Ssw_ClassesStart( pMiter );
+ // allocate memory for classes
+ p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, Vec_IntSize(vPairs) );
+ // create classes
+ for ( i = 0; i < Vec_IntSize(vPairs); i += 2 )
+ {
+ pRepr = Aig_ManObj( pMiter, Vec_IntEntry(vPairs, i) );
+ pObj = Aig_ManObj( pMiter, Vec_IntEntry(vPairs, i+1) );
+ assert( Aig_ObjId(pRepr) < Aig_ObjId(pObj) );
+ Aig_ObjSetRepr( pMiter, pObj, pRepr );
+ // get room for storing the class
+ ppClassNew = p->pMemClasses + i;
+ ppClassNew[0] = pRepr;
+ ppClassNew[1] = pObj;
+ // create new class
+ Ssw_ObjAddClass( p, pRepr, ppClassNew, 2 );
+ }
+ // prepare room for new classes
+ p->pMemClassesFree = NULL;
+ Ssw_ClassesCheck( p );
+// Ssw_ClassesPrint( p, 0 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Iteratively refines the classes after simulation.]
+
+ Description [Returns the number of refinements performed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ClassesRefineOneClass( Ssw_Cla_t * p, Aig_Obj_t * pReprOld, int fRecursive )
+{
+ Aig_Obj_t ** pClassOld, ** pClassNew;
+ Aig_Obj_t * pObj, * pReprNew;
+ int i;
+
+ // split the class
+ Vec_PtrClear( p->vClassOld );
+ Vec_PtrClear( p->vClassNew );
+ Ssw_ClassForEachNode( p, pReprOld, pObj, i )
+ if ( p->pFuncNodesAreEqual(p->pManData, pReprOld, pObj) )
+ Vec_PtrPush( p->vClassOld, pObj );
+ else
+ Vec_PtrPush( p->vClassNew, pObj );
+ // check if splitting happened
+ if ( Vec_PtrSize(p->vClassNew) == 0 )
+ return 0;
+ // remember that this class is refined
+// Ssw_ClassForEachNode( p, pReprOld, pObj, i )
+// Vec_PtrPush( p->vRefined, pObj );
+
+ // get the new representative
+ pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 );
+ assert( Vec_PtrSize(p->vClassOld) > 0 );
+ assert( Vec_PtrSize(p->vClassNew) > 0 );
+
+ // create old class
+ pClassOld = Ssw_ObjRemoveClass( p, pReprOld );
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassOld, pObj, i )
+ {
+ pClassOld[i] = pObj;
+ Aig_ObjSetRepr( p->pAig, pObj, i? pReprOld : NULL );
+ }
+ // create new class
+ pClassNew = pClassOld + i;
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
+ {
+ pClassNew[i] = pObj;
+ Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL );
+ }
+
+ // put classes back
+ if ( Vec_PtrSize(p->vClassOld) > 1 )
+ Ssw_ObjAddClass( p, pReprOld, pClassOld, Vec_PtrSize(p->vClassOld) );
+ if ( Vec_PtrSize(p->vClassNew) > 1 )
+ Ssw_ObjAddClass( p, pReprNew, pClassNew, Vec_PtrSize(p->vClassNew) );
+
+ // check if the class should be recursively refined
+ if ( fRecursive && Vec_PtrSize(p->vClassNew) > 1 )
+ return 1 + Ssw_ClassesRefineOneClass( p, pReprNew, 1 );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Refines the classes after simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ClassesRefine( Ssw_Cla_t * p, int fRecursive )
+{
+ Aig_Obj_t ** ppClass;
+ int i, nRefis = 0;
+ Ssw_ManForEachClass( p, ppClass, i )
+ nRefis += Ssw_ClassesRefineOneClass( p, ppClass[0], fRecursive );
+ return nRefis;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Refines the classes after simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ClassesRefineGroup( Ssw_Cla_t * p, Vec_Ptr_t * vReprs, int fRecursive )
+{
+ Aig_Obj_t * pObj;
+ int i, nRefis = 0;
+ Vec_PtrForEachEntry( Aig_Obj_t *, vReprs, pObj, i )
+ nRefis += Ssw_ClassesRefineOneClass( p, pObj, fRecursive );
+ return nRefis;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Refine the group of constant 1 nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ClassesRefineConst1Group( Ssw_Cla_t * p, Vec_Ptr_t * vRoots, int fRecursive )
+{
+ Aig_Obj_t * pObj, * pReprNew, ** ppClassNew;
+ int i;
+ if ( Vec_PtrSize(vRoots) == 0 )
+ return 0;
+ // collect the nodes to be refined
+ Vec_PtrClear( p->vClassNew );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vRoots, pObj, i )
+ if ( !p->pFuncNodeIsConst( p->pManData, pObj ) )
+ Vec_PtrPush( p->vClassNew, pObj );
+ // check if there is a new class
+ if ( Vec_PtrSize(p->vClassNew) == 0 )
+ return 0;
+ p->nCands1 -= Vec_PtrSize(p->vClassNew);
+ pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 );
+ Aig_ObjSetRepr( p->pAig, pReprNew, NULL );
+ if ( Vec_PtrSize(p->vClassNew) == 1 )
+ return 1;
+ // create a new class composed of these nodes
+ ppClassNew = p->pMemClassesFree;
+ p->pMemClassesFree += Vec_PtrSize(p->vClassNew);
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
+ {
+ ppClassNew[i] = pObj;
+ Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL );
+ }
+ Ssw_ObjAddClass( p, pReprNew, ppClassNew, Vec_PtrSize(p->vClassNew) );
+ // refine them recursively
+ if ( fRecursive )
+ return 1 + Ssw_ClassesRefineOneClass( p, pReprNew, 1 );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Refine the group of constant 1 nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ClassesRefineConst1( Ssw_Cla_t * p, int fRecursive )
+{
+ Aig_Obj_t * pObj, * pReprNew, ** ppClassNew;
+ int i;
+ // collect the nodes to be refined
+ Vec_PtrClear( p->vClassNew );
+ for ( i = 0; i < Vec_PtrSize(p->pAig->vObjs); i++ )
+ if ( p->pAig->pReprs[i] == Aig_ManConst1(p->pAig) )
+ {
+ pObj = Aig_ManObj( p->pAig, i );
+ if ( !p->pFuncNodeIsConst( p->pManData, pObj ) )
+ {
+ Vec_PtrPush( p->vClassNew, pObj );
+// Vec_PtrPush( p->vRefined, pObj );
+ }
+ }
+ // check if there is a new class
+ if ( Vec_PtrSize(p->vClassNew) == 0 )
+ return 0;
+ if ( p->fConstCorr )
+ {
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
+ Aig_ObjSetRepr( p->pAig, pObj, NULL );
+ return 1;
+ }
+ p->nCands1 -= Vec_PtrSize(p->vClassNew);
+ pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 );
+ Aig_ObjSetRepr( p->pAig, pReprNew, NULL );
+ if ( Vec_PtrSize(p->vClassNew) == 1 )
+ return 1;
+ // create a new class composed of these nodes
+ ppClassNew = p->pMemClassesFree;
+ p->pMemClassesFree += Vec_PtrSize(p->vClassNew);
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
+ {
+ ppClassNew[i] = pObj;
+ Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL );
+ }
+ Ssw_ObjAddClass( p, pReprNew, ppClassNew, Vec_PtrSize(p->vClassNew) );
+ // refine them recursively
+ if ( fRecursive )
+ return 1 + Ssw_ClassesRefineOneClass( p, pReprNew, 1 );
+ return 1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/ssw/sswCnf.c b/src/proof/ssw/sswCnf.c
new file mode 100644
index 00000000..1970c62f
--- /dev/null
+++ b/src/proof/ssw/sswCnf.c
@@ -0,0 +1,428 @@
+/**CFile****************************************************************
+
+ FileName [sswCnf.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Inductive prover with constraints.]
+
+ Synopsis [Computation of CNF.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 1, 2008.]
+
+ Revision [$Id: sswCnf.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Starts the SAT manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ssw_Sat_t * Ssw_SatStart( int fPolarFlip )
+{
+ Ssw_Sat_t * p;
+ int Lit;
+ p = ABC_ALLOC( Ssw_Sat_t, 1 );
+ memset( p, 0, sizeof(Ssw_Sat_t) );
+ p->pAig = NULL;
+ p->fPolarFlip = fPolarFlip;
+ p->vSatVars = Vec_IntStart( 10000 );
+ p->vFanins = Vec_PtrAlloc( 100 );
+ p->vUsedPis = Vec_PtrAlloc( 100 );
+ p->pSat = sat_solver_new();
+ sat_solver_setnvars( p->pSat, 1000 );
+ // var 0 is not used
+ // var 1 is reserved for const1 node - add the clause
+ p->nSatVars = 1;
+ Lit = toLit( p->nSatVars );
+ if ( fPolarFlip )
+ Lit = lit_neg( Lit );
+ sat_solver_addclause( p->pSat, &Lit, &Lit + 1 );
+// Ssw_ObjSetSatNum( p, Aig_ManConst1(p->pAig), p->nSatVars++ );
+ Vec_IntWriteEntry( p->vSatVars, 0, p->nSatVars++ );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stop the SAT manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SatStop( Ssw_Sat_t * p )
+{
+// printf( "Recycling SAT solver with %d vars and %d restarts.\n",
+// p->pSat->size, p->pSat->stats.starts );
+ if ( p->pSat )
+ sat_solver_delete( p->pSat );
+ Vec_IntFree( p->vSatVars );
+ Vec_PtrFree( p->vFanins );
+ Vec_PtrFree( p->vUsedPis );
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Addes clauses to the solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_AddClausesMux( Ssw_Sat_t * p, Aig_Obj_t * pNode )
+{
+ Aig_Obj_t * pNodeI, * pNodeT, * pNodeE;
+ int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE;
+
+ assert( !Aig_IsComplement( pNode ) );
+ assert( Aig_ObjIsMuxType( pNode ) );
+ // get nodes (I = if, T = then, E = else)
+ pNodeI = Aig_ObjRecognizeMux( pNode, &pNodeT, &pNodeE );
+ // get the variable numbers
+ VarF = Ssw_ObjSatNum(p,pNode);
+ VarI = Ssw_ObjSatNum(p,pNodeI);
+ VarT = Ssw_ObjSatNum(p,Aig_Regular(pNodeT));
+ VarE = Ssw_ObjSatNum(p,Aig_Regular(pNodeE));
+ // get the complementation flags
+ fCompT = Aig_IsComplement(pNodeT);
+ fCompE = Aig_IsComplement(pNodeE);
+
+ // f = ITE(i, t, e)
+
+ // i' + t' + f
+ // i' + t + f'
+ // i + e' + f
+ // i + e + f'
+
+ // create four clauses
+ pLits[0] = toLitCond(VarI, 1);
+ pLits[1] = toLitCond(VarT, 1^fCompT);
+ pLits[2] = toLitCond(VarF, 0);
+ if ( p->fPolarFlip )
+ {
+ if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( Aig_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+ pLits[0] = toLitCond(VarI, 1);
+ pLits[1] = toLitCond(VarT, 0^fCompT);
+ pLits[2] = toLitCond(VarF, 1);
+ if ( p->fPolarFlip )
+ {
+ if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( Aig_Regular(pNodeT)->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+ pLits[0] = toLitCond(VarI, 0);
+ pLits[1] = toLitCond(VarE, 1^fCompE);
+ pLits[2] = toLitCond(VarF, 0);
+ if ( p->fPolarFlip )
+ {
+ if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+ pLits[0] = toLitCond(VarI, 0);
+ pLits[1] = toLitCond(VarE, 0^fCompE);
+ pLits[2] = toLitCond(VarF, 1);
+ if ( p->fPolarFlip )
+ {
+ if ( pNodeI->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+
+ // two additional clauses
+ // t' & e' -> f'
+ // t & e -> f
+
+ // t + e + f'
+ // t' + e' + f
+
+ if ( VarT == VarE )
+ {
+// assert( fCompT == !fCompE );
+ return;
+ }
+
+ pLits[0] = toLitCond(VarT, 0^fCompT);
+ pLits[1] = toLitCond(VarE, 0^fCompE);
+ pLits[2] = toLitCond(VarF, 1);
+ if ( p->fPolarFlip )
+ {
+ if ( Aig_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+ pLits[0] = toLitCond(VarT, 1^fCompT);
+ pLits[1] = toLitCond(VarE, 1^fCompE);
+ pLits[2] = toLitCond(VarF, 0);
+ if ( p->fPolarFlip )
+ {
+ if ( Aig_Regular(pNodeT)->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( Aig_Regular(pNodeE)->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ if ( pNode->fPhase ) pLits[2] = lit_neg( pLits[2] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 );
+ assert( RetValue );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Addes clauses to the solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_AddClausesSuper( Ssw_Sat_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vSuper )
+{
+ Aig_Obj_t * pFanin;
+ int * pLits, nLits, RetValue, i;
+ assert( !Aig_IsComplement(pNode) );
+ assert( Aig_ObjIsNode( pNode ) );
+ // create storage for literals
+ nLits = Vec_PtrSize(vSuper) + 1;
+ pLits = ABC_ALLOC( int, nLits );
+ // suppose AND-gate is A & B = C
+ // add !A => !C or A + !C
+ Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i )
+ {
+ pLits[0] = toLitCond(Ssw_ObjSatNum(p,Aig_Regular(pFanin)), Aig_IsComplement(pFanin));
+ pLits[1] = toLitCond(Ssw_ObjSatNum(p,pNode), 1);
+ if ( p->fPolarFlip )
+ {
+ if ( Aig_Regular(pFanin)->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( pNode->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
+ assert( RetValue );
+ }
+ // add A & B => C or !A + !B + C
+ Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i )
+ {
+ pLits[i] = toLitCond(Ssw_ObjSatNum(p,Aig_Regular(pFanin)), !Aig_IsComplement(pFanin));
+ if ( p->fPolarFlip )
+ {
+ if ( Aig_Regular(pFanin)->fPhase ) pLits[i] = lit_neg( pLits[i] );
+ }
+ }
+ pLits[nLits-1] = toLitCond(Ssw_ObjSatNum(p,pNode), 0);
+ if ( p->fPolarFlip )
+ {
+ if ( pNode->fPhase ) pLits[nLits-1] = lit_neg( pLits[nLits-1] );
+ }
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits );
+ assert( RetValue );
+ ABC_FREE( pLits );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_CollectSuper_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes )
+{
+ // if the new node is complemented or a PI, another gate begins
+ if ( Aig_IsComplement(pObj) || Aig_ObjIsPi(pObj) ||
+ (!fFirst && Aig_ObjRefs(pObj) > 1) ||
+ (fUseMuxes && Aig_ObjIsMuxType(pObj)) )
+ {
+ Vec_PtrPushUnique( vSuper, pObj );
+ return;
+ }
+// pObj->fMarkA = 1;
+ // go through the branches
+ Ssw_CollectSuper_rec( Aig_ObjChild0(pObj), vSuper, 0, fUseMuxes );
+ Ssw_CollectSuper_rec( Aig_ObjChild1(pObj), vSuper, 0, fUseMuxes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects the supergate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_CollectSuper( Aig_Obj_t * pObj, int fUseMuxes, Vec_Ptr_t * vSuper )
+{
+ assert( !Aig_IsComplement(pObj) );
+ assert( !Aig_ObjIsPi(pObj) );
+ Vec_PtrClear( vSuper );
+ Ssw_CollectSuper_rec( pObj, vSuper, 1, fUseMuxes );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the solver clause database.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ObjAddToFrontier( Ssw_Sat_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vFrontier )
+{
+ assert( !Aig_IsComplement(pObj) );
+ if ( Ssw_ObjSatNum(p,pObj) )
+ return;
+ assert( Ssw_ObjSatNum(p,pObj) == 0 );
+ if ( Aig_ObjIsConst1(pObj) )
+ return;
+// pObj->fMarkA = 1;
+ // save PIs (used by register correspondence)
+ if ( Aig_ObjIsPi(pObj) )
+ Vec_PtrPush( p->vUsedPis, pObj );
+ Ssw_ObjSetSatNum( p, pObj, p->nSatVars++ );
+ sat_solver_setnvars( p->pSat, 100 * (1 + p->nSatVars / 100) );
+ if ( Aig_ObjIsNode(pObj) )
+ Vec_PtrPush( vFrontier, pObj );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Updates the solver clause database.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_CnfNodeAddToSolver( Ssw_Sat_t * p, Aig_Obj_t * pObj )
+{
+ Vec_Ptr_t * vFrontier;
+ Aig_Obj_t * pNode, * pFanin;
+ int i, k, fUseMuxes = 1;
+ // quit if CNF is ready
+ if ( Ssw_ObjSatNum(p,pObj) )
+ return;
+ // start the frontier
+ vFrontier = Vec_PtrAlloc( 100 );
+ Ssw_ObjAddToFrontier( p, pObj, vFrontier );
+ // explore nodes in the frontier
+ Vec_PtrForEachEntry( Aig_Obj_t *, vFrontier, pNode, i )
+ {
+ // create the supergate
+ assert( Ssw_ObjSatNum(p,pNode) );
+ if ( fUseMuxes && Aig_ObjIsMuxType(pNode) )
+ {
+ Vec_PtrClear( p->vFanins );
+ Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin0( Aig_ObjFanin0(pNode) ) );
+ Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin0( Aig_ObjFanin1(pNode) ) );
+ Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin1( Aig_ObjFanin0(pNode) ) );
+ Vec_PtrPushUnique( p->vFanins, Aig_ObjFanin1( Aig_ObjFanin1(pNode) ) );
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanins, pFanin, k )
+ Ssw_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier );
+ Ssw_AddClausesMux( p, pNode );
+ }
+ else
+ {
+ Ssw_CollectSuper( pNode, fUseMuxes, p->vFanins );
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanins, pFanin, k )
+ Ssw_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier );
+ Ssw_AddClausesSuper( p, pNode, p->vFanins );
+ }
+ assert( Vec_PtrSize(p->vFanins) > 1 );
+ }
+ Vec_PtrFree( vFrontier );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Copy pattern from the solver into the internal storage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_CnfGetNodeValue( Ssw_Sat_t * p, Aig_Obj_t * pObj )
+{
+ int Value0, Value1, nVarNum;
+ assert( !Aig_IsComplement(pObj) );
+ nVarNum = Ssw_ObjSatNum( p, pObj );
+ if ( nVarNum > 0 )
+ return sat_solver_var_value( p->pSat, nVarNum );
+// if ( pObj->fMarkA == 1 )
+// return 0;
+ if ( Aig_ObjIsPi(pObj) )
+ return 0;
+ assert( Aig_ObjIsNode(pObj) );
+ Value0 = Ssw_CnfGetNodeValue( p, Aig_ObjFanin0(pObj) );
+ Value0 ^= Aig_ObjFaninC0(pObj);
+ Value1 = Ssw_CnfGetNodeValue( p, Aig_ObjFanin1(pObj) );
+ Value1 ^= Aig_ObjFaninC1(pObj);
+ return Value0 & Value1;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/ssw/sswConstr.c b/src/proof/ssw/sswConstr.c
new file mode 100644
index 00000000..239e35b9
--- /dev/null
+++ b/src/proof/ssw/sswConstr.c
@@ -0,0 +1,714 @@
+/**CFile****************************************************************
+
+ FileName [sswConstr.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Inductive prover with constraints.]
+
+ Synopsis [One round of SAT sweeping.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 1, 2008.]
+
+ Revision [$Id: sswConstr.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+#include "src/sat/cnf/cnf.h"
+#include "src/misc/bar/bar.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Constructs initialized timeframes with constraints as POs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Ssw_FramesWithConstraints( Aig_Man_t * p, int nFrames )
+{
+ Aig_Man_t * pFrames;
+ Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+ int i, f;
+ assert( Saig_ManConstrNum(p) > 0 );
+ assert( Aig_ManRegNum(p) > 0 );
+ assert( Aig_ManRegNum(p) < Aig_ManPiNum(p) );
+ // start the fraig package
+ pFrames = Aig_ManStart( Aig_ManObjNumMax(p) * nFrames );
+ // create latches for the first frame
+ Saig_ManForEachLo( p, pObj, i )
+ Aig_ObjSetCopy( pObj, Aig_ManConst0(pFrames) );
+ // add timeframes
+ for ( f = 0; f < nFrames; f++ )
+ {
+ // map constants and PIs
+ Aig_ObjSetCopy( Aig_ManConst1(p), Aig_ManConst1(pFrames) );
+ Saig_ManForEachPi( p, pObj, i )
+ Aig_ObjSetCopy( pObj, Aig_ObjCreatePi(pFrames) );
+ // add internal nodes of this frame
+ Aig_ManForEachNode( p, pObj, i )
+ Aig_ObjSetCopy( pObj, Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ) );
+ // transfer to the primary output
+ Aig_ManForEachPo( p, pObj, i )
+ Aig_ObjSetCopy( pObj, Aig_ObjChild0Copy(pObj) );
+ // create constraint outputs
+ Saig_ManForEachPo( p, pObj, i )
+ {
+ if ( i < Saig_ManPoNum(p) - Saig_ManConstrNum(p) )
+ continue;
+ Aig_ObjCreatePo( pFrames, Aig_Not( Aig_ObjCopy(pObj) ) );
+ }
+ // transfer latch inputs to the latch outputs
+ Saig_ManForEachLiLo( p, pObjLi, pObjLo, i )
+ Aig_ObjSetCopy( pObjLo, Aig_ObjCopy(pObjLi) );
+ }
+ // remove dangling nodes
+ Aig_ManCleanup( pFrames );
+ return pFrames;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds one satisfiable assignment of the timeframes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ManSetConstrPhases( Aig_Man_t * p, int nFrames, Vec_Int_t ** pvInits )
+{
+ Aig_Man_t * pFrames;
+ sat_solver * pSat;
+ Cnf_Dat_t * pCnf;
+ Aig_Obj_t * pObj;
+ int i, RetValue;
+ if ( pvInits )
+ *pvInits = NULL;
+ assert( p->nConstrs > 0 );
+ // derive the timeframes
+ pFrames = Ssw_FramesWithConstraints( p, nFrames );
+ // create CNF
+ pCnf = Cnf_Derive( pFrames, 0 );
+ // create SAT solver
+ pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
+ if ( pSat == NULL )
+ {
+ Cnf_DataFree( pCnf );
+ Aig_ManStop( pFrames );
+ return 1;
+ }
+ // solve
+ RetValue = sat_solver_solve( pSat, NULL, NULL,
+ (ABC_INT64_T)1000000, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+ if ( RetValue == l_True && pvInits )
+ {
+ *pvInits = Vec_IntAlloc( 1000 );
+ Aig_ManForEachPi( pFrames, pObj, i )
+ Vec_IntPush( *pvInits, sat_solver_var_value(pSat, pCnf->pVarNums[Aig_ObjId(pObj)]) );
+
+// Aig_ManForEachPi( pFrames, pObj, i )
+// printf( "%d", Vec_IntEntry(*pvInits, i) );
+// printf( "\n" );
+ }
+ sat_solver_delete( pSat );
+ Cnf_DataFree( pCnf );
+ Aig_ManStop( pFrames );
+ if ( RetValue == l_False )
+ return 1;
+ if ( RetValue == l_True )
+ return 0;
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging for one node.]
+
+ Description [Returns the fraiged node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ManSetConstrPhases_( Aig_Man_t * p, int nFrames, Vec_Int_t ** pvInits )
+{
+ Vec_Int_t * vLits;
+ sat_solver * pSat;
+ Cnf_Dat_t * pCnf;
+ Aig_Obj_t * pObj;
+ int i, f, iVar, RetValue, nRegs;
+ if ( pvInits )
+ *pvInits = NULL;
+ assert( p->nConstrs > 0 );
+ // create CNF
+ nRegs = p->nRegs; p->nRegs = 0;
+ pCnf = Cnf_Derive( p, Aig_ManPoNum(p) );
+ p->nRegs = nRegs;
+ // create SAT solver
+ pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, nFrames, 0 );
+ assert( pSat->size == nFrames * pCnf->nVars );
+ // collect constraint literals
+ vLits = Vec_IntAlloc( 100 );
+ Saig_ManForEachLo( p, pObj, i )
+ {
+ assert( pCnf->pVarNums[Aig_ObjId(pObj)] >= 0 );
+ Vec_IntPush( vLits, toLitCond(pCnf->pVarNums[Aig_ObjId(pObj)], 1) );
+ }
+ for ( f = 0; f < nFrames; f++ )
+ {
+ Saig_ManForEachPo( p, pObj, i )
+ {
+ if ( i < Saig_ManPoNum(p) - Saig_ManConstrNum(p) )
+ continue;
+ assert( pCnf->pVarNums[Aig_ObjId(pObj)] >= 0 );
+ iVar = pCnf->pVarNums[Aig_ObjId(pObj)] + pCnf->nVars*f;
+ Vec_IntPush( vLits, toLitCond(iVar, 1) );
+ }
+ }
+ RetValue = sat_solver_solve( pSat, (int *)Vec_IntArray(vLits),
+ (int *)Vec_IntArray(vLits) + Vec_IntSize(vLits),
+ (ABC_INT64_T)1000000, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+ if ( RetValue == l_True && pvInits )
+ {
+ *pvInits = Vec_IntAlloc( 1000 );
+ for ( f = 0; f < nFrames; f++ )
+ {
+ Saig_ManForEachPi( p, pObj, i )
+ {
+ iVar = pCnf->pVarNums[Aig_ObjId(pObj)] + pCnf->nVars*f;
+ Vec_IntPush( *pvInits, sat_solver_var_value(pSat, iVar) );
+ }
+ }
+ }
+ sat_solver_delete( pSat );
+ Vec_IntFree( vLits );
+ Cnf_DataFree( pCnf );
+ if ( RetValue == l_False )
+ return 1;
+ if ( RetValue == l_True )
+ return 0;
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging for one node.]
+
+ Description [Returns the fraiged node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ManPrintPolarity( Aig_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Aig_ManForEachObj( p, pObj, i )
+ printf( "%d", pObj->fPhase );
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging for one node.]
+
+ Description [Returns the fraiged node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ManRefineByConstrSim( Ssw_Man_t * p )
+{
+ Aig_Obj_t * pObj, * pObjLi;
+ int f, i, iLits, RetValue1, RetValue2;
+ int nFrames = Vec_IntSize(p->vInits) / Saig_ManPiNum(p->pAig);
+ assert( Vec_IntSize(p->vInits) % Saig_ManPiNum(p->pAig) == 0 );
+ // assign register outputs
+ Saig_ManForEachLi( p->pAig, pObj, i )
+ pObj->fMarkB = 0;
+ // simulate the timeframes
+ iLits = 0;
+ for ( f = 0; f < nFrames; f++ )
+ {
+ // set the PI simulation information
+ Aig_ManConst1(p->pAig)->fMarkB = 1;
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ pObj->fMarkB = Vec_IntEntry( p->vInits, iLits++ );
+ Saig_ManForEachLiLo( p->pAig, pObjLi, pObj, i )
+ pObj->fMarkB = pObjLi->fMarkB;
+ // simulate internal nodes
+ Aig_ManForEachNode( p->pAig, pObj, i )
+ pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) )
+ & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) );
+ // assign the COs
+ Aig_ManForEachPo( p->pAig, pObj, i )
+ pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) );
+ // check the outputs
+ Saig_ManForEachPo( p->pAig, pObj, i )
+ {
+ if ( i < Saig_ManPoNum(p->pAig) - Saig_ManConstrNum(p->pAig) )
+ {
+ if ( pObj->fMarkB )
+ printf( "output %d failed in frame %d.\n", i, f );
+ }
+ else
+ {
+ if ( pObj->fMarkB )
+ printf( "constraint %d failed in frame %d.\n", i, f );
+ }
+ }
+ // transfer
+ if ( f == 0 )
+ { // copy markB into phase
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ pObj->fPhase = pObj->fMarkB;
+ }
+ else
+ { // refine classes
+ RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 0 );
+ RetValue2 = Ssw_ClassesRefine( p->ppClasses, 0 );
+ }
+ }
+ assert( iLits == Vec_IntSize(p->vInits) );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging for one node.]
+
+ Description [Returns the fraiged node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ManSweepNodeConstr( Ssw_Man_t * p, Aig_Obj_t * pObj, int f, int fBmc )
+{
+ Aig_Obj_t * pObjRepr, * pObjFraig, * pObjFraig2, * pObjReprFraig;
+ int RetValue;
+ // get representative of this class
+ pObjRepr = Aig_ObjRepr( p->pAig, pObj );
+ if ( pObjRepr == NULL )
+ return 0;
+ // get the fraiged node
+ pObjFraig = Ssw_ObjFrame( p, pObj, f );
+ // get the fraiged representative
+ pObjReprFraig = Ssw_ObjFrame( p, pObjRepr, f );
+ // check if constant 0 pattern distinquishes these nodes
+ assert( pObjFraig != NULL && pObjReprFraig != NULL );
+ assert( (pObj->fPhase == pObjRepr->fPhase) == (Aig_ObjPhaseReal(pObjFraig) == Aig_ObjPhaseReal(pObjReprFraig)) );
+ // if the fraiged nodes are the same, return
+ if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) )
+ return 0;
+ // call equivalence checking
+ if ( Aig_Regular(pObjFraig) != Aig_ManConst1(p->pFrames) )
+ RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) );
+ else
+ RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjFraig), Aig_Regular(pObjReprFraig) );
+ if ( RetValue == 1 ) // proved equivalent
+ {
+ pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase );
+ Ssw_ObjSetFrame( p, pObj, f, pObjFraig2 );
+ return 0;
+ }
+ if ( RetValue == -1 ) // timed out
+ {
+ Ssw_ClassesRemoveNode( p->ppClasses, pObj );
+ return 1;
+ }
+ // disproved equivalence
+ Ssw_SmlSavePatternAig( p, f );
+ Ssw_ManResimulateBit( p, pObj, pObjRepr );
+ assert( Aig_ObjRepr( p->pAig, pObj ) != pObjRepr );
+ if ( Aig_ObjRepr( p->pAig, pObj ) == pObjRepr )
+ {
+ printf( "Ssw_ManSweepNodeConstr(): Failed to refine representative.\n" );
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging for the internal nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Obj_t * Ssw_ManSweepBmcConstr_rec( Ssw_Man_t * p, Aig_Obj_t * pObj, int f )
+{
+ Aig_Obj_t * pObjNew, * pObjLi;
+ pObjNew = Ssw_ObjFrame( p, pObj, f );
+ if ( pObjNew )
+ return pObjNew;
+ assert( !Saig_ObjIsPi(p->pAig, pObj) );
+ if ( Saig_ObjIsLo(p->pAig, pObj) )
+ {
+ assert( f > 0 );
+ pObjLi = Saig_ObjLoToLi( p->pAig, pObj );
+ pObjNew = Ssw_ManSweepBmcConstr_rec( p, Aig_ObjFanin0(pObjLi), f-1 );
+ pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObjLi) );
+ }
+ else
+ {
+ assert( Aig_ObjIsNode(pObj) );
+ Ssw_ManSweepBmcConstr_rec( p, Aig_ObjFanin0(pObj), f );
+ Ssw_ManSweepBmcConstr_rec( p, Aig_ObjFanin1(pObj), f );
+ pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) );
+ }
+ Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+ assert( pObjNew != NULL );
+ return pObjNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging for the internal nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ManSweepBmcConstr_old( Ssw_Man_t * p )
+{
+ Bar_Progress_t * pProgress = NULL;
+ Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo;
+ int i, f, iLits, clk;
+clk = clock();
+
+ // start initialized timeframes
+ p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK );
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ Ssw_ObjSetFrame( p, pObj, 0, Aig_ManConst0(p->pFrames) );
+
+ // build the constraint outputs
+ iLits = 0;
+ for ( f = 0; f < p->pPars->nFramesK; f++ )
+ {
+ // map constants and PIs
+ Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) );
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ {
+ pObjNew = Aig_ObjCreatePi(p->pFrames);
+ pObjNew->fPhase = Vec_IntEntry( p->vInits, iLits++ );
+ Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+ }
+ // build the constraint cones
+ Saig_ManForEachPo( p->pAig, pObj, i )
+ {
+ if ( i < Saig_ManPoNum(p->pAig) - Saig_ManConstrNum(p->pAig) )
+ continue;
+ pObjNew = Ssw_ManSweepBmcConstr_rec( p, Aig_ObjFanin0(pObj), f );
+ pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObj) );
+ if ( Aig_Regular(pObjNew) == Aig_ManConst1(p->pFrames) )
+ {
+ assert( Aig_IsComplement(pObjNew) );
+ continue;
+ }
+ Ssw_NodesAreConstrained( p, pObjNew, Aig_ManConst0(p->pFrames) );
+ }
+ }
+ assert( Vec_IntSize(p->vInits) == iLits + Saig_ManPiNum(p->pAig) );
+
+ // sweep internal nodes
+ p->fRefined = 0;
+ if ( p->pPars->fVerbose )
+ pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK );
+ for ( f = 0; f < p->pPars->nFramesK; f++ )
+ {
+ // sweep internal nodes
+ Aig_ManForEachNode( p->pAig, pObj, i )
+ {
+ if ( p->pPars->fVerbose )
+ Bar_ProgressUpdate( pProgress, Aig_ManObjNumMax(p->pAig) * f + i, NULL );
+ pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) );
+ Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+ p->fRefined |= Ssw_ManSweepNodeConstr( p, pObj, f, 1 );
+ }
+ // quit if this is the last timeframe
+ if ( f == p->pPars->nFramesK - 1 )
+ break;
+ // transfer latch input to the latch outputs
+ Aig_ManForEachPo( p->pAig, pObj, i )
+ Ssw_ObjSetFrame( p, pObj, f, Ssw_ObjChild0Fra(p, pObj, f) );
+ // build logic cones for register outputs
+ Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+ {
+ pObjNew = Ssw_ObjFrame( p, pObjLi, f );
+ Ssw_ObjSetFrame( p, pObjLo, f+1, pObjNew );
+ Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pObjNew) );//
+ }
+ }
+ if ( p->pPars->fVerbose )
+ Bar_ProgressStop( pProgress );
+
+ // cleanup
+// Ssw_ClassesCheck( p->ppClasses );
+p->timeBmc += clock() - clk;
+ return p->fRefined;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging for the internal nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ManSweepBmcConstr( Ssw_Man_t * p )
+{
+ Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo;
+ int i, f, iLits, clk;
+clk = clock();
+
+ // start initialized timeframes
+ p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK );
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ Ssw_ObjSetFrame( p, pObj, 0, Aig_ManConst0(p->pFrames) );
+
+ // build the constraint outputs
+ iLits = 0;
+ p->fRefined = 0;
+ for ( f = 0; f < p->pPars->nFramesK; f++ )
+ {
+ // map constants and PIs
+ Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) );
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ {
+ pObjNew = Aig_ObjCreatePi(p->pFrames);
+ pObjNew->fPhase = Vec_IntEntry( p->vInits, iLits++ );
+ Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+ }
+ // build the constraint cones
+ Saig_ManForEachPo( p->pAig, pObj, i )
+ {
+ if ( i < Saig_ManPoNum(p->pAig) - Saig_ManConstrNum(p->pAig) )
+ continue;
+ pObjNew = Ssw_ManSweepBmcConstr_rec( p, Aig_ObjFanin0(pObj), f );
+ pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObj) );
+ if ( Aig_Regular(pObjNew) == Aig_ManConst1(p->pFrames) )
+ {
+ assert( Aig_IsComplement(pObjNew) );
+ continue;
+ }
+ Ssw_NodesAreConstrained( p, pObjNew, Aig_ManConst0(p->pFrames) );
+ }
+
+ // sweep internal nodes
+ Aig_ManForEachNode( p->pAig, pObj, i )
+ {
+ pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) );
+ Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+ p->fRefined |= Ssw_ManSweepNodeConstr( p, pObj, f, 1 );
+ }
+ // quit if this is the last timeframe
+ if ( f == p->pPars->nFramesK - 1 )
+ break;
+ // transfer latch input to the latch outputs
+ Aig_ManForEachPo( p->pAig, pObj, i )
+ Ssw_ObjSetFrame( p, pObj, f, Ssw_ObjChild0Fra(p, pObj, f) );
+ // build logic cones for register outputs
+ Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+ {
+ pObjNew = Ssw_ObjFrame( p, pObjLi, f );
+ Ssw_ObjSetFrame( p, pObjLo, f+1, pObjNew );
+ Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pObjNew) );//
+ }
+ }
+ assert( Vec_IntSize(p->vInits) == iLits + Saig_ManPiNum(p->pAig) );
+
+ // cleanup
+// Ssw_ClassesCheck( p->ppClasses );
+p->timeBmc += clock() - clk;
+ return p->fRefined;
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging for the internal nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Obj_t * Ssw_FramesWithClasses_rec( Ssw_Man_t * p, Aig_Obj_t * pObj, int f )
+{
+ Aig_Obj_t * pObjNew, * pObjLi;
+ pObjNew = Ssw_ObjFrame( p, pObj, f );
+ if ( pObjNew )
+ return pObjNew;
+ assert( !Saig_ObjIsPi(p->pAig, pObj) );
+ if ( Saig_ObjIsLo(p->pAig, pObj) )
+ {
+ assert( f > 0 );
+ pObjLi = Saig_ObjLoToLi( p->pAig, pObj );
+ pObjNew = Ssw_FramesWithClasses_rec( p, Aig_ObjFanin0(pObjLi), f-1 );
+ pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObjLi) );
+ }
+ else
+ {
+ assert( Aig_ObjIsNode(pObj) );
+ Ssw_FramesWithClasses_rec( p, Aig_ObjFanin0(pObj), f );
+ Ssw_FramesWithClasses_rec( p, Aig_ObjFanin1(pObj), f );
+ pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) );
+ }
+ Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+ assert( pObjNew != NULL );
+ return pObjNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging for the internal nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ManSweepConstr( Ssw_Man_t * p )
+{
+ Bar_Progress_t * pProgress = NULL;
+ Aig_Obj_t * pObj, * pObj2, * pObjNew;
+ int nConstrPairs, clk, i, f, iLits;
+//Ssw_ManPrintPolarity( p->pAig );
+
+ // perform speculative reduction
+clk = clock();
+ // create timeframes
+ p->pFrames = Ssw_FramesWithClasses( p );
+ // add constants
+ nConstrPairs = Aig_ManPoNum(p->pFrames)-Aig_ManRegNum(p->pAig);
+ assert( (nConstrPairs & 1) == 0 );
+ for ( i = 0; i < nConstrPairs; i += 2 )
+ {
+ pObj = Aig_ManPo( p->pFrames, i );
+ pObj2 = Aig_ManPo( p->pFrames, i+1 );
+ Ssw_NodesAreConstrained( p, Aig_ObjChild0(pObj), Aig_ObjChild0(pObj2) );
+ }
+ // build logic cones for register inputs
+ for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ )
+ {
+ pObj = Aig_ManPo( p->pFrames, nConstrPairs + i );
+ Ssw_CnfNodeAddToSolver( p->pMSat, Aig_ObjFanin0(pObj) );//
+ }
+
+ // map constants and PIs of the last frame
+ f = p->pPars->nFramesK;
+// iLits = 0;
+ iLits = f * Saig_ManPiNum(p->pAig);
+ Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) );
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ {
+ pObjNew = Aig_ObjCreatePi(p->pFrames);
+ pObjNew->fPhase = (p->vInits != NULL) && Vec_IntEntry(p->vInits, iLits++);
+ Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+ }
+ assert( Vec_IntSize(p->vInits) == iLits );
+p->timeReduce += clock() - clk;
+
+ // add constraints to all timeframes
+ for ( f = 0; f <= p->pPars->nFramesK; f++ )
+ {
+ Saig_ManForEachPo( p->pAig, pObj, i )
+ {
+ if ( i < Saig_ManPoNum(p->pAig) - Saig_ManConstrNum(p->pAig) )
+ continue;
+ Ssw_FramesWithClasses_rec( p, Aig_ObjFanin0(pObj), f );
+// if ( Aig_Regular(Ssw_ObjChild0Fra(p,pObj,f)) == Aig_ManConst1(p->pFrames) )
+ if ( Ssw_ObjChild0Fra(p,pObj,f) == Aig_ManConst0(p->pFrames) )
+ continue;
+ assert( Ssw_ObjChild0Fra(p,pObj,f) != Aig_ManConst1(p->pFrames) );
+ if ( Ssw_ObjChild0Fra(p,pObj,f) == Aig_ManConst1(p->pFrames) )
+ {
+ printf( "Polarity violation.\n" );
+ continue;
+ }
+ Ssw_NodesAreConstrained( p, Ssw_ObjChild0Fra(p,pObj,f), Aig_ManConst0(p->pFrames) );
+ }
+ }
+ f = p->pPars->nFramesK;
+ // clean the solver
+ sat_solver_simplify( p->pMSat->pSat );
+
+
+ // sweep internal nodes
+ p->fRefined = 0;
+ Ssw_ClassesClearRefined( p->ppClasses );
+ if ( p->pPars->fVerbose )
+ pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) );
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ {
+ if ( p->pPars->fVerbose )
+ Bar_ProgressUpdate( pProgress, i, NULL );
+ if ( Saig_ObjIsLo(p->pAig, pObj) )
+ p->fRefined |= Ssw_ManSweepNodeConstr( p, pObj, f, 0 );
+ else if ( Aig_ObjIsNode(pObj) )
+ {
+ pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) );
+ Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+ p->fRefined |= Ssw_ManSweepNodeConstr( p, pObj, f, 0 );
+ }
+ }
+ if ( p->pPars->fVerbose )
+ Bar_ProgressStop( pProgress );
+ // cleanup
+// Ssw_ClassesCheck( p->ppClasses );
+ return p->fRefined;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/ssw/sswCore.c b/src/proof/ssw/sswCore.c
new file mode 100644
index 00000000..df48a5b8
--- /dev/null
+++ b/src/proof/ssw/sswCore.c
@@ -0,0 +1,522 @@
+/**CFile****************************************************************
+
+ FileName [sswCore.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Inductive prover with constraints.]
+
+ Synopsis [The core procedures.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 1, 2008.]
+
+ Revision [$Id: sswCore.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [This procedure sets default parameters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ManSetDefaultParams( Ssw_Pars_t * p )
+{
+ memset( p, 0, sizeof(Ssw_Pars_t) );
+ p->nPartSize = 0; // size of the partition
+ p->nOverSize = 0; // size of the overlap between partitions
+ p->nFramesK = 1; // the induction depth
+ p->nFramesAddSim = 2; // additional frames to simulate
+ p->fConstrs = 0; // treat the last nConstrs POs as seq constraints
+ p->fMergeFull = 0; // enables full merge when constraints are used
+ p->nBTLimit = 1000; // conflict limit at a node
+ p->nBTLimitGlobal = 5000000; // conflict limit for all runs
+ p->nMinDomSize = 100; // min clock domain considered for optimization
+ p->nItersStop = -1; // stop after the given number of iterations
+ p->nResimDelta = 1000; // the internal of nodes to resimulate
+ p->nStepsMax = -1; // (scorr only) the max number of induction steps
+ p->fPolarFlip = 0; // uses polarity adjustment
+ p->fLatchCorr = 0; // performs register correspondence
+ p->fConstCorr = 0; // performs constant correspondence
+ p->fOutputCorr = 0; // perform 'PO correspondence'
+ p->fSemiFormal = 0; // enable semiformal filtering
+ p->fDynamic = 0; // dynamic partitioning
+ p->fLocalSim = 0; // local simulation
+ p->fVerbose = 0; // verbose stats
+ p->fEquivDump = 0; // enables dumping equivalences
+
+ // latch correspondence
+ p->fLatchCorrOpt = 0; // performs optimized register correspondence
+ p->nSatVarMax = 1000; // the max number of SAT variables
+ p->nRecycleCalls = 50; // calls to perform before recycling SAT solver
+ // signal correspondence
+ p->nSatVarMax2 = 5000; // the max number of SAT variables
+ p->nRecycleCalls2 = 250; // calls to perform before recycling SAT solver
+ // return values
+ p->nIters = 0; // the number of iterations performed
+}
+
+/**Function*************************************************************
+
+ Synopsis [This procedure sets default parameters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ManSetDefaultParamsLcorr( Ssw_Pars_t * p )
+{
+ Ssw_ManSetDefaultParams( p );
+ p->fLatchCorrOpt = 1;
+ p->nBTLimit = 10000;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reports improvements for property cones.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ReportConeReductions( Ssw_Man_t * p, Aig_Man_t * pAigInit, Aig_Man_t * pAigStop )
+{
+ Aig_Man_t * pAig1, * pAig2, * pAux;
+ pAig1 = Aig_ManDupOneOutput( pAigInit, 0, 1 );
+ pAig1 = Aig_ManScl( pAux = pAig1, 1, 1, 0, -1, -1, 0, 0 );
+ Aig_ManStop( pAux );
+ pAig2 = Aig_ManDupOneOutput( pAigStop, 0, 1 );
+ pAig2 = Aig_ManScl( pAux = pAig2, 1, 1, 0, -1, -1, 0, 0 );
+ Aig_ManStop( pAux );
+
+ p->nNodesBegC = Aig_ManNodeNum(pAig1);
+ p->nNodesEndC = Aig_ManNodeNum(pAig2);
+ p->nRegsBegC = Aig_ManRegNum(pAig1);
+ p->nRegsEndC = Aig_ManRegNum(pAig2);
+
+ Aig_ManStop( pAig1 );
+ Aig_ManStop( pAig2 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reports one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ReportOneOutput( Aig_Man_t * p, Aig_Obj_t * pObj )
+{
+ if ( pObj == Aig_ManConst1(p) )
+ printf( "1" );
+ else if ( pObj == Aig_ManConst0(p) )
+ printf( "0" );
+ else
+ printf( "X" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Reports improvements for property cones.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ReportOutputs( Aig_Man_t * pAig )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Saig_ManForEachPo( pAig, pObj, i )
+ {
+ if ( i < Saig_ManPoNum(pAig)-Saig_ManConstrNum(pAig) )
+ printf( "o" );
+ else
+ printf( "c" );
+ Ssw_ReportOneOutput( pAig, Aig_ObjChild0(pObj) );
+ }
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Remove from-equivs that are in the cone of constraints.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ManUpdateEquivs( Ssw_Man_t * p, Aig_Man_t * pAig, int fVerbose )
+{
+ Vec_Ptr_t * vCones;
+ Aig_Obj_t ** pArray;
+ Aig_Obj_t * pObj;
+ int i, nTotal = 0, nRemoved = 0;
+ // collect the nodes in the cone of constraints
+ pArray = (Aig_Obj_t **)Vec_PtrArray(pAig->vPos);
+ pArray += Saig_ManPoNum(pAig) - Saig_ManConstrNum(pAig);
+ vCones = Aig_ManDfsNodes( pAig, pArray, Saig_ManConstrNum(pAig) );
+ // remove all the node that are equiv to something and are in the cones
+ Aig_ManForEachObj( pAig, pObj, i )
+ {
+ if ( !Aig_ObjIsPi(pObj) && !Aig_ObjIsNode(pObj) )
+ continue;
+ if ( pAig->pReprs[i] != NULL )
+ nTotal++;
+ if ( !Aig_ObjIsTravIdCurrent(pAig, pObj) )
+ continue;
+ if ( pAig->pReprs[i] )
+ {
+ if ( p->pPars->fConstrs && !p->pPars->fMergeFull )
+ {
+ pAig->pReprs[i] = NULL;
+ nRemoved++;
+ }
+ }
+ }
+ // collect statistics
+ p->nConesTotal = Aig_ManPiNum(pAig) + Aig_ManNodeNum(pAig);
+ p->nConesConstr = Vec_PtrSize(vCones);
+ p->nEquivsTotal = nTotal;
+ p->nEquivsConstr = nRemoved;
+ Vec_PtrFree( vCones );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs computation of signal correspondence with constraints.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Ssw_SignalCorrespondenceRefine( Ssw_Man_t * p )
+{
+ int nSatProof, nSatCallsSat, nRecycles, nSatFailsReal, nUniques;
+ Aig_Man_t * pAigNew;
+ int RetValue, nIter = -1;
+ int clk, clkTotal = clock();
+ // get the starting stats
+ p->nLitsBeg = Ssw_ClassesLitNum( p->ppClasses );
+ p->nNodesBeg = Aig_ManNodeNum(p->pAig);
+ p->nRegsBeg = Aig_ManRegNum(p->pAig);
+ // refine classes using BMC
+ if ( p->pPars->fVerbose )
+ {
+ printf( "Before BMC: " );
+ Ssw_ClassesPrint( p->ppClasses, 0 );
+ }
+ if ( !p->pPars->fLatchCorr )
+ {
+ p->pMSat = Ssw_SatStart( 0 );
+ if ( p->pPars->fConstrs )
+ Ssw_ManSweepBmcConstr( p );
+ else
+ Ssw_ManSweepBmc( p );
+ Ssw_SatStop( p->pMSat );
+ p->pMSat = NULL;
+ Ssw_ManCleanup( p );
+ }
+ if ( p->pPars->fVerbose )
+ {
+ printf( "After BMC: " );
+ Ssw_ClassesPrint( p->ppClasses, 0 );
+ }
+ // apply semi-formal filtering
+/*
+ if ( p->pPars->fSemiFormal )
+ {
+ Aig_Man_t * pSRed;
+ Ssw_FilterUsingSemi( p, 0, 2000, p->pPars->fVerbose );
+// Ssw_FilterUsingSemi( p, 1, 100000, p->pPars->fVerbose );
+ pSRed = Ssw_SpeculativeReduction( p );
+ Aig_ManDumpBlif( pSRed, "srm.blif", NULL, NULL );
+ Aig_ManStop( pSRed );
+ }
+*/
+ if ( p->pPars->pFunc )
+ {
+ ((int (*)(void *))p->pPars->pFunc)( p->pPars->pData );
+ ((int (*)(void *))p->pPars->pFunc)( p->pPars->pData );
+ }
+ if ( p->pPars->nStepsMax == 0 )
+ {
+ printf( "Stopped signal correspondence after BMC.\n" );
+ goto finalize;
+ }
+ // refine classes using induction
+ nSatProof = nSatCallsSat = nRecycles = nSatFailsReal = nUniques = 0;
+ for ( nIter = 0; ; nIter++ )
+ {
+ if ( p->pPars->nStepsMax == nIter )
+ {
+ printf( "Stopped signal correspondence after %d refiment iterations.\n", nIter );
+ goto finalize;
+ }
+ if ( p->pPars->nItersStop >= 0 && p->pPars->nItersStop == nIter )
+ {
+ Aig_Man_t * pSRed = Ssw_SpeculativeReduction( p );
+ Aig_ManDumpBlif( pSRed, "srm.blif", NULL, NULL );
+ Aig_ManStop( pSRed );
+ printf( "Iterative refinement is stopped before iteration %d.\n", nIter );
+ printf( "The network is reduced using candidate equivalences.\n" );
+ printf( "Speculatively reduced miter is saved in file \"%s\".\n", "srm.blif" );
+ printf( "If the miter is SAT, the reduced result is incorrect.\n" );
+ break;
+ }
+
+clk = clock();
+ p->pMSat = Ssw_SatStart( 0 );
+ if ( p->pPars->fLatchCorrOpt )
+ {
+ RetValue = Ssw_ManSweepLatch( p );
+ if ( p->pPars->fVerbose )
+ {
+ printf( "%3d : C =%7d. Cl =%7d. Pr =%6d. Cex =%5d. R =%4d. F =%4d. ",
+ nIter, Ssw_ClassesCand1Num(p->ppClasses), Ssw_ClassesClassNum(p->ppClasses),
+ p->nSatProof-nSatProof, p->nSatCallsSat-nSatCallsSat,
+ p->nRecycles-nRecycles, p->nSatFailsReal-nSatFailsReal );
+ ABC_PRT( "T", clock() - clk );
+ }
+ }
+ else
+ {
+ if ( p->pPars->fConstrs )
+ RetValue = Ssw_ManSweepConstr( p );
+ else if ( p->pPars->fDynamic )
+ RetValue = Ssw_ManSweepDyn( p );
+ else
+ RetValue = Ssw_ManSweep( p );
+
+ p->pPars->nConflicts += p->pMSat->pSat->stats.conflicts;
+ if ( p->pPars->fVerbose )
+ {
+ printf( "%3d : C =%7d. Cl =%7d. LR =%6d. NR =%6d. ",
+ nIter, Ssw_ClassesCand1Num(p->ppClasses), Ssw_ClassesClassNum(p->ppClasses),
+ p->nConstrReduced, Aig_ManNodeNum(p->pFrames) );
+ if ( p->pPars->fDynamic )
+ {
+ printf( "Cex =%5d. ", p->nSatCallsSat-nSatCallsSat );
+ printf( "R =%4d. ", p->nRecycles-nRecycles );
+ }
+ printf( "F =%5d. %s ", p->nSatFailsReal-nSatFailsReal,
+ (Saig_ManPoNum(p->pAig)==1 && Ssw_ObjIsConst1Cand(p->pAig,Aig_ObjFanin0(Aig_ManPo(p->pAig,0))))? "+" : "-" );
+ ABC_PRT( "T", clock() - clk );
+ }
+// if ( p->pPars->fDynamic && p->nSatCallsSat-nSatCallsSat < 100 )
+// p->pPars->nBTLimit = 10000;
+ }
+ nSatProof = p->nSatProof;
+ nSatCallsSat = p->nSatCallsSat;
+ nRecycles = p->nRecycles;
+ nSatFailsReal = p->nSatFailsReal;
+ nUniques = p->nUniques;
+
+ p->nVarsMax = Abc_MaxInt( p->nVarsMax, p->pMSat->nSatVars );
+ p->nCallsMax = Abc_MaxInt( p->nCallsMax, p->pMSat->nSolverCalls );
+ Ssw_SatStop( p->pMSat );
+ p->pMSat = NULL;
+ Ssw_ManCleanup( p );
+ if ( !RetValue )
+ break;
+ if ( p->pPars->pFunc )
+ ((int (*)(void *))p->pPars->pFunc)( p->pPars->pData );
+ }
+
+finalize:
+ p->pPars->nIters = nIter + 1;
+p->timeTotal = clock() - clkTotal;
+
+ Ssw_ManUpdateEquivs( p, p->pAig, p->pPars->fVerbose );
+ pAigNew = Aig_ManDupRepr( p->pAig, 0 );
+ Aig_ManSeqCleanup( pAigNew );
+//Ssw_ClassesPrint( p->ppClasses, 1 );
+ // get the final stats
+ p->nLitsEnd = Ssw_ClassesLitNum( p->ppClasses );
+ p->nNodesEnd = Aig_ManNodeNum(pAigNew);
+ p->nRegsEnd = Aig_ManRegNum(pAigNew);
+ // cleanup
+ Aig_ManSetPhase( p->pAig );
+ Aig_ManCleanMarkB( p->pAig );
+ return pAigNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs computation of signal correspondence with constraints.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Ssw_SignalCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars )
+{
+ Ssw_Pars_t Pars;
+ Aig_Man_t * pAigNew;
+ Ssw_Man_t * p;
+ assert( Aig_ManRegNum(pAig) > 0 );
+ // reset random numbers
+ Aig_ManRandom( 1 );
+ // if parameters are not given, create them
+ if ( pPars == NULL )
+ Ssw_ManSetDefaultParams( pPars = &Pars );
+ // consider the case of empty AIG
+ if ( Aig_ManNodeNum(pAig) == 0 )
+ {
+ pPars->nIters = 0;
+ // Ntl_ManFinalize() needs the following to satisfy an assertion
+ Aig_ManReprStart( pAig,Aig_ManObjNumMax(pAig) );
+ return Aig_ManDupOrdered(pAig);
+ }
+ // check and update parameters
+ if ( pPars->fLatchCorrOpt )
+ {
+ pPars->fLatchCorr = 1;
+ pPars->nFramesAddSim = 0;
+ if ( (pAig->vClockDoms && Vec_VecSize(pAig->vClockDoms) > 0) )
+ return Ssw_SignalCorrespondencePart( pAig, pPars );
+ }
+ else
+ {
+ assert( pPars->nFramesK > 0 );
+ // perform partitioning
+ if ( (pPars->nPartSize > 0 && pPars->nPartSize < Aig_ManRegNum(pAig))
+ || (pAig->vClockDoms && Vec_VecSize(pAig->vClockDoms) > 0) )
+ return Ssw_SignalCorrespondencePart( pAig, pPars );
+ }
+
+ if ( pPars->fScorrGia )
+ {
+ if ( pPars->fLatchCorrOpt )
+ {
+ extern Aig_Man_t * Cec_LatchCorrespondence( Aig_Man_t * pAig, int nConfs, int fUseCSat );
+ return Cec_LatchCorrespondence( pAig, pPars->nBTLimit, pPars->fUseCSat );
+ }
+ else
+ {
+ extern Aig_Man_t * Cec_SignalCorrespondence( Aig_Man_t * pAig, int nConfs, int fUseCSat );
+ return Cec_SignalCorrespondence( pAig, pPars->nBTLimit, pPars->fUseCSat );
+ }
+ }
+
+ // start the induction manager
+ p = Ssw_ManCreate( pAig, pPars );
+ // compute candidate equivalence classes
+// p->pPars->nConstrs = 1;
+ if ( p->pPars->fConstrs )
+ {
+ // create trivial equivalence classes with all nodes being candidates for constant 1
+ p->ppClasses = Ssw_ClassesPrepareSimple( pAig, pPars->fLatchCorr, pPars->nMaxLevs );
+ Ssw_ClassesSetData( p->ppClasses, NULL, NULL, Ssw_SmlObjIsConstBit, Ssw_SmlObjsAreEqualBit );
+ // derive phase bits to satisfy the constraints
+ if ( Ssw_ManSetConstrPhases( pAig, p->pPars->nFramesK + 1, &p->vInits ) != 0 )
+ {
+ printf( "Ssw_SignalCorrespondence(): The init state does not satisfy the constraints!\n" );
+ p->pPars->fVerbose = 0;
+ Ssw_ManStop( p );
+ return NULL;
+ }
+ // perform simulation of the first timeframes
+ Ssw_ManRefineByConstrSim( p );
+ }
+ else
+ {
+ // perform one round of seq simulation and generate candidate equivalence classes
+ p->ppClasses = Ssw_ClassesPrepare( pAig, pPars->nFramesK, pPars->fLatchCorr, pPars->fConstCorr, pPars->fOutputCorr, pPars->nMaxLevs, pPars->fVerbose );
+// p->ppClasses = Ssw_ClassesPrepareTargets( pAig );
+ if ( pPars->fLatchCorrOpt )
+ p->pSml = Ssw_SmlStart( pAig, 0, 2, 1 );
+ else if ( pPars->fDynamic )
+ p->pSml = Ssw_SmlStart( pAig, 0, p->nFrames + p->pPars->nFramesAddSim, 1 );
+ else
+ p->pSml = Ssw_SmlStart( pAig, 0, 1 + p->pPars->nFramesAddSim, 1 );
+ Ssw_ClassesSetData( p->ppClasses, p->pSml, (unsigned(*)(void *,Aig_Obj_t *))Ssw_SmlObjHashWord, (int(*)(void *,Aig_Obj_t *))Ssw_SmlObjIsConstWord, (int(*)(void *,Aig_Obj_t *,Aig_Obj_t *))Ssw_SmlObjsAreEqualWord );
+ }
+ // allocate storage
+ if ( p->pPars->fLocalSim )
+ p->pVisited = ABC_CALLOC( int, Ssw_SmlNumFrames( p->pSml ) * Aig_ManObjNumMax(p->pAig) );
+ // perform refinement of classes
+ pAigNew = Ssw_SignalCorrespondenceRefine( p );
+// Ssw_ReportOutputs( pAigNew );
+ if ( pPars->fConstrs && pPars->fVerbose )
+ Ssw_ReportConeReductions( p, pAig, pAigNew );
+ // cleanup
+ Ssw_ManStop( p );
+ return pAigNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs computation of latch correspondence.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Ssw_LatchCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars )
+{
+ Aig_Man_t * pRes;
+ Ssw_Pars_t Pars;
+ if ( pPars == NULL )
+ Ssw_ManSetDefaultParamsLcorr( pPars = &Pars );
+ pRes = Ssw_SignalCorrespondence( pAig, pPars );
+// if ( pPars->fConstrs && pPars->fVerbose )
+// Ssw_ReportConeReductions( pAig, pRes );
+ return pRes;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/ssw/sswDyn.c b/src/proof/ssw/sswDyn.c
new file mode 100644
index 00000000..d9a16e22
--- /dev/null
+++ b/src/proof/ssw/sswDyn.c
@@ -0,0 +1,489 @@
+/**CFile****************************************************************
+
+ FileName [sswDyn.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Inductive prover with constraints.]
+
+ Synopsis [Dynamic loading of constraints.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 1, 2008.]
+
+ Revision [$Id: sswDyn.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+#include "src/misc/bar/bar.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Label PIs nodes of the frames corresponding to PIs of AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ManLabelPiNodes( Ssw_Man_t * p )
+{
+ Aig_Obj_t * pObj, * pObjFrames;
+ int f, i;
+ Aig_ManConst1( p->pFrames )->fMarkA = 1;
+ Aig_ManConst1( p->pFrames )->fMarkB = 1;
+ for ( f = 0; f < p->nFrames; f++ )
+ {
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ {
+ pObjFrames = Ssw_ObjFrame( p, pObj, f );
+ assert( Aig_ObjIsPi(pObjFrames) );
+ assert( pObjFrames->fMarkB == 0 );
+ pObjFrames->fMarkA = 1;
+ pObjFrames->fMarkB = 1;
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects new POs in p->vNewPos.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ManCollectPis_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vNewPis )
+{
+ assert( !Aig_IsComplement(pObj) );
+ if ( pObj->fMarkA )
+ return;
+ pObj->fMarkA = 1;
+ if ( Aig_ObjIsPi(pObj) )
+ {
+ Vec_PtrPush( vNewPis, pObj );
+ return;
+ }
+ assert( Aig_ObjIsNode(pObj) );
+ Ssw_ManCollectPis_rec( Aig_ObjFanin0(pObj), vNewPis );
+ Ssw_ManCollectPis_rec( Aig_ObjFanin1(pObj), vNewPis );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collects new POs in p->vNewPos.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ManCollectPos_rec( Ssw_Man_t * p, Aig_Obj_t * pObj, Vec_Int_t * vNewPos )
+{
+ Aig_Obj_t * pFanout;
+ int iFanout = -1, i;
+ assert( !Aig_IsComplement(pObj) );
+ if ( pObj->fMarkB )
+ return;
+ pObj->fMarkB = 1;
+ if ( pObj->Id > p->nSRMiterMaxId )
+ return;
+ if ( Aig_ObjIsPo(pObj) )
+ {
+ // skip if it is a register input PO
+ if ( Aig_ObjPioNum(pObj) >= Aig_ManPoNum(p->pFrames)-Aig_ManRegNum(p->pAig) )
+ return;
+ // add the number of this constraint
+ Vec_IntPush( vNewPos, Aig_ObjPioNum(pObj)/2 );
+ return;
+ }
+ // visit the fanouts
+ assert( p->pFrames->pFanData != NULL );
+ Aig_ObjForEachFanout( p->pFrames, pObj, pFanout, iFanout, i )
+ Ssw_ManCollectPos_rec( p, pFanout, vNewPos );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Loads logic cones and relevant constraints.]
+
+ Description [Both pRepr and pObj are objects of the AIG.
+ The result is the current SAT solver loaded with the logic cones
+ for pRepr and pObj corresponding to them in the frames,
+ as well as all the relevant constraints.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ManLoadSolver( Ssw_Man_t * p, Aig_Obj_t * pRepr, Aig_Obj_t * pObj )
+{
+ Aig_Obj_t * pObjFrames, * pReprFrames;
+ Aig_Obj_t * pTemp, * pObj0, * pObj1;
+ int i, iConstr, RetValue;
+
+ assert( pRepr != pObj );
+ // get the corresponding frames nodes
+ pReprFrames = Aig_Regular( Ssw_ObjFrame( p, pRepr, p->pPars->nFramesK ) );
+ pObjFrames = Aig_Regular( Ssw_ObjFrame( p, pObj, p->pPars->nFramesK ) );
+ assert( pReprFrames != pObjFrames );
+ /*
+ // compute the AIG support
+ Vec_PtrClear( p->vNewLos );
+ Ssw_ManCollectPis_rec( pRepr, p->vNewLos );
+ Ssw_ManCollectPis_rec( pObj, p->vNewLos );
+ // add logic cones for register outputs
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vNewLos, pTemp, i )
+ {
+ pObj0 = Aig_Regular( Ssw_ObjFrame( p, pTemp, p->pPars->nFramesK ) );
+ Ssw_CnfNodeAddToSolver( p->pMSat, pObj0 );
+ }
+*/
+ // add cones for the nodes
+ Ssw_CnfNodeAddToSolver( p->pMSat, pReprFrames );
+ Ssw_CnfNodeAddToSolver( p->pMSat, pObjFrames );
+
+ // compute the frames support
+ Vec_PtrClear( p->vNewLos );
+ Ssw_ManCollectPis_rec( pReprFrames, p->vNewLos );
+ Ssw_ManCollectPis_rec( pObjFrames, p->vNewLos );
+ // these nodes include both nodes corresponding to PIs and LOs
+ // (the nodes corresponding to PIs should be labeled with fMarkB!)
+
+ // collect the related constraint POs
+ Vec_IntClear( p->vNewPos );
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vNewLos, pTemp, i )
+ Ssw_ManCollectPos_rec( p, pTemp, p->vNewPos );
+ // check if the corresponding pairs are added
+ Vec_IntForEachEntry( p->vNewPos, iConstr, i )
+ {
+ pObj0 = Aig_ManPo( p->pFrames, 2*iConstr );
+ pObj1 = Aig_ManPo( p->pFrames, 2*iConstr+1 );
+// if ( pObj0->fMarkB && pObj1->fMarkB )
+ if ( pObj0->fMarkB || pObj1->fMarkB )
+ {
+ pObj0->fMarkB = 1;
+ pObj1->fMarkB = 1;
+ Ssw_NodesAreConstrained( p, Aig_ObjChild0(pObj0), Aig_ObjChild0(pObj1) );
+ }
+ }
+ if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead )
+ {
+ RetValue = sat_solver_simplify(p->pMSat->pSat);
+ assert( RetValue != 0 );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Tranfers simulation information from FRAIG to AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ManSweepTransferDyn( Ssw_Man_t * p )
+{
+ Aig_Obj_t * pObj, * pObjFraig;
+ unsigned * pInfo;
+ int i, f, nFrames;
+
+ // transfer simulation information
+ Aig_ManForEachPi( p->pAig, pObj, i )
+ {
+ pObjFraig = Ssw_ObjFrame( p, pObj, 0 );
+ if ( pObjFraig == Aig_ManConst0(p->pFrames) )
+ {
+ Ssw_SmlObjAssignConst( p->pSml, pObj, 0, 0 );
+ continue;
+ }
+ assert( !Aig_IsComplement(pObjFraig) );
+ assert( Aig_ObjIsPi(pObjFraig) );
+ pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjPioNum(pObjFraig) );
+ Ssw_SmlObjSetWord( p->pSml, pObj, pInfo[0], 0, 0 );
+ }
+ // set random simulation info for the second frame
+ for ( f = 1; f < p->nFrames; f++ )
+ {
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ {
+ pObjFraig = Ssw_ObjFrame( p, pObj, f );
+ assert( !Aig_IsComplement(pObjFraig) );
+ assert( Aig_ObjIsPi(pObjFraig) );
+ pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjPioNum(pObjFraig) );
+ Ssw_SmlObjSetWord( p->pSml, pObj, pInfo[0], 0, f );
+ }
+ }
+ // create random info
+ nFrames = Ssw_SmlNumFrames( p->pSml );
+ for ( ; f < nFrames; f++ )
+ {
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ Ssw_SmlAssignRandomFrame( p->pSml, pObj, f );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs one round of simulation with counter-examples.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ManSweepResimulateDyn( Ssw_Man_t * p, int f )
+{
+ int RetValue1, RetValue2, clk = clock();
+ // transfer PI simulation information from storage
+// Ssw_SmlAssignDist1Plus( p->pSml, p->pPatWords );
+ Ssw_ManSweepTransferDyn( p );
+ // simulate internal nodes
+// Ssw_SmlSimulateOneFrame( p->pSml );
+ Ssw_SmlSimulateOne( p->pSml );
+ // check equivalence classes
+ RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 1 );
+ RetValue2 = Ssw_ClassesRefine( p->ppClasses, 1 );
+ // prepare simulation info for the next round
+ Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 );
+ p->nPatterns = 0;
+ p->nSimRounds++;
+p->timeSimSat += clock() - clk;
+ return RetValue1 > 0 || RetValue2 > 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs one round of simulation with counter-examples.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ManSweepResimulateDynLocal( Ssw_Man_t * p, int f )
+{
+ Aig_Obj_t * pObj, * pRepr, ** ppClass;
+ int i, k, nSize, RetValue1, RetValue2, clk = clock();
+ p->nSimRounds++;
+ // transfer PI simulation information from storage
+// Ssw_SmlAssignDist1Plus( p->pSml, p->pPatWords );
+ Ssw_ManSweepTransferDyn( p );
+ // determine const1 cands and classes to be simulated
+ Vec_PtrClear( p->vResimConsts );
+ Vec_PtrClear( p->vResimClasses );
+ Aig_ManIncrementTravId( p->pAig );
+ for ( i = p->iNodeStart; i < p->iNodeLast + p->pPars->nResimDelta; i++ )
+ {
+ if ( i >= Aig_ManObjNumMax( p->pAig ) )
+ break;
+ pObj = Aig_ManObj( p->pAig, i );
+ if ( pObj == NULL )
+ continue;
+ if ( Ssw_ObjIsConst1Cand(p->pAig, pObj) )
+ {
+ Vec_PtrPush( p->vResimConsts, pObj );
+ continue;
+ }
+ pRepr = Aig_ObjRepr(p->pAig, pObj);
+ if ( pRepr == NULL )
+ continue;
+ if ( Aig_ObjIsTravIdCurrent(p->pAig, pRepr) )
+ continue;
+ Aig_ObjSetTravIdCurrent(p->pAig, pRepr);
+ Vec_PtrPush( p->vResimClasses, pRepr );
+ }
+ // simulate internal nodes
+// Ssw_SmlSimulateOneFrame( p->pSml );
+// Ssw_SmlSimulateOne( p->pSml );
+ // resimulate dynamically
+// Aig_ManIncrementTravId( p->pAig );
+// Aig_ObjIsTravIdCurrent( p->pAig, Aig_ManConst1(p->pAig) );
+ p->nVisCounter++;
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vResimConsts, pObj, i )
+ Ssw_SmlSimulateOneDyn_rec( p->pSml, pObj, p->nFrames-1, p->pVisited, p->nVisCounter );
+ // resimulate the cone of influence of the cand classes
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vResimClasses, pRepr, i )
+ {
+ ppClass = Ssw_ClassesReadClass( p->ppClasses, pRepr, &nSize );
+ for ( k = 0; k < nSize; k++ )
+ Ssw_SmlSimulateOneDyn_rec( p->pSml, ppClass[k], p->nFrames-1, p->pVisited, p->nVisCounter );
+ }
+
+ // check equivalence classes
+// RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 1 );
+// RetValue2 = Ssw_ClassesRefine( p->ppClasses, 1 );
+ // refine these nodes
+ RetValue1 = Ssw_ClassesRefineConst1Group( p->ppClasses, p->vResimConsts, 1 );
+ RetValue2 = 0;
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vResimClasses, pRepr, i )
+ RetValue2 += Ssw_ClassesRefineOneClass( p->ppClasses, pRepr, 1 );
+
+ // prepare simulation info for the next round
+ Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 );
+ p->nPatterns = 0;
+ p->nSimRounds++;
+p->timeSimSat += clock() - clk;
+ return RetValue1 > 0 || RetValue2 > 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging for the internal nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ManSweepDyn( Ssw_Man_t * p )
+{
+ Bar_Progress_t * pProgress = NULL;
+ Aig_Obj_t * pObj, * pObjNew;
+ int clk, i, f;
+
+ // perform speculative reduction
+clk = clock();
+ // create timeframes
+ p->pFrames = Ssw_FramesWithClasses( p );
+ Aig_ManFanoutStart( p->pFrames );
+ p->nSRMiterMaxId = Aig_ManObjNumMax( p->pFrames );
+
+ // map constants and PIs of the last frame
+ f = p->pPars->nFramesK;
+ Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) );
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ Ssw_ObjSetFrame( p, pObj, f, Aig_ObjCreatePi(p->pFrames) );
+ Aig_ManSetPioNumbers( p->pFrames );
+ // label nodes corresponding to primary inputs
+ Ssw_ManLabelPiNodes( p );
+p->timeReduce += clock() - clk;
+
+ // prepare simulation info
+ assert( p->vSimInfo == NULL );
+ p->vSimInfo = Vec_PtrAllocSimInfo( Aig_ManPiNum(p->pFrames), 1 );
+ Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 );
+
+ // sweep internal nodes
+ p->fRefined = 0;
+ Ssw_ClassesClearRefined( p->ppClasses );
+ if ( p->pPars->fVerbose )
+ pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) );
+ p->iNodeStart = 0;
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ {
+ if ( p->iNodeStart == 0 )
+ p->iNodeStart = i;
+ if ( p->pPars->fVerbose )
+ Bar_ProgressUpdate( pProgress, i, NULL );
+ if ( Saig_ObjIsLo(p->pAig, pObj) )
+ p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 0, NULL );
+ else if ( Aig_ObjIsNode(pObj) )
+ {
+ pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) );
+ Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+ p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 0, NULL );
+ }
+ // check if it is time to recycle the solver
+ if ( p->pMSat->pSat == NULL ||
+ (p->pPars->nSatVarMax2 &&
+ p->pMSat->nSatVars > p->pPars->nSatVarMax2 &&
+ p->nRecycleCalls > p->pPars->nRecycleCalls2) )
+ {
+ // resimulate
+ if ( p->nPatterns > 0 )
+ {
+ p->iNodeLast = i;
+ if ( p->pPars->fLocalSim )
+ Ssw_ManSweepResimulateDynLocal( p, f );
+ else
+ Ssw_ManSweepResimulateDyn( p, f );
+ p->iNodeStart = i+1;
+ }
+// printf( "Recycling SAT solver with %d vars and %d calls.\n",
+// p->pMSat->nSatVars, p->nRecycleCalls );
+// Aig_ManCleanMarkAB( p->pAig );
+ Aig_ManCleanMarkAB( p->pFrames );
+ // label nodes corresponding to primary inputs
+ Ssw_ManLabelPiNodes( p );
+ // replace the solver
+ if ( p->pMSat )
+ {
+ p->nVarsMax = Abc_MaxInt( p->nVarsMax, p->pMSat->nSatVars );
+ p->nCallsMax = Abc_MaxInt( p->nCallsMax, p->pMSat->nSolverCalls );
+ Ssw_SatStop( p->pMSat );
+ p->nRecycles++;
+ p->nRecyclesTotal++;
+ p->nRecycleCalls = 0;
+ }
+ p->pMSat = Ssw_SatStart( 0 );
+ assert( p->nPatterns == 0 );
+ }
+ // resimulate
+ if ( p->nPatterns == 32 )
+ {
+ p->iNodeLast = i;
+ if ( p->pPars->fLocalSim )
+ Ssw_ManSweepResimulateDynLocal( p, f );
+ else
+ Ssw_ManSweepResimulateDyn( p, f );
+ p->iNodeStart = i+1;
+ }
+ }
+ // resimulate
+ if ( p->nPatterns > 0 )
+ {
+ p->iNodeLast = i;
+ if ( p->pPars->fLocalSim )
+ Ssw_ManSweepResimulateDynLocal( p, f );
+ else
+ Ssw_ManSweepResimulateDyn( p, f );
+ }
+ // collect stats
+ if ( p->pPars->fVerbose )
+ Bar_ProgressStop( pProgress );
+
+ // cleanup
+// Ssw_ClassesCheck( p->ppClasses );
+ return p->fRefined;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/ssw/sswFilter.c b/src/proof/ssw/sswFilter.c
new file mode 100644
index 00000000..380ac7e5
--- /dev/null
+++ b/src/proof/ssw/sswFilter.c
@@ -0,0 +1,493 @@
+/**CFile****************************************************************
+
+ FileName [sswConstr.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Inductive prover with constraints.]
+
+ Synopsis [One round of SAT sweeping.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 1, 2008.]
+
+ Revision [$Id: sswConstr.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+#include "src/aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging for one node.]
+
+ Description [Returns the fraiged node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ManRefineByFilterSim( Ssw_Man_t * p, int nFrames )
+{
+ Aig_Obj_t * pObj, * pObjLi;
+ int f, i, RetValue1, RetValue2;
+ assert( nFrames > 0 );
+ // assign register outputs
+ Saig_ManForEachLi( p->pAig, pObj, i )
+ pObj->fMarkB = Abc_InfoHasBit( p->pPatWords, Saig_ManPiNum(p->pAig) + i );
+ // simulate the timeframes
+ for ( f = 0; f < nFrames; f++ )
+ {
+ // set the PI simulation information
+ Aig_ManConst1(p->pAig)->fMarkB = 1;
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ pObj->fMarkB = 0;
+ Saig_ManForEachLiLo( p->pAig, pObjLi, pObj, i )
+ pObj->fMarkB = pObjLi->fMarkB;
+ // simulate internal nodes
+ Aig_ManForEachNode( p->pAig, pObj, i )
+ pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) )
+ & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) );
+ // assign the COs
+ Aig_ManForEachPo( p->pAig, pObj, i )
+ pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) );
+ // transfer
+ if ( f == 0 )
+ { // copy markB into phase
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ pObj->fPhase = pObj->fMarkB;
+ }
+ else
+ { // refine classes
+ RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 0 );
+ RetValue2 = Ssw_ClassesRefine( p->ppClasses, 0 );
+ }
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging for one node.]
+
+ Description [Returns the fraiged node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ManRollForward( Ssw_Man_t * p, int nFrames )
+{
+ Aig_Obj_t * pObj, * pObjLi;
+ int f, i;
+ assert( nFrames > 0 );
+ // assign register outputs
+ Saig_ManForEachLi( p->pAig, pObj, i )
+ pObj->fMarkB = Abc_InfoHasBit( p->pPatWords, Saig_ManPiNum(p->pAig) + i );
+ // simulate the timeframes
+ for ( f = 0; f < nFrames; f++ )
+ {
+ // set the PI simulation information
+ Aig_ManConst1(p->pAig)->fMarkB = 1;
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ pObj->fMarkB = Aig_ManRandom(0) & 1;
+ Saig_ManForEachLiLo( p->pAig, pObjLi, pObj, i )
+ pObj->fMarkB = pObjLi->fMarkB;
+ // simulate internal nodes
+ Aig_ManForEachNode( p->pAig, pObj, i )
+ pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) )
+ & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) );
+ // assign the COs
+ Aig_ManForEachPo( p->pAig, pObj, i )
+ pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) );
+ }
+ // record the new pattern
+ Saig_ManForEachLi( p->pAig, pObj, i )
+ if ( pObj->fMarkB ^ Abc_InfoHasBit(p->pPatWords, Saig_ManPiNum(p->pAig) + i) )
+ Abc_InfoXorBit( p->pPatWords, Saig_ManPiNum(p->pAig) + i );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging for one node.]
+
+ Description [Returns the fraiged node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ManFindStartingState( Ssw_Man_t * p, Abc_Cex_t * pCex )
+{
+ Aig_Obj_t * pObj, * pObjLi;
+ int f, i, iBit;
+ // assign register outputs
+ Saig_ManForEachLi( p->pAig, pObj, i )
+ pObj->fMarkB = 0;
+ // simulate the timeframes
+ iBit = pCex->nRegs;
+ for ( f = 0; f <= pCex->iFrame; f++ )
+ {
+ // set the PI simulation information
+ Aig_ManConst1(p->pAig)->fMarkB = 1;
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ pObj->fMarkB = Abc_InfoHasBit( pCex->pData, iBit++ );
+ Saig_ManForEachLiLo( p->pAig, pObjLi, pObj, i )
+ pObj->fMarkB = pObjLi->fMarkB;
+ // simulate internal nodes
+ Aig_ManForEachNode( p->pAig, pObj, i )
+ pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) )
+ & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) );
+ // assign the COs
+ Aig_ManForEachPo( p->pAig, pObj, i )
+ pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) );
+ }
+ assert( iBit == pCex->nBits );
+ // check that the output failed as expected -- cannot check because it is not an SRM!
+// pObj = Aig_ManPo( p->pAig, pCex->iPo );
+// if ( pObj->fMarkB != 1 )
+// printf( "The counter-example does not refine the output.\n" );
+ // record the new pattern
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ if ( pObj->fMarkB ^ Abc_InfoHasBit(p->pPatWords, Saig_ManPiNum(p->pAig) + i) )
+ Abc_InfoXorBit( p->pPatWords, Saig_ManPiNum(p->pAig) + i );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging for one node.]
+
+ Description [Returns the fraiged node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ManSweepNodeFilter( Ssw_Man_t * p, Aig_Obj_t * pObj, int f )
+{
+ Aig_Obj_t * pObjRepr, * pObjFraig, * pObjFraig2, * pObjReprFraig;
+ int RetValue;
+ // get representative of this class
+ pObjRepr = Aig_ObjRepr( p->pAig, pObj );
+ if ( pObjRepr == NULL )
+ return 0;
+ // get the fraiged node
+ pObjFraig = Ssw_ObjFrame( p, pObj, f );
+ // get the fraiged representative
+ pObjReprFraig = Ssw_ObjFrame( p, pObjRepr, f );
+ // check if constant 0 pattern distinquishes these nodes
+ assert( pObjFraig != NULL && pObjReprFraig != NULL );
+ assert( (pObj->fPhase == pObjRepr->fPhase) == (Aig_ObjPhaseReal(pObjFraig) == Aig_ObjPhaseReal(pObjReprFraig)) );
+ // if the fraiged nodes are the same, return
+ if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) )
+ return 0;
+ // call equivalence checking
+ if ( Aig_Regular(pObjFraig) != Aig_ManConst1(p->pFrames) )
+ RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) );
+ else
+ RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjFraig), Aig_Regular(pObjReprFraig) );
+ if ( RetValue == 1 ) // proved equivalent
+ {
+ pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase );
+ Ssw_ObjSetFrame( p, pObj, f, pObjFraig2 );
+ return 0;
+ }
+ if ( RetValue == -1 ) // timed out
+ {
+// Ssw_ClassesRemoveNode( p->ppClasses, pObj );
+ return 1;
+ }
+ // disproved equivalence
+ Ssw_SmlSavePatternAig( p, f );
+ Ssw_ManResimulateBit( p, pObj, pObjRepr );
+ assert( Aig_ObjRepr( p->pAig, pObj ) != pObjRepr );
+ if ( Aig_ObjRepr( p->pAig, pObj ) == pObjRepr )
+ {
+ printf( "Ssw_ManSweepNodeFilter(): Failed to refine representative.\n" );
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging for the internal nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Obj_t * Ssw_ManSweepBmcFilter_rec( Ssw_Man_t * p, Aig_Obj_t * pObj, int f )
+{
+ Aig_Obj_t * pObjNew, * pObjLi;
+ pObjNew = Ssw_ObjFrame( p, pObj, f );
+ if ( pObjNew )
+ return pObjNew;
+ assert( !Saig_ObjIsPi(p->pAig, pObj) );
+ if ( Saig_ObjIsLo(p->pAig, pObj) )
+ {
+ assert( f > 0 );
+ pObjLi = Saig_ObjLoToLi( p->pAig, pObj );
+ pObjNew = Ssw_ManSweepBmcFilter_rec( p, Aig_ObjFanin0(pObjLi), f-1 );
+ pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObjLi) );
+ }
+ else
+ {
+ assert( Aig_ObjIsNode(pObj) );
+ Ssw_ManSweepBmcFilter_rec( p, Aig_ObjFanin0(pObj), f );
+ Ssw_ManSweepBmcFilter_rec( p, Aig_ObjFanin1(pObj), f );
+ pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) );
+ }
+ Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+ assert( pObjNew != NULL );
+ return pObjNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Filter equivalence classes of nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ManSweepBmcFilter( Ssw_Man_t * p, int TimeLimit )
+{
+ Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo;
+ int f, f1, i, clkTotal = clock();
+ // start initialized timeframes
+ p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK );
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ {
+ if ( Abc_InfoHasBit( p->pPatWords, Saig_ManPiNum(p->pAig) + i ) )
+ {
+ Ssw_ObjSetFrame( p, pObj, 0, Aig_ManConst1(p->pFrames) );
+//printf( "1" );
+ }
+ else
+ {
+ Ssw_ObjSetFrame( p, pObj, 0, Aig_ManConst0(p->pFrames) );
+//printf( "0" );
+ }
+ }
+//printf( "\n" );
+
+ // sweep internal nodes
+ for ( f = 0; f < p->pPars->nFramesK; f++ )
+ {
+ // realloc mapping of timeframes
+ if ( f == p->nFrames-1 )
+ {
+ Aig_Obj_t ** pNodeToFrames;
+ pNodeToFrames = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) * 2 * p->nFrames );
+ for ( f1 = 0; f1 < p->nFrames; f1++ )
+ {
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ pNodeToFrames[2*p->nFrames*pObj->Id + f1] = Ssw_ObjFrame( p, pObj, f1 );
+ }
+ ABC_FREE( p->pNodeToFrames );
+ p->pNodeToFrames = pNodeToFrames;
+ p->nFrames *= 2;
+ }
+ // map constants and PIs
+ Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) );
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ {
+ pObjNew = Aig_ObjCreatePi(p->pFrames);
+ Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+ }
+ // sweep internal nodes
+ Aig_ManForEachNode( p->pAig, pObj, i )
+ {
+ pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) );
+ Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+ if ( Ssw_ManSweepNodeFilter( p, pObj, f ) )
+ break;
+ }
+ // printout
+ if ( p->pPars->fVerbose )
+ {
+ printf( "Frame %4d : ", f );
+ Ssw_ClassesPrint( p->ppClasses, 0 );
+ }
+ if ( i < Vec_PtrSize(p->pAig->vObjs) )
+ {
+ if ( p->pPars->fVerbose )
+ printf( "Exceeded the resource limits (%d conflicts). Quitting...\n", p->pPars->nBTLimit );
+ break;
+ }
+ // quit if this is the last timeframe
+ if ( f == p->pPars->nFramesK - 1 )
+ {
+ if ( p->pPars->fVerbose )
+ printf( "Exceeded the time frame limit (%d time frames). Quitting...\n", p->pPars->nFramesK );
+ break;
+ }
+ // check timeout
+ if ( TimeLimit && ((float)TimeLimit <= (float)(clock()-clkTotal)/(float)(CLOCKS_PER_SEC)) )
+ break;
+ // transfer latch input to the latch outputs
+ Aig_ManForEachPo( p->pAig, pObj, i )
+ Ssw_ObjSetFrame( p, pObj, f, Ssw_ObjChild0Fra(p, pObj, f) );
+ // build logic cones for register outputs
+ Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+ {
+ pObjNew = Ssw_ObjFrame( p, pObjLi, f );
+ Ssw_ObjSetFrame( p, pObjLo, f+1, pObjNew );
+ Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pObjNew) );//
+ }
+ }
+ // verify
+// Ssw_ClassesCheck( p->ppClasses );
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Filter equivalence classes of nodes.]
+
+ Description [Unrolls at most nFramesMax frames. Works with nConfMax
+ conflicts until the first undefined SAT call. Verbose prints the message.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SignalFilter( Aig_Man_t * pAig, int nFramesMax, int nConfMax, int nRounds, int TimeLimit, int TimeLimit2, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose )
+{
+ Ssw_Pars_t Pars, * pPars = &Pars;
+ Ssw_Man_t * p;
+ int r, TimeLimitPart, clkTotal = clock();
+ int nTimeToStop = TimeLimit ? TimeLimit + time(NULL) : 0;
+ assert( Aig_ManRegNum(pAig) > 0 );
+ assert( Aig_ManConstrNum(pAig) == 0 );
+ // consider the case of empty AIG
+ if ( Aig_ManNodeNum(pAig) == 0 )
+ return;
+ // reset random numbers
+ Aig_ManRandom( 1 );
+ // if parameters are not given, create them
+ Ssw_ManSetDefaultParams( pPars = &Pars );
+ pPars->nFramesK = 3; //nFramesMax;
+ pPars->nBTLimit = nConfMax;
+ pPars->TimeLimit = TimeLimit;
+ pPars->fVerbose = fVerbose;
+ // start the induction manager
+ p = Ssw_ManCreate( pAig, pPars );
+ pPars->nFramesK = nFramesMax;
+ // create trivial equivalence classes with all nodes being candidates for constant 1
+ if ( pAig->pReprs == NULL )
+ p->ppClasses = Ssw_ClassesPrepareSimple( pAig, fLatchOnly, 0 );
+ else
+ p->ppClasses = Ssw_ClassesPrepareFromReprs( pAig );
+ Ssw_ClassesSetData( p->ppClasses, NULL, NULL, Ssw_SmlObjIsConstBit, Ssw_SmlObjsAreEqualBit );
+ assert( p->vInits == NULL );
+ // compute starting state if needed
+ if ( pCex )
+ Ssw_ManFindStartingState( p, pCex );
+ // refine classes using BMC
+ for ( r = 0; r < nRounds; r++ )
+ {
+ if ( p->pPars->fVerbose )
+ printf( "Round %3d:\n", r );
+ // start filtering equivalence classes
+ Ssw_ManRefineByFilterSim( p, p->pPars->nFramesK );
+ if ( Ssw_ClassesCand1Num(p->ppClasses) == 0 && Ssw_ClassesClassNum(p->ppClasses) == 0 )
+ {
+ printf( "All equivalences are refined away.\n" );
+ break;
+ }
+ // printout
+ if ( p->pPars->fVerbose )
+ {
+ printf( "Initial : " );
+ Ssw_ClassesPrint( p->ppClasses, 0 );
+ }
+ p->pMSat = Ssw_SatStart( 0 );
+ TimeLimitPart = TimeLimit ? nTimeToStop - time(NULL) : 0;
+ if ( TimeLimit2 )
+ {
+ if ( TimeLimitPart )
+ TimeLimitPart = Abc_MinInt( TimeLimitPart, TimeLimit2 );
+ else
+ TimeLimitPart = TimeLimit2;
+ }
+ Ssw_ManSweepBmcFilter( p, TimeLimitPart );
+ Ssw_SatStop( p->pMSat );
+ p->pMSat = NULL;
+ Ssw_ManCleanup( p );
+ // simulate pattern forward
+ Ssw_ManRollForward( p, p->pPars->nFramesK );
+ // check timeout
+ if ( TimeLimit && time(NULL) > nTimeToStop )
+ {
+ printf( "Reached timeout (%d seconds).\n", TimeLimit );
+ break;
+ }
+ }
+ // cleanup
+ Aig_ManSetPhase( p->pAig );
+ Aig_ManCleanMarkB( p->pAig );
+ // cleanup
+ pPars->fVerbose = 0;
+ Ssw_ManStop( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Filter equivalence classes of nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SignalFilterGia( Gia_Man_t * p, int nFramesMax, int nConfMax, int nRounds, int TimeLimit, int TimeLimit2, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose )
+{
+ Aig_Man_t * pAig;
+ pAig = Gia_ManToAigSimple( p );
+ if ( p->pReprs != NULL )
+ {
+ Gia_ManReprToAigRepr2( pAig, p );
+ ABC_FREE( p->pReprs );
+ ABC_FREE( p->pNexts );
+ }
+ Ssw_SignalFilter( pAig, nFramesMax, nConfMax, nRounds, TimeLimit, TimeLimit2, pCex, fLatchOnly, fVerbose );
+ Gia_ManReprFromAigRepr( pAig, p );
+ Aig_ManStop( pAig );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/ssw/sswInt.h b/src/proof/ssw/sswInt.h
new file mode 100644
index 00000000..acd273fd
--- /dev/null
+++ b/src/proof/ssw/sswInt.h
@@ -0,0 +1,302 @@
+/**CFile****************************************************************
+
+ FileName [sswInt.h]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Inductive prover with constraints.]
+
+ Synopsis [External declarations.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 1, 2008.]
+
+ Revision [$Id: sswInt.h,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#ifndef ABC__aig__ssw__sswInt_h
+#define ABC__aig__ssw__sswInt_h
+
+
+////////////////////////////////////////////////////////////////////////
+/// INCLUDES ///
+////////////////////////////////////////////////////////////////////////
+
+#include "src/aig/saig/saig.h"
+#include "src/sat/bsat/satSolver.h"
+#include "ssw.h"
+#include "src/aig/ioa/ioa.h"
+
+////////////////////////////////////////////////////////////////////////
+/// PARAMETERS ///
+////////////////////////////////////////////////////////////////////////
+
+
+
+ABC_NAMESPACE_HEADER_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// BASIC TYPES ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Ssw_Man_t_ Ssw_Man_t; // signal correspondence manager
+typedef struct Ssw_Frm_t_ Ssw_Frm_t; // unrolled frames manager
+typedef struct Ssw_Sat_t_ Ssw_Sat_t; // SAT solver manager
+typedef struct Ssw_Cla_t_ Ssw_Cla_t; // equivalence classe manager
+
+struct Ssw_Man_t_
+{
+ // parameters
+ Ssw_Pars_t * pPars; // parameters
+ int nFrames; // for quick lookup
+ // AIGs used in the package
+ Aig_Man_t * pAig; // user-given AIG
+ Aig_Man_t * pFrames; // final AIG
+ Aig_Obj_t ** pNodeToFrames; // mapping of AIG nodes into FRAIG nodes
+ // equivalence classes
+ Ssw_Cla_t * ppClasses; // equivalence classes of nodes
+ int fRefined; // is set to 1 when refinement happens
+ // SAT solving
+ Ssw_Sat_t * pMSatBmc; // SAT manager for base case
+ Ssw_Sat_t * pMSat; // SAT manager for inductive case
+ // SAT solving (latch corr only)
+ Vec_Ptr_t * vSimInfo; // simulation information for the framed PIs
+ int nPatterns; // the number of patterns saved
+ int nSimRounds; // the number of simulation rounds performed
+ int nCallsCount; // the number of calls in this round
+ int nCallsDelta; // the number of calls to skip
+ int nCallsSat; // the number of SAT calls in this round
+ int nCallsUnsat; // the number of UNSAT calls in this round
+ int nRecycleCalls; // the number of calls since last recycling
+ int nRecycles; // the number of time SAT solver was recycled
+ int nRecyclesTotal; // the number of time SAT solver was recycled
+ int nVarsMax; // the maximum variables in the solver
+ int nCallsMax; // the maximum number of SAT calls
+ // uniqueness
+ Vec_Ptr_t * vCommon; // the set of common variables in the logic cones
+ int iOutputLit; // the output literal of the uniqueness constraint
+ Vec_Int_t * vDiffPairs; // is set to 1 if reg pair can be diff
+ int nUniques; // the number of uniqueness constraints used
+ int nUniquesAdded; // useful uniqueness constraints
+ int nUniquesUseful; // useful uniqueness constraints
+ // dynamic constraint addition
+ int nSRMiterMaxId; // max ID after which the last frame begins
+ Vec_Ptr_t * vNewLos; // new time frame LOs of to constrain
+ Vec_Int_t * vNewPos; // new time frame POs of to add constraints
+ int * pVisited; // flags to label visited nodes in each frame
+ int nVisCounter; // the traversal ID
+ // sequential simulation
+ Ssw_Sml_t * pSml; // the simulator
+ int iNodeStart; // the first node considered
+ int iNodeLast; // the last node considered
+ Vec_Ptr_t * vResimConsts; // resimulation constants
+ Vec_Ptr_t * vResimClasses; // resimulation classes
+ Vec_Int_t * vInits; // the init values of primary inputs under constraints
+ // counter example storage
+ int nPatWords; // the number of words in the counter example
+ unsigned * pPatWords; // the counter example
+ // constraints
+ int nConstrTotal; // the number of total constraints
+ int nConstrReduced; // the number of reduced constraints
+ int nStrangers; // the number of strange situations
+ // SAT calls statistics
+ int nSatCalls; // the number of SAT calls
+ int nSatProof; // the number of proofs
+ int nSatFailsReal; // the number of timeouts
+ int nSatCallsUnsat; // the number of unsat SAT calls
+ int nSatCallsSat; // the number of sat SAT calls
+ // node/register/lit statistics
+ int nLitsBeg;
+ int nLitsEnd;
+ int nNodesBeg;
+ int nNodesEnd;
+ int nRegsBeg;
+ int nRegsEnd;
+ // equiv statistis
+ int nConesTotal;
+ int nConesConstr;
+ int nEquivsTotal;
+ int nEquivsConstr;
+ int nNodesBegC;
+ int nNodesEndC;
+ int nRegsBegC;
+ int nRegsEndC;
+ // runtime stats
+ int timeBmc; // bounded model checking
+ int timeReduce; // speculative reduction
+ int timeMarkCones; // marking the cones not to be refined
+ int timeSimSat; // simulation of the counter-examples
+ int timeSat; // solving SAT
+ int timeSatSat; // sat
+ int timeSatUnsat; // unsat
+ int timeSatUndec; // undecided
+ int timeOther; // other runtime
+ int timeTotal; // total runtime
+};
+
+// internal SAT manager
+struct Ssw_Sat_t_
+{
+ Aig_Man_t * pAig; // the AIG manager
+ int fPolarFlip; // flips polarity
+ sat_solver * pSat; // recyclable SAT solver
+ int nSatVars; // the counter of SAT variables
+ Vec_Int_t * vSatVars; // mapping of each node into its SAT var
+ Vec_Ptr_t * vFanins; // fanins of the CNF node
+ Vec_Ptr_t * vUsedPis; // the PIs with SAT variables
+ int nSolverCalls; // the total number of SAT calls
+};
+
+// internal frames manager
+struct Ssw_Frm_t_
+{
+ Aig_Man_t * pAig; // user-given AIG
+ int nObjs; // offset in terms of AIG nodes
+ int nFrames; // the number of frames in current unrolling
+ Aig_Man_t * pFrames; // unrolled AIG
+ Vec_Ptr_t * vAig2Frm; // mapping of AIG nodes into frame nodes
+};
+
+////////////////////////////////////////////////////////////////////////
+/// MACRO DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static inline int Ssw_ObjSatNum( Ssw_Sat_t * p, Aig_Obj_t * pObj ) { return Vec_IntGetEntry( p->vSatVars, pObj->Id ); }
+static inline void Ssw_ObjSetSatNum( Ssw_Sat_t * p, Aig_Obj_t * pObj, int Num ) { Vec_IntSetEntry(p->vSatVars, pObj->Id, Num); }
+
+static inline int Ssw_ObjIsConst1Cand( Aig_Man_t * pAig, Aig_Obj_t * pObj )
+{
+ return Aig_ObjRepr(pAig, pObj) == Aig_ManConst1(pAig);
+}
+static inline void Ssw_ObjSetConst1Cand( Aig_Man_t * pAig, Aig_Obj_t * pObj )
+{
+ assert( !Ssw_ObjIsConst1Cand( pAig, pObj ) );
+ Aig_ObjSetRepr( pAig, pObj, Aig_ManConst1(pAig) );
+}
+
+static inline Aig_Obj_t * Ssw_ObjFrame( Ssw_Man_t * p, Aig_Obj_t * pObj, int i ) { return p->pNodeToFrames[p->nFrames*pObj->Id + i]; }
+static inline void Ssw_ObjSetFrame( Ssw_Man_t * p, Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { p->pNodeToFrames[p->nFrames*pObj->Id + i] = pNode; }
+
+static inline Aig_Obj_t * Ssw_ObjChild0Fra( Ssw_Man_t * p, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Ssw_ObjFrame(p, Aig_ObjFanin0(pObj), i), Aig_ObjFaninC0(pObj)) : NULL; }
+static inline Aig_Obj_t * Ssw_ObjChild1Fra( Ssw_Man_t * p, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Ssw_ObjFrame(p, Aig_ObjFanin1(pObj), i), Aig_ObjFaninC1(pObj)) : NULL; }
+
+static inline Aig_Obj_t * Ssw_ObjFrame_( Ssw_Frm_t * p, Aig_Obj_t * pObj, int i ) { return (Aig_Obj_t *)Vec_PtrGetEntry( p->vAig2Frm, p->nObjs*i+pObj->Id ); }
+static inline void Ssw_ObjSetFrame_( Ssw_Frm_t * p, Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { Vec_PtrSetEntry( p->vAig2Frm, p->nObjs*i+pObj->Id, pNode ); }
+
+static inline Aig_Obj_t * Ssw_ObjChild0Fra_( Ssw_Frm_t * p, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Ssw_ObjFrame_(p, Aig_ObjFanin0(pObj), i), Aig_ObjFaninC0(pObj)) : NULL; }
+static inline Aig_Obj_t * Ssw_ObjChild1Fra_( Ssw_Frm_t * p, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Ssw_ObjFrame_(p, Aig_ObjFanin1(pObj), i), Aig_ObjFaninC1(pObj)) : NULL; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/*=== sswAig.c ===================================================*/
+extern Ssw_Frm_t * Ssw_FrmStart( Aig_Man_t * pAig );
+extern void Ssw_FrmStop( Ssw_Frm_t * p );
+extern Aig_Man_t * Ssw_FramesWithClasses( Ssw_Man_t * p );
+extern Aig_Man_t * Ssw_SpeculativeReduction( Ssw_Man_t * p );
+/*=== sswBmc.c ===================================================*/
+/*=== sswClass.c =================================================*/
+extern Ssw_Cla_t * Ssw_ClassesStart( Aig_Man_t * pAig );
+extern void Ssw_ClassesSetData( Ssw_Cla_t * p, void * pManData,
+ unsigned (*pFuncNodeHash)(void *,Aig_Obj_t *),
+ int (*pFuncNodeIsConst)(void *,Aig_Obj_t *),
+ int (*pFuncNodesAreEqual)(void *,Aig_Obj_t *, Aig_Obj_t *) );
+extern void Ssw_ClassesStop( Ssw_Cla_t * p );
+extern Aig_Man_t * Ssw_ClassesReadAig( Ssw_Cla_t * p );
+extern Vec_Ptr_t * Ssw_ClassesGetRefined( Ssw_Cla_t * p );
+extern void Ssw_ClassesClearRefined( Ssw_Cla_t * p );
+extern int Ssw_ClassesCand1Num( Ssw_Cla_t * p );
+extern int Ssw_ClassesClassNum( Ssw_Cla_t * p );
+extern int Ssw_ClassesLitNum( Ssw_Cla_t * p );
+extern Aig_Obj_t ** Ssw_ClassesReadClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, int * pnSize );
+extern void Ssw_ClassesCollectClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, Vec_Ptr_t * vClass );
+extern void Ssw_ClassesCheck( Ssw_Cla_t * p );
+extern void Ssw_ClassesPrint( Ssw_Cla_t * p, int fVeryVerbose );
+extern void Ssw_ClassesRemoveNode( Ssw_Cla_t * p, Aig_Obj_t * pObj );
+extern Ssw_Cla_t * Ssw_ClassesPrepare( Aig_Man_t * pAig, int nFramesK, int fLatchCorr, int fConstCorr, int fOutputCorr, int nMaxLevs, int fVerbose );
+extern Ssw_Cla_t * Ssw_ClassesPrepareSimple( Aig_Man_t * pAig, int fLatchCorr, int nMaxLevs );
+extern Ssw_Cla_t * Ssw_ClassesPrepareFromReprs( Aig_Man_t * pAig );
+extern Ssw_Cla_t * Ssw_ClassesPrepareTargets( Aig_Man_t * pAig );
+extern Ssw_Cla_t * Ssw_ClassesPreparePairs( Aig_Man_t * pAig, Vec_Int_t ** pvClasses );
+extern Ssw_Cla_t * Ssw_ClassesPreparePairsSimple( Aig_Man_t * pMiter, Vec_Int_t * vPairs );
+extern int Ssw_ClassesRefine( Ssw_Cla_t * p, int fRecursive );
+extern int Ssw_ClassesRefineGroup( Ssw_Cla_t * p, Vec_Ptr_t * vReprs, int fRecursive );
+extern int Ssw_ClassesRefineOneClass( Ssw_Cla_t * p, Aig_Obj_t * pRepr, int fRecursive );
+extern int Ssw_ClassesRefineConst1Group( Ssw_Cla_t * p, Vec_Ptr_t * vRoots, int fRecursive );
+extern int Ssw_ClassesRefineConst1( Ssw_Cla_t * p, int fRecursive );
+extern int Ssw_ClassesPrepareRehash( Ssw_Cla_t * p, Vec_Ptr_t * vCands, int fConstCorr );
+/*=== sswCnf.c ===================================================*/
+extern Ssw_Sat_t * Ssw_SatStart( int fPolarFlip );
+extern void Ssw_SatStop( Ssw_Sat_t * p );
+extern void Ssw_CnfNodeAddToSolver( Ssw_Sat_t * p, Aig_Obj_t * pObj );
+extern int Ssw_CnfGetNodeValue( Ssw_Sat_t * p, Aig_Obj_t * pObjFraig );
+/*=== sswConstr.c ===================================================*/
+extern int Ssw_ManSweepBmcConstr( Ssw_Man_t * p );
+extern int Ssw_ManSweepConstr( Ssw_Man_t * p );
+extern void Ssw_ManRefineByConstrSim( Ssw_Man_t * p );
+/*=== sswCore.c ===================================================*/
+extern Aig_Man_t * Ssw_SignalCorrespondenceRefine( Ssw_Man_t * p );
+/*=== sswDyn.c ===================================================*/
+extern void Ssw_ManLoadSolver( Ssw_Man_t * p, Aig_Obj_t * pRepr, Aig_Obj_t * pObj );
+extern int Ssw_ManSweepDyn( Ssw_Man_t * p );
+/*=== sswLcorr.c ==========================================================*/
+extern int Ssw_ManSweepLatch( Ssw_Man_t * p );
+/*=== sswMan.c ===================================================*/
+extern Ssw_Man_t * Ssw_ManCreate( Aig_Man_t * pAig, Ssw_Pars_t * pPars );
+extern void Ssw_ManCleanup( Ssw_Man_t * p );
+extern void Ssw_ManStop( Ssw_Man_t * p );
+/*=== sswSat.c ===================================================*/
+extern int Ssw_NodesAreEquiv( Ssw_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew );
+extern int Ssw_NodesAreConstrained( Ssw_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew );
+extern int Ssw_NodeIsConstrained( Ssw_Man_t * p, Aig_Obj_t * pPoObj );
+/*=== sswSemi.c ===================================================*/
+extern int Ssw_FilterUsingSemi( Ssw_Man_t * pMan, int fCheckTargets, int nConfMax, int fVerbose );
+/*=== sswSim.c ===================================================*/
+extern unsigned Ssw_SmlObjHashWord( Ssw_Sml_t * p, Aig_Obj_t * pObj );
+extern int Ssw_SmlObjIsConstWord( Ssw_Sml_t * p, Aig_Obj_t * pObj );
+extern int Ssw_SmlObjsAreEqualWord( Ssw_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 );
+extern int Ssw_SmlObjIsConstBit( void * p, Aig_Obj_t * pObj );
+extern int Ssw_SmlObjsAreEqualBit( void * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 );
+extern void Ssw_SmlAssignRandomFrame( Ssw_Sml_t * p, Aig_Obj_t * pObj, int iFrame );
+extern Ssw_Sml_t * Ssw_SmlStart( Aig_Man_t * pAig, int nPref, int nFrames, int nWordsFrame );
+extern void Ssw_SmlClean( Ssw_Sml_t * p );
+extern void Ssw_SmlStop( Ssw_Sml_t * p );
+extern void Ssw_SmlObjAssignConst( Ssw_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame );
+extern void Ssw_SmlObjSetWord( Ssw_Sml_t * p, Aig_Obj_t * pObj, unsigned Word, int iWord, int iFrame );
+extern void Ssw_SmlAssignDist1Plus( Ssw_Sml_t * p, unsigned * pPat );
+extern void Ssw_SmlSimulateOne( Ssw_Sml_t * p );
+extern void Ssw_SmlSimulateOneFrame( Ssw_Sml_t * p );
+extern void Ssw_SmlSimulateOneDyn_rec( Ssw_Sml_t * p, Aig_Obj_t * pObj, int f, int * pVisited, int nVisCounter );
+extern void Ssw_SmlResimulateSeq( Ssw_Sml_t * p );
+/*=== sswSimSat.c ===================================================*/
+extern void Ssw_ManResimulateBit( Ssw_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr );
+extern void Ssw_ManResimulateWord( Ssw_Man_t * p, Aig_Obj_t * pCand, Aig_Obj_t * pRepr, int f );
+/*=== sswSweep.c ===================================================*/
+extern int Ssw_ManGetSatVarValue( Ssw_Man_t * p, Aig_Obj_t * pObj, int f );
+extern void Ssw_SmlSavePatternAig( Ssw_Man_t * p, int f );
+extern int Ssw_ManSweepNode( Ssw_Man_t * p, Aig_Obj_t * pObj, int f, int fBmc, Vec_Int_t * vPairs );
+extern int Ssw_ManSweepBmc( Ssw_Man_t * p );
+extern int Ssw_ManSweep( Ssw_Man_t * p );
+/*=== sswUnique.c ===================================================*/
+extern void Ssw_UniqueRegisterPairInfo( Ssw_Man_t * p );
+extern int Ssw_ManUniqueOne( Ssw_Man_t * p, Aig_Obj_t * pRepr, Aig_Obj_t * pObj, int fVerbose );
+extern int Ssw_ManUniqueAddConstraint( Ssw_Man_t * p, Vec_Ptr_t * vCommon, int f1, int f2 );
+
+
+
+ABC_NAMESPACE_HEADER_END
+
+
+
+#endif
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
diff --git a/src/proof/ssw/sswIslands.c b/src/proof/ssw/sswIslands.c
new file mode 100644
index 00000000..0802aca5
--- /dev/null
+++ b/src/proof/ssw/sswIslands.c
@@ -0,0 +1,598 @@
+/**CFile****************************************************************
+
+ FileName [sswIslands.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Inductive prover with constraints.]
+
+ Synopsis [Detection of islands of difference.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 1, 2008.]
+
+ Revision [$Id: sswIslands.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Creates pair of structurally equivalent nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_CreatePair( Vec_Int_t * vPairs, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
+{
+ pObj0->pData = pObj1;
+ pObj1->pData = pObj0;
+ Vec_IntPush( vPairs, pObj0->Id );
+ Vec_IntPush( vPairs, pObj1->Id );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Establishes relationship between nodes using pairing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_MatchingStart( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs )
+{
+ Aig_Obj_t * pObj0, * pObj1;
+ int i;
+ // create matching
+ Aig_ManCleanData( p0 );
+ Aig_ManCleanData( p1 );
+ for ( i = 0; i < Vec_IntSize(vPairs); i += 2 )
+ {
+ pObj0 = Aig_ManObj( p0, Vec_IntEntry(vPairs, i) );
+ pObj1 = Aig_ManObj( p1, Vec_IntEntry(vPairs, i+1) );
+ assert( pObj0->pData == NULL );
+ assert( pObj1->pData == NULL );
+ pObj0->pData = pObj1;
+ pObj1->pData = pObj0;
+ }
+ // make sure constants are matched
+ pObj0 = Aig_ManConst1( p0 );
+ pObj1 = Aig_ManConst1( p1 );
+ assert( pObj0->pData == pObj1 );
+ assert( pObj1->pData == pObj0 );
+ // make sure PIs are matched
+ Saig_ManForEachPi( p0, pObj0, i )
+ {
+ pObj1 = Aig_ManPi( p1, i );
+ assert( pObj0->pData == pObj1 );
+ assert( pObj1->pData == pObj0 );
+ }
+ // make sure the POs are not matched
+ Aig_ManForEachPo( p0, pObj0, i )
+ {
+ pObj1 = Aig_ManPo( p1, i );
+ assert( pObj0->pData == NULL );
+ assert( pObj1->pData == NULL );
+ }
+
+ // check that LIs/LOs are matched in sync
+ Saig_ManForEachLo( p0, pObj0, i )
+ {
+ if ( pObj0->pData == NULL )
+ continue;
+ pObj1 = (Aig_Obj_t *)pObj0->pData;
+ if ( !Saig_ObjIsLo(p1, pObj1) )
+ printf( "Mismatch between LO pairs.\n" );
+ }
+ Saig_ManForEachLo( p1, pObj1, i )
+ {
+ if ( pObj1->pData == NULL )
+ continue;
+ pObj0 = (Aig_Obj_t *)pObj1->pData;
+ if ( !Saig_ObjIsLo(p0, pObj0) )
+ printf( "Mismatch between LO pairs.\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Establishes relationship between nodes using pairing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_MatchingExtendOne( Aig_Man_t * p, Vec_Ptr_t * vNodes )
+{
+ Aig_Obj_t * pNext, * pObj;
+ int i, k, iFan;
+ Vec_PtrClear( vNodes );
+ Aig_ManIncrementTravId( p );
+ Aig_ManForEachObj( p, pObj, i )
+ {
+ if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) )
+ continue;
+ if ( pObj->pData != NULL )
+ continue;
+ if ( Saig_ObjIsLo(p, pObj) )
+ {
+ pNext = Saig_ObjLoToLi(p, pObj);
+ pNext = Aig_ObjFanin0(pNext);
+ if ( pNext->pData && !Aig_ObjIsTravIdCurrent(p, pNext) && !Aig_ObjIsConst1(pNext) )
+ {
+ Aig_ObjSetTravIdCurrent(p, pNext);
+ Vec_PtrPush( vNodes, pNext );
+ }
+ }
+ if ( Aig_ObjIsNode(pObj) )
+ {
+ pNext = Aig_ObjFanin0(pObj);
+ if ( pNext->pData && !Aig_ObjIsTravIdCurrent(p, pNext) )
+ {
+ Aig_ObjSetTravIdCurrent(p, pNext);
+ Vec_PtrPush( vNodes, pNext );
+ }
+ pNext = Aig_ObjFanin1(pObj);
+ if ( pNext->pData && !Aig_ObjIsTravIdCurrent(p, pNext) )
+ {
+ Aig_ObjSetTravIdCurrent(p, pNext);
+ Vec_PtrPush( vNodes, pNext );
+ }
+ }
+ Aig_ObjForEachFanout( p, pObj, pNext, iFan, k )
+ {
+ if ( Saig_ObjIsPo(p, pNext) )
+ continue;
+ if ( Saig_ObjIsLi(p, pNext) )
+ pNext = Saig_ObjLiToLo(p, pNext);
+ if ( pNext->pData && !Aig_ObjIsTravIdCurrent(p, pNext) )
+ {
+ Aig_ObjSetTravIdCurrent(p, pNext);
+ Vec_PtrPush( vNodes, pNext );
+ }
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Establishes relationship between nodes using pairing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_MatchingCountUnmached( Aig_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ Aig_ManForEachObj( p, pObj, i )
+ {
+ if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) )
+ continue;
+ if ( pObj->pData != NULL )
+ continue;
+ Counter++;
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Establishes relationship between nodes using pairing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_MatchingExtend( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose )
+{
+ Vec_Ptr_t * vNodes0, * vNodes1;
+ Aig_Obj_t * pNext0, * pNext1;
+ int d, k;
+ Aig_ManFanoutStart(p0);
+ Aig_ManFanoutStart(p1);
+ vNodes0 = Vec_PtrAlloc( 1000 );
+ vNodes1 = Vec_PtrAlloc( 1000 );
+ if ( fVerbose )
+ {
+ int nUnmached = Ssw_MatchingCountUnmached(p0);
+ printf( "Extending islands by %d steps:\n", nDist );
+ printf( "%2d : Total = %6d. Unmatched = %6d. Ratio = %6.2f %%\n",
+ 0, Aig_ManPiNum(p0) + Aig_ManNodeNum(p0),
+ nUnmached, 100.0 * nUnmached/(Aig_ManPiNum(p0) + Aig_ManNodeNum(p0)) );
+ }
+ for ( d = 0; d < nDist; d++ )
+ {
+ Ssw_MatchingExtendOne( p0, vNodes0 );
+ Ssw_MatchingExtendOne( p1, vNodes1 );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes0, pNext0, k )
+ {
+ pNext1 = (Aig_Obj_t *)pNext0->pData;
+ if ( pNext1 == NULL )
+ continue;
+ assert( pNext1->pData == pNext0 );
+ if ( Saig_ObjIsPi(p0, pNext1) )
+ continue;
+ pNext0->pData = NULL;
+ pNext1->pData = NULL;
+ }
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNodes1, pNext0, k )
+ {
+ pNext1 = (Aig_Obj_t *)pNext0->pData;
+ if ( pNext1 == NULL )
+ continue;
+ assert( pNext1->pData == pNext0 );
+ if ( Saig_ObjIsPi(p1, pNext1) )
+ continue;
+ pNext0->pData = NULL;
+ pNext1->pData = NULL;
+ }
+ if ( fVerbose )
+ {
+ int nUnmached = Ssw_MatchingCountUnmached(p0);
+ printf( "%2d : Total = %6d. Unmatched = %6d. Ratio = %6.2f %%\n",
+ d+1, Aig_ManPiNum(p0) + Aig_ManNodeNum(p0),
+ nUnmached, 100.0 * nUnmached/(Aig_ManPiNum(p0) + Aig_ManNodeNum(p0)) );
+ }
+ }
+ Vec_PtrFree( vNodes0 );
+ Vec_PtrFree( vNodes1 );
+ Aig_ManFanoutStop(p0);
+ Aig_ManFanoutStop(p1);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Used differences in p0 to complete p1.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_MatchingComplete( Aig_Man_t * p0, Aig_Man_t * p1 )
+{
+ Vec_Ptr_t * vNewLis;
+ Aig_Obj_t * pObj0, * pObj0Li, * pObj1;
+ int i;
+ // create register outputs in p0 that are absent in p1
+ vNewLis = Vec_PtrAlloc( 100 );
+ Saig_ManForEachLiLo( p0, pObj0Li, pObj0, i )
+ {
+ if ( pObj0->pData != NULL )
+ continue;
+ pObj1 = Aig_ObjCreatePi( p1 );
+ pObj0->pData = pObj1;
+ pObj1->pData = pObj0;
+ Vec_PtrPush( vNewLis, pObj0Li );
+ }
+ // add missing nodes in the topological order
+ Aig_ManForEachNode( p0, pObj0, i )
+ {
+ if ( pObj0->pData != NULL )
+ continue;
+ pObj1 = Aig_And( p1, Aig_ObjChild0Copy(pObj0), Aig_ObjChild1Copy(pObj0) );
+ pObj0->pData = pObj1;
+ pObj1->pData = pObj0;
+ }
+ // create register outputs in p0 that are absent in p1
+ Vec_PtrForEachEntry( Aig_Obj_t *, vNewLis, pObj0Li, i )
+ Aig_ObjCreatePo( p1, Aig_ObjChild0Copy(pObj0Li) );
+ // increment the number of registers
+ Aig_ManSetRegNum( p1, Aig_ManRegNum(p1) + Vec_PtrSize(vNewLis) );
+ Vec_PtrFree( vNewLis );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Derives matching for all pairs.]
+
+ Description [Modifies both AIGs.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Ssw_MatchingPairs( Aig_Man_t * p0, Aig_Man_t * p1 )
+{
+ Vec_Int_t * vPairsNew;
+ Aig_Obj_t * pObj0, * pObj1;
+ int i;
+ // check correctness
+ assert( Aig_ManPiNum(p0) == Aig_ManPiNum(p1) );
+ assert( Aig_ManPoNum(p0) == Aig_ManPoNum(p1) );
+ assert( Aig_ManRegNum(p0) == Aig_ManRegNum(p1) );
+ assert( Aig_ManObjNum(p0) == Aig_ManObjNum(p1) );
+ // create complete pairs
+ vPairsNew = Vec_IntAlloc( 2*Aig_ManObjNum(p0) );
+ Aig_ManForEachObj( p0, pObj0, i )
+ {
+ if ( Aig_ObjIsPo(pObj0) )
+ continue;
+ pObj1 = (Aig_Obj_t *)pObj0->pData;
+ Vec_IntPush( vPairsNew, pObj0->Id );
+ Vec_IntPush( vPairsNew, pObj1->Id );
+ }
+ return vPairsNew;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Transfers the result of matching to miter.]
+
+ Description [The array of pairs should be complete.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Ssw_MatchingMiter( Aig_Man_t * pMiter, Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairsAll )
+{
+ Vec_Int_t * vPairsMiter;
+ Aig_Obj_t * pObj0, * pObj1;
+ int i;
+ // create matching of nodes in the miter
+ vPairsMiter = Vec_IntAlloc( 2*Aig_ManObjNum(p0) );
+ for ( i = 0; i < Vec_IntSize(vPairsAll); i += 2 )
+ {
+ pObj0 = Aig_ManObj( p0, Vec_IntEntry(vPairsAll, i) );
+ pObj1 = Aig_ManObj( p1, Vec_IntEntry(vPairsAll, i+1) );
+ assert( pObj0->pData != NULL );
+ assert( pObj1->pData != NULL );
+ if ( pObj0->pData == pObj1->pData )
+ continue;
+ if ( Aig_ObjIsNone((Aig_Obj_t *)pObj0->pData) || Aig_ObjIsNone((Aig_Obj_t *)pObj1->pData) )
+ continue;
+ // get the miter nodes
+ pObj0 = (Aig_Obj_t *)pObj0->pData;
+ pObj1 = (Aig_Obj_t *)pObj1->pData;
+ assert( !Aig_IsComplement(pObj0) );
+ assert( !Aig_IsComplement(pObj1) );
+ assert( Aig_ObjType(pObj0) == Aig_ObjType(pObj1) );
+ if ( Aig_ObjIsPo(pObj0) )
+ continue;
+ assert( Aig_ObjIsNode(pObj0) || Saig_ObjIsLo(pMiter, pObj0) );
+ assert( Aig_ObjIsNode(pObj1) || Saig_ObjIsLo(pMiter, pObj1) );
+ assert( pObj0->Id < pObj1->Id );
+ Vec_IntPush( vPairsMiter, pObj0->Id );
+ Vec_IntPush( vPairsMiter, pObj1->Id );
+ }
+ return vPairsMiter;
+}
+
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Solves SEC using structural similarity.]
+
+ Description [Modifies both p0 and p1 by adding extra logic.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Ssw_SecWithSimilaritySweep( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs, Ssw_Pars_t * pPars )
+{
+ Ssw_Man_t * p;
+ Vec_Int_t * vPairsAll, * vPairsMiter;
+ Aig_Man_t * pMiter, * pAigNew;
+ // derive full matching
+ Ssw_MatchingStart( p0, p1, vPairs );
+ if ( pPars->nIsleDist )
+ Ssw_MatchingExtend( p0, p1, pPars->nIsleDist, pPars->fVerbose );
+ Ssw_MatchingComplete( p0, p1 );
+ Ssw_MatchingComplete( p1, p0 );
+ vPairsAll = Ssw_MatchingPairs( p0, p1 );
+ // create miter and transfer matching
+ pMiter = Saig_ManCreateMiter( p0, p1, 0 );
+ vPairsMiter = Ssw_MatchingMiter( pMiter, p0, p1, vPairsAll );
+ Vec_IntFree( vPairsAll );
+ // start the induction manager
+ p = Ssw_ManCreate( pMiter, pPars );
+ // create equivalence classes using these IDs
+ if ( p->pPars->fPartSigCorr )
+ p->ppClasses = Ssw_ClassesPreparePairsSimple( pMiter, vPairsMiter );
+ else
+ p->ppClasses = Ssw_ClassesPrepare( pMiter, pPars->nFramesK, pPars->fLatchCorr, pPars->fConstCorr, pPars->fOutputCorr, pPars->nMaxLevs, pPars->fVerbose );
+ if ( p->pPars->fDumpSRInit )
+ {
+ if ( p->pPars->fPartSigCorr )
+ {
+ Aig_Man_t * pSRed = Ssw_SpeculativeReduction( p );
+ Aig_ManDumpBlif( pSRed, "srm_part.blif", NULL, NULL );
+ Aig_ManStop( pSRed );
+ printf( "Speculatively reduced miter is saved in file \"%s\".\n", "srm_part.blif" );
+ }
+ else
+ printf( "Dumping speculative miter is possible only for partial signal correspondence (switch \"-c\").\n" );
+ }
+ p->pSml = Ssw_SmlStart( pMiter, 0, 1 + p->pPars->nFramesAddSim, 1 );
+ Ssw_ClassesSetData( p->ppClasses, p->pSml, (unsigned(*)(void *,Aig_Obj_t *))Ssw_SmlObjHashWord, (int(*)(void *,Aig_Obj_t *))Ssw_SmlObjIsConstWord, (int(*)(void *,Aig_Obj_t *,Aig_Obj_t *))Ssw_SmlObjsAreEqualWord );
+ // perform refinement of classes
+ pAigNew = Ssw_SignalCorrespondenceRefine( p );
+ // cleanup
+ Ssw_ManStop( p );
+ Aig_ManStop( pMiter );
+ Vec_IntFree( vPairsMiter );
+ return pAigNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Solves SEC with structural similarity.]
+
+ Description [The first two arguments are pointers to the AIG managers.
+ The third argument is the array of pairs of IDs of structurally equivalent
+ nodes from the first and second managers, respectively.]
+
+ SideEffects [The managers will be updated by adding "islands of difference".]
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_SecWithSimilarityPairs( Aig_Man_t * p0, Aig_Man_t * p1, Vec_Int_t * vPairs, Ssw_Pars_t * pPars )
+{
+ Ssw_Pars_t Pars;
+ Aig_Man_t * pAigRes;
+ int RetValue, clk = clock();
+ // derive parameters if not given
+ if ( pPars == NULL )
+ Ssw_ManSetDefaultParams( pPars = &Pars );
+ // reduce the AIG with pairs
+ pAigRes = Ssw_SecWithSimilaritySweep( p0, p1, vPairs, pPars );
+ // report the result of verification
+ RetValue = Ssw_MiterStatus( pAigRes, 1 );
+ if ( RetValue == 1 )
+ printf( "Verification successful. " );
+ else if ( RetValue == 0 )
+ printf( "Verification failed with a counter-example. " );
+ else
+ printf( "Verification UNDECIDED. The number of remaining regs = %d (total = %d). ",
+ Aig_ManRegNum(pAigRes), Aig_ManRegNum(p0)+Aig_ManRegNum(p1) );
+ ABC_PRT( "Time", clock() - clk );
+ Aig_ManStop( pAigRes );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Dummy procedure to detect structural similarity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Saig_StrSimPerformMatching_hack( Aig_Man_t * p0, Aig_Man_t * p1 )
+{
+ Vec_Int_t * vPairs;
+ Aig_Obj_t * pObj;
+ int i;
+ // create array of pairs
+ vPairs = Vec_IntAlloc( 100 );
+ Aig_ManForEachObj( p0, pObj, i )
+ {
+ if ( !Aig_ObjIsConst1(pObj) && !Aig_ObjIsPi(pObj) && !Aig_ObjIsNode(pObj) )
+ continue;
+ Vec_IntPush( vPairs, i );
+ Vec_IntPush( vPairs, i );
+ }
+ return vPairs;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Solves SEC with structural similarity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_SecWithSimilarity( Aig_Man_t * p0, Aig_Man_t * p1, Ssw_Pars_t * pPars )
+{
+ Vec_Int_t * vPairs;
+ Aig_Man_t * pPart0, * pPart1;
+ int RetValue;
+ if ( pPars->fVerbose )
+ printf( "Performing sequential verification using structural similarity.\n" );
+ // consider the case when a miter is given
+ if ( p1 == NULL )
+ {
+ if ( pPars->fVerbose )
+ {
+ Aig_ManPrintStats( p0 );
+ }
+ // demiter the miter
+ if ( !Saig_ManDemiterSimpleDiff( p0, &pPart0, &pPart1 ) )
+ {
+ printf( "Demitering has failed.\n" );
+ return -1;
+ }
+ }
+ else
+ {
+ pPart0 = Aig_ManDupSimple( p0 );
+ pPart1 = Aig_ManDupSimple( p1 );
+ }
+ if ( pPars->fVerbose )
+ {
+// Aig_ManPrintStats( pPart0 );
+// Aig_ManPrintStats( pPart1 );
+ if ( p1 == NULL )
+ {
+// Aig_ManDumpBlif( pPart0, "part0.blif", NULL, NULL );
+// Aig_ManDumpBlif( pPart1, "part1.blif", NULL, NULL );
+// printf( "The result of demitering is written into files \"%s\" and \"%s\".\n", "part0.blif", "part1.blif" );
+ }
+ }
+ assert( Aig_ManRegNum(pPart0) > 0 );
+ assert( Aig_ManRegNum(pPart1) > 0 );
+ assert( Saig_ManPiNum(pPart0) == Saig_ManPiNum(pPart1) );
+ assert( Saig_ManPoNum(pPart0) == Saig_ManPoNum(pPart1) );
+ // derive pairs
+// vPairs = Saig_StrSimPerformMatching_hack( pPart0, pPart1 );
+ vPairs = Saig_StrSimPerformMatching( pPart0, pPart1, 0, pPars->fVerbose, NULL );
+ RetValue = Ssw_SecWithSimilarityPairs( pPart0, pPart1, vPairs, pPars );
+ Aig_ManStop( pPart0 );
+ Aig_ManStop( pPart1 );
+ Vec_IntFree( vPairs );
+ return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/ssw/sswLcorr.c b/src/proof/ssw/sswLcorr.c
new file mode 100644
index 00000000..ce9c2563
--- /dev/null
+++ b/src/proof/ssw/sswLcorr.c
@@ -0,0 +1,336 @@
+/**CFile****************************************************************
+
+ FileName [sswLcorr.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Inductive prover with constraints.]
+
+ Synopsis [Latch correspondence.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 1, 2008.]
+
+ Revision [$Id: sswLcorr.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+//#include "bar.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Tranfers simulation information from FRAIG to AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ManSweepTransfer( Ssw_Man_t * p )
+{
+ Aig_Obj_t * pObj, * pObjFraig;
+ unsigned * pInfo;
+ int i;
+ // transfer simulation information
+ Aig_ManForEachPi( p->pAig, pObj, i )
+ {
+ pObjFraig = Ssw_ObjFrame( p, pObj, 0 );
+ if ( pObjFraig == Aig_ManConst0(p->pFrames) )
+ {
+ Ssw_SmlObjAssignConst( p->pSml, pObj, 0, 0 );
+ continue;
+ }
+ assert( !Aig_IsComplement(pObjFraig) );
+ assert( Aig_ObjIsPi(pObjFraig) );
+ pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjPioNum(pObjFraig) );
+ Ssw_SmlObjSetWord( p->pSml, pObj, pInfo[0], 0, 0 );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs one round of simulation with counter-examples.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ManSweepResimulate( Ssw_Man_t * p )
+{
+ int RetValue1, RetValue2, clk = clock();
+ // transfer PI simulation information from storage
+ Ssw_ManSweepTransfer( p );
+ // simulate internal nodes
+ Ssw_SmlSimulateOneFrame( p->pSml );
+ // check equivalence classes
+ RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 1 );
+ RetValue2 = Ssw_ClassesRefine( p->ppClasses, 1 );
+ // prepare simulation info for the next round
+ Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 );
+ p->nPatterns = 0;
+ p->nSimRounds++;
+p->timeSimSat += clock() - clk;
+ return RetValue1 > 0 || RetValue2 > 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Saves one counter-example into internal storage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlAddPattern( Ssw_Man_t * p, Aig_Obj_t * pRepr, Aig_Obj_t * pCand )
+{
+ Aig_Obj_t * pObj;
+ unsigned * pInfo;
+ int i, nVarNum, Value;
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->pMSat->vUsedPis, pObj, i )
+ {
+ nVarNum = Ssw_ObjSatNum( p->pMSat, pObj );
+ assert( nVarNum > 0 );
+ Value = sat_solver_var_value( p->pMSat->pSat, nVarNum );
+ if ( Value == 0 )
+ continue;
+ pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjPioNum(pObj) );
+ Abc_InfoSetBit( pInfo, p->nPatterns );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Builds fraiged logic cone of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ManBuildCone_rec( Ssw_Man_t * p, Aig_Obj_t * pObj )
+{
+ Aig_Obj_t * pObjNew;
+ assert( !Aig_IsComplement(pObj) );
+ if ( Ssw_ObjFrame( p, pObj, 0 ) )
+ return;
+ assert( Aig_ObjIsNode(pObj) );
+ Ssw_ManBuildCone_rec( p, Aig_ObjFanin0(pObj) );
+ Ssw_ManBuildCone_rec( p, Aig_ObjFanin1(pObj) );
+ pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, 0), Ssw_ObjChild1Fra(p, pObj, 0) );
+ Ssw_ObjSetFrame( p, pObj, 0, pObjNew );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Recycles the SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ManSweepLatchOne( Ssw_Man_t * p, Aig_Obj_t * pObjRepr, Aig_Obj_t * pObj )
+{
+ Aig_Obj_t * pObjFraig, * pObjReprFraig, * pObjLi;
+ int RetValue, clk;
+ assert( Aig_ObjIsPi(pObj) );
+ assert( Aig_ObjIsPi(pObjRepr) || Aig_ObjIsConst1(pObjRepr) );
+ // check if it makes sense to skip some calls
+ if ( p->nCallsCount > 100 && p->nCallsUnsat < p->nCallsSat )
+ {
+ if ( ++p->nCallsDelta < 0 )
+ return;
+ }
+ p->nCallsDelta = 0;
+clk = clock();
+ // get the fraiged node
+ pObjLi = Saig_ObjLoToLi( p->pAig, pObj );
+ Ssw_ManBuildCone_rec( p, Aig_ObjFanin0(pObjLi) );
+ pObjFraig = Ssw_ObjChild0Fra( p, pObjLi, 0 );
+ // get the fraiged representative
+ if ( Aig_ObjIsPi(pObjRepr) )
+ {
+ pObjLi = Saig_ObjLoToLi( p->pAig, pObjRepr );
+ Ssw_ManBuildCone_rec( p, Aig_ObjFanin0(pObjLi) );
+ pObjReprFraig = Ssw_ObjChild0Fra( p, pObjLi, 0 );
+ }
+ else
+ pObjReprFraig = Ssw_ObjFrame( p, pObjRepr, 0 );
+p->timeReduce += clock() - clk;
+ // if the fraiged nodes are the same, return
+ if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) )
+ return;
+ p->nRecycleCalls++;
+ p->nCallsCount++;
+
+ // check equivalence of the two nodes
+ if ( (pObj->fPhase == pObjRepr->fPhase) != (Aig_ObjPhaseReal(pObjFraig) == Aig_ObjPhaseReal(pObjReprFraig)) )
+ {
+ p->nPatterns++;
+ p->nStrangers++;
+ p->fRefined = 1;
+ }
+ else
+ {
+ RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) );
+ if ( RetValue == 1 ) // proved equivalence
+ {
+ p->nCallsUnsat++;
+ return;
+ }
+ if ( RetValue == -1 ) // timed out
+ {
+ Ssw_ClassesRemoveNode( p->ppClasses, pObj );
+ p->nCallsUnsat++;
+ p->fRefined = 1;
+ return;
+ }
+ else // disproved equivalence
+ {
+ Ssw_SmlAddPattern( p, pObjRepr, pObj );
+ p->nPatterns++;
+ p->nCallsSat++;
+ p->fRefined = 1;
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs one iteration of sweeping latches.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ManSweepLatch( Ssw_Man_t * p )
+{
+// Bar_Progress_t * pProgress = NULL;
+ Vec_Ptr_t * vClass;
+ Aig_Obj_t * pObj, * pRepr, * pTemp;
+ int i, k;
+
+ // start the timeframe
+ p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) );
+ // map constants and PIs
+ Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), 0, Aig_ManConst1(p->pFrames) );
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ Ssw_ObjSetFrame( p, pObj, 0, Aig_ObjCreatePi(p->pFrames) );
+
+ // implement equivalence classes
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ {
+ pRepr = Aig_ObjRepr( p->pAig, pObj );
+ if ( pRepr == NULL )
+ {
+ pTemp = Aig_ObjCreatePi(p->pFrames);
+ pTemp->pData = pObj;
+ }
+ else
+ pTemp = Aig_NotCond( Ssw_ObjFrame(p, pRepr, 0), pRepr->fPhase ^ pObj->fPhase );
+ Ssw_ObjSetFrame( p, pObj, 0, pTemp );
+ }
+ Aig_ManSetPioNumbers( p->pFrames );
+
+ // prepare simulation info
+ assert( p->vSimInfo == NULL );
+ p->vSimInfo = Vec_PtrAllocSimInfo( Aig_ManPiNum(p->pFrames), 1 );
+ Vec_PtrCleanSimInfo( p->vSimInfo, 0, 1 );
+
+ // go through the registers
+// if ( p->pPars->fVerbose )
+// pProgress = Bar_ProgressStart( stdout, Aig_ManRegNum(p->pAig) );
+ vClass = Vec_PtrAlloc( 100 );
+ p->fRefined = 0;
+ p->nCallsCount = p->nCallsSat = p->nCallsUnsat = 0;
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ {
+// if ( p->pPars->fVerbose )
+// Bar_ProgressUpdate( pProgress, i, NULL );
+ // consider the case of constant candidate
+ if ( Ssw_ObjIsConst1Cand( p->pAig, pObj ) )
+ Ssw_ManSweepLatchOne( p, Aig_ManConst1(p->pAig), pObj );
+ else
+ {
+ // consider the case of equivalence class
+ Ssw_ClassesCollectClass( p->ppClasses, pObj, vClass );
+ if ( Vec_PtrSize(vClass) == 0 )
+ continue;
+ // try to prove equivalences in this class
+ Vec_PtrForEachEntry( Aig_Obj_t *, vClass, pTemp, k )
+ if ( Aig_ObjRepr(p->pAig, pTemp) == pObj )
+ {
+ Ssw_ManSweepLatchOne( p, pObj, pTemp );
+ if ( p->nPatterns == 32 )
+ break;
+ }
+ }
+ // resimulate
+ if ( p->nPatterns == 32 )
+ Ssw_ManSweepResimulate( p );
+ // attempt recycling the SAT solver
+ if ( p->pPars->nSatVarMax &&
+ p->pMSat->nSatVars > p->pPars->nSatVarMax &&
+ p->nRecycleCalls > p->pPars->nRecycleCalls )
+ {
+ p->nVarsMax = Abc_MaxInt( p->nVarsMax, p->pMSat->nSatVars );
+ p->nCallsMax = Abc_MaxInt( p->nCallsMax, p->pMSat->nSolverCalls );
+ Ssw_SatStop( p->pMSat );
+ p->pMSat = Ssw_SatStart( 0 );
+ p->nRecycles++;
+ p->nRecycleCalls = 0;
+ }
+ }
+// ABC_PRT( "reduce", p->timeReduce );
+// Aig_TableProfile( p->pFrames );
+// printf( "And gates = %d\n", Aig_ManNodeNum(p->pFrames) );
+ // resimulate
+ if ( p->nPatterns > 0 )
+ Ssw_ManSweepResimulate( p );
+ // cleanup
+ Vec_PtrFree( vClass );
+// if ( p->pPars->fVerbose )
+// Bar_ProgressStop( pProgress );
+
+ // cleanup
+// Ssw_ClassesCheck( p->ppClasses );
+ return p->fRefined;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/ssw/sswMan.c b/src/proof/ssw/sswMan.c
new file mode 100644
index 00000000..c635569d
--- /dev/null
+++ b/src/proof/ssw/sswMan.c
@@ -0,0 +1,218 @@
+/**CFile****************************************************************
+
+ FileName [sswMan.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Inductive prover with constraints.]
+
+ Synopsis [Calls to the SAT solver.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 1, 2008.]
+
+ Revision [$Id: sswMan.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Creates the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ssw_Man_t * Ssw_ManCreate( Aig_Man_t * pAig, Ssw_Pars_t * pPars )
+{
+ Ssw_Man_t * p;
+ // prepare the sequential AIG
+ assert( Saig_ManRegNum(pAig) > 0 );
+ Aig_ManFanoutStart( pAig );
+ Aig_ManSetPioNumbers( pAig );
+ // create interpolation manager
+ p = ABC_ALLOC( Ssw_Man_t, 1 );
+ memset( p, 0, sizeof(Ssw_Man_t) );
+ p->pPars = pPars;
+ p->pAig = pAig;
+ p->nFrames = pPars->nFramesK + 1;
+ p->pNodeToFrames = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) * p->nFrames );
+ p->vCommon = Vec_PtrAlloc( 100 );
+ p->iOutputLit = -1;
+ // allocate storage for sim pattern
+ p->nPatWords = Abc_BitWordNum( Saig_ManPiNum(pAig) * p->nFrames + Saig_ManRegNum(pAig) );
+ p->pPatWords = ABC_CALLOC( unsigned, p->nPatWords );
+ // other
+ p->vNewLos = Vec_PtrAlloc( 100 );
+ p->vNewPos = Vec_IntAlloc( 100 );
+ p->vResimConsts = Vec_PtrAlloc( 100 );
+ p->vResimClasses = Vec_PtrAlloc( 100 );
+// p->pPars->fVerbose = 1;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints stats of the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ManCountEquivs( Ssw_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i, nEquivs = 0;
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ nEquivs += ( Aig_ObjRepr(p->pAig, pObj) != NULL );
+ return nEquivs;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints stats of the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ManPrintStats( Ssw_Man_t * p )
+{
+ double nMemory = 1.0*Aig_ManObjNumMax(p->pAig)*p->nFrames*(2*sizeof(int)+2*sizeof(void*))/(1<<20);
+
+ printf( "Parameters: F = %d. AddF = %d. C-lim = %d. Constr = %d. MaxLev = %d. Mem = %0.2f Mb.\n",
+ p->pPars->nFramesK, p->pPars->nFramesAddSim, p->pPars->nBTLimit, Saig_ManConstrNum(p->pAig), p->pPars->nMaxLevs, nMemory );
+ printf( "AIG : PI = %d. PO = %d. Latch = %d. Node = %d. Ave SAT vars = %d.\n",
+ Saig_ManPiNum(p->pAig), Saig_ManPoNum(p->pAig), Saig_ManRegNum(p->pAig), Aig_ManNodeNum(p->pAig),
+ 0/(p->pPars->nIters+1) );
+ printf( "SAT calls : Proof = %d. Cex = %d. Fail = %d. Lits proved = %d.\n",
+ p->nSatProof, p->nSatCallsSat, p->nSatFailsReal, Ssw_ManCountEquivs(p) );
+ printf( "SAT solver: Vars max = %d. Calls max = %d. Recycles = %d. Sim rounds = %d.\n",
+ p->nVarsMax, p->nCallsMax, p->nRecyclesTotal, p->nSimRounds );
+ printf( "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n",
+ p->nNodesBeg, p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/(p->nNodesBeg?p->nNodesBeg:1),
+ p->nRegsBeg, p->nRegsEnd, 100.0*(p->nRegsBeg-p->nRegsEnd)/(p->nRegsBeg?p->nRegsBeg:1) );
+
+ p->timeOther = p->timeTotal-p->timeBmc-p->timeReduce-p->timeMarkCones-p->timeSimSat-p->timeSat;
+ ABC_PRTP( "BMC ", p->timeBmc, p->timeTotal );
+ ABC_PRTP( "Spec reduce", p->timeReduce, p->timeTotal );
+ ABC_PRTP( "Mark cones ", p->timeMarkCones, p->timeTotal );
+ ABC_PRTP( "Sim SAT ", p->timeSimSat, p->timeTotal );
+ ABC_PRTP( "SAT solving", p->timeSat, p->timeTotal );
+ ABC_PRTP( " unsat ", p->timeSatUnsat, p->timeTotal );
+ ABC_PRTP( " sat ", p->timeSatSat, p->timeTotal );
+ ABC_PRTP( " undecided", p->timeSatUndec, p->timeTotal );
+ ABC_PRTP( "Other ", p->timeOther, p->timeTotal );
+ ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal );
+
+ // report the reductions
+ if ( p->pAig->nConstrs )
+ {
+ printf( "Statistics reflecting the use of constraints:\n" );
+ printf( "Total cones = %6d. Constraint cones = %6d. (%6.2f %%)\n",
+ p->nConesTotal, p->nConesConstr, 100.0*p->nConesConstr/p->nConesTotal );
+ printf( "Total equivs = %6d. Removed equivs = %6d. (%6.2f %%)\n",
+ p->nEquivsTotal, p->nEquivsConstr, 100.0*p->nEquivsConstr/p->nEquivsTotal );
+ printf( "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n",
+ p->nNodesBegC, p->nNodesEndC, 100.0*(p->nNodesBegC-p->nNodesEndC)/(p->nNodesBegC?p->nNodesBegC:1),
+ p->nRegsBegC, p->nRegsEndC, 100.0*(p->nRegsBegC-p->nRegsEndC)/(p->nRegsBegC?p->nRegsBegC:1) );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ManCleanup( Ssw_Man_t * p )
+{
+// Aig_ManCleanMarkAB( p->pAig );
+ assert( p->pMSat == NULL );
+ if ( p->pFrames )
+ {
+ Aig_ManCleanMarkAB( p->pFrames );
+ Aig_ManStop( p->pFrames );
+ p->pFrames = NULL;
+ memset( p->pNodeToFrames, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p->pAig) * p->nFrames );
+ }
+ if ( p->vSimInfo )
+ {
+ Vec_PtrFree( p->vSimInfo );
+ p->vSimInfo = NULL;
+ }
+ p->nConstrTotal = 0;
+ p->nConstrReduced = 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Frees the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ManStop( Ssw_Man_t * p )
+{
+ ABC_FREE( p->pVisited );
+ if ( p->pPars->fVerbose )//&& p->pPars->nStepsMax == -1 )
+ Ssw_ManPrintStats( p );
+ if ( p->ppClasses )
+ Ssw_ClassesStop( p->ppClasses );
+ if ( p->pSml )
+ Ssw_SmlStop( p->pSml );
+ if ( p->vDiffPairs )
+ Vec_IntFree( p->vDiffPairs );
+ if ( p->vInits )
+ Vec_IntFree( p->vInits );
+ Vec_PtrFree( p->vResimConsts );
+ Vec_PtrFree( p->vResimClasses );
+ Vec_PtrFree( p->vNewLos );
+ Vec_IntFree( p->vNewPos );
+ Vec_PtrFree( p->vCommon );
+ ABC_FREE( p->pNodeToFrames );
+ ABC_FREE( p->pPatWords );
+ ABC_FREE( p );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/ssw/sswPairs.c b/src/proof/ssw/sswPairs.c
new file mode 100644
index 00000000..0aba942f
--- /dev/null
+++ b/src/proof/ssw/sswPairs.c
@@ -0,0 +1,477 @@
+/**CFile****************************************************************
+
+ FileName [sswPairs.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Inductive prover with constraints.]
+
+ Synopsis [Calls to the SAT solver.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 1, 2008.]
+
+ Revision [$Id: sswPairs.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Reports the status of the miter.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_MiterStatus( Aig_Man_t * p, int fVerbose )
+{
+ Aig_Obj_t * pObj, * pChild;
+ int i, CountConst0 = 0, CountNonConst0 = 0, CountUndecided = 0;
+// if ( p->pData )
+// return 0;
+ Saig_ManForEachPo( 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 ( p->nRegs == 0 && Aig_ObjIsPi(Aig_Regular(pChild)) )
+ {
+ CountNonConst0++;
+ continue;
+ }
+ // check if the output can be not constant 0
+ if ( Aig_Regular(pChild)->fPhase != (unsigned)Aig_IsComplement(pChild) )
+ {
+ CountNonConst0++;
+ continue;
+ }
+ CountUndecided++;
+ }
+
+ if ( fVerbose )
+ {
+ printf( "Miter has %d outputs. ", Saig_ManPoNum(p) );
+ 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 [Transfer equivalent pairs to the miter.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Ssw_TransferSignalPairs( Aig_Man_t * pMiter, Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vIds1, Vec_Int_t * vIds2 )
+{
+ Vec_Int_t * vIds;
+ Aig_Obj_t * pObj1, * pObj2;
+ Aig_Obj_t * pObj1m, * pObj2m;
+ int i;
+ vIds = Vec_IntAlloc( 2 * Vec_IntSize(vIds1) );
+ for ( i = 0; i < Vec_IntSize(vIds1); i++ )
+ {
+ pObj1 = Aig_ManObj( pAig1, Vec_IntEntry(vIds1, i) );
+ pObj2 = Aig_ManObj( pAig2, Vec_IntEntry(vIds2, i) );
+ pObj1m = Aig_Regular((Aig_Obj_t *)pObj1->pData);
+ pObj2m = Aig_Regular((Aig_Obj_t *)pObj2->pData);
+ assert( pObj1m && pObj2m );
+ if ( pObj1m == pObj2m )
+ continue;
+ if ( pObj1m->Id < pObj2m->Id )
+ {
+ Vec_IntPush( vIds, pObj1m->Id );
+ Vec_IntPush( vIds, pObj2m->Id );
+ }
+ else
+ {
+ Vec_IntPush( vIds, pObj2m->Id );
+ Vec_IntPush( vIds, pObj1m->Id );
+ }
+ }
+ return vIds;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transform pairs into class representation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t ** Ssw_TransformPairsIntoTempClasses( Vec_Int_t * vPairs, int nObjNumMax )
+{
+ Vec_Int_t ** pvClasses; // vector of classes
+ int * pReprs; // mapping nodes into their representatives
+ int Entry, idObj, idRepr, idReprObj, idReprRepr, i;
+ // allocate data-structures
+ pvClasses = ABC_CALLOC( Vec_Int_t *, nObjNumMax );
+ pReprs = ABC_ALLOC( int, nObjNumMax );
+ for ( i = 0; i < nObjNumMax; i++ )
+ pReprs[i] = -1;
+ // consider pairs
+ for ( i = 0; i < Vec_IntSize(vPairs); i += 2 )
+ {
+ // get both objects
+ idRepr = Vec_IntEntry( vPairs, i );
+ idObj = Vec_IntEntry( vPairs, i+1 );
+ assert( idObj > 0 );
+ assert( (pReprs[idRepr] == -1) || (pvClasses[pReprs[idRepr]] != NULL) );
+ assert( (pReprs[idObj] == -1) || (pvClasses[pReprs[idObj] ] != NULL) );
+ // get representatives of both objects
+ idReprRepr = pReprs[idRepr];
+ idReprObj = pReprs[idObj];
+ // check different situations
+ if ( idReprRepr == -1 && idReprObj == -1 )
+ { // they do not have classes
+ // create a class
+ pvClasses[idRepr] = Vec_IntAlloc( 4 );
+ Vec_IntPush( pvClasses[idRepr], idRepr );
+ Vec_IntPush( pvClasses[idRepr], idObj );
+ pReprs[ idRepr ] = idRepr;
+ pReprs[ idObj ] = idRepr;
+ }
+ else if ( idReprRepr >= 0 && idReprObj == -1 )
+ { // representative has a class
+ // add iObj to the same class
+ Vec_IntPushUniqueOrder( pvClasses[idReprRepr], idObj );
+ pReprs[ idObj ] = idReprRepr;
+ }
+ else if ( idReprRepr == -1 && idReprObj >= 0 )
+ { // object has a class
+ assert( idReprObj != idRepr );
+ if ( idReprObj < idRepr )
+ { // add idRepr to the same class
+ Vec_IntPushUniqueOrder( pvClasses[idReprObj], idRepr );
+ pReprs[ idRepr ] = idReprObj;
+ }
+ else // if ( idReprObj > idRepr )
+ { // make idRepr new representative
+ Vec_IntPushFirst( pvClasses[idReprObj], idRepr );
+ pvClasses[idRepr] = pvClasses[idReprObj];
+ pvClasses[idReprObj] = NULL;
+ // set correct representatives of each node
+ Vec_IntForEachEntry( pvClasses[idRepr], Entry, i )
+ pReprs[ Entry ] = idRepr;
+ }
+ }
+ else // if ( idReprRepr >= 0 && idReprObj >= 0 )
+ { // both have classes
+ if ( idReprRepr == idReprObj )
+ { // the classes are the same
+ // nothing to do
+ }
+ else
+ { // the classes are different
+ // find the repr of the new class
+ if ( idReprRepr < idReprObj )
+ {
+ Vec_IntForEachEntry( pvClasses[idReprObj], Entry, i )
+ {
+ Vec_IntPushUniqueOrder( pvClasses[idReprRepr], Entry );
+ pReprs[ Entry ] = idReprRepr;
+ }
+ Vec_IntFree( pvClasses[idReprObj] );
+ pvClasses[idReprObj] = NULL;
+ }
+ else // if ( idReprRepr > idReprObj )
+ {
+ Vec_IntForEachEntry( pvClasses[idReprRepr], Entry, i )
+ {
+ Vec_IntPushUniqueOrder( pvClasses[idReprObj], Entry );
+ pReprs[ Entry ] = idReprObj;
+ }
+ Vec_IntFree( pvClasses[idReprRepr] );
+ pvClasses[idReprRepr] = NULL;
+ }
+ }
+ }
+ }
+ ABC_FREE( pReprs );
+ return pvClasses;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_FreeTempClasses( Vec_Int_t ** pvClasses, int nObjNumMax )
+{
+ int i;
+ for ( i = 0; i < nObjNumMax; i++ )
+ if ( pvClasses[i] )
+ Vec_IntFree( pvClasses[i] );
+ ABC_FREE( pvClasses );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs signal correspondence for the miter of two AIGs with node pairs defined.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Ssw_SignalCorrespondenceWithPairs( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vIds1, Vec_Int_t * vIds2, Ssw_Pars_t * pPars )
+{
+ Ssw_Man_t * p;
+ Aig_Man_t * pAigNew, * pMiter;
+ Ssw_Pars_t Pars;
+ Vec_Int_t * vPairs;
+ Vec_Int_t ** pvClasses;
+ assert( Vec_IntSize(vIds1) == Vec_IntSize(vIds2) );
+ // create sequential miter
+ pMiter = Saig_ManCreateMiter( pAig1, pAig2, 0 );
+ Aig_ManCleanup( pMiter );
+ // transfer information to the miter
+ vPairs = Ssw_TransferSignalPairs( pMiter, pAig1, pAig2, vIds1, vIds2 );
+ // create representation of the classes
+ pvClasses = Ssw_TransformPairsIntoTempClasses( vPairs, Aig_ManObjNumMax(pMiter) );
+ Vec_IntFree( vPairs );
+ // if parameters are not given, create them
+ if ( pPars == NULL )
+ Ssw_ManSetDefaultParams( pPars = &Pars );
+ // start the induction manager
+ p = Ssw_ManCreate( pMiter, pPars );
+ // create equivalence classes using these IDs
+ p->ppClasses = Ssw_ClassesPreparePairs( pMiter, pvClasses );
+ p->pSml = Ssw_SmlStart( pMiter, 0, p->nFrames + p->pPars->nFramesAddSim, 1 );
+ Ssw_ClassesSetData( p->ppClasses, p->pSml, (unsigned(*)(void *,Aig_Obj_t *))Ssw_SmlObjHashWord, (int(*)(void *,Aig_Obj_t *))Ssw_SmlObjIsConstWord, (int(*)(void *,Aig_Obj_t *,Aig_Obj_t *))Ssw_SmlObjsAreEqualWord );
+ // perform refinement of classes
+ pAigNew = Ssw_SignalCorrespondenceRefine( p );
+ // cleanup
+ Ssw_FreeTempClasses( pvClasses, Aig_ManObjNumMax(pMiter) );
+ Ssw_ManStop( p );
+ Aig_ManStop( pMiter );
+ return pAigNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Runs inductive SEC for the miter of two AIGs with node pairs defined.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Ssw_SignalCorrespondeceTestPairs( Aig_Man_t * pAig )
+{
+ Aig_Man_t * pAigNew, * pAigRes;
+ Ssw_Pars_t Pars, * pPars = &Pars;
+ Vec_Int_t * vIds1, * vIds2;
+ Aig_Obj_t * pObj, * pRepr;
+ int RetValue, i, clk = clock();
+ Ssw_ManSetDefaultParams( pPars );
+ pPars->fVerbose = 1;
+ pAigNew = Ssw_SignalCorrespondence( pAig, pPars );
+ // record pairs of equivalent nodes
+ vIds1 = Vec_IntAlloc( Aig_ManObjNumMax(pAig) );
+ vIds2 = Vec_IntAlloc( Aig_ManObjNumMax(pAig) );
+ Aig_ManForEachObj( pAig, pObj, i )
+ {
+ pRepr = Aig_Regular((Aig_Obj_t *)pObj->pData);
+ if ( pRepr == NULL )
+ continue;
+ if ( Aig_ManObj(pAigNew, pRepr->Id) == NULL )
+ continue;
+/*
+ if ( Aig_ObjIsNode(pObj) )
+ printf( "n " );
+ else if ( Saig_ObjIsPi(pAig, pObj) )
+ printf( "pi " );
+ else if ( Saig_ObjIsLo(pAig, pObj) )
+ printf( "lo " );
+*/
+ Vec_IntPush( vIds1, Aig_ObjId(pObj) );
+ Vec_IntPush( vIds2, Aig_ObjId(pRepr) );
+ }
+ printf( "Recorded %d pairs (before: %d after: %d).\n", Vec_IntSize(vIds1), Aig_ManObjNumMax(pAig), Aig_ManObjNumMax(pAigNew) );
+ // try the new AIGs
+ pAigRes = Ssw_SignalCorrespondenceWithPairs( pAig, pAigNew, vIds1, vIds2, pPars );
+ Vec_IntFree( vIds1 );
+ Vec_IntFree( vIds2 );
+ // report the results
+ RetValue = Ssw_MiterStatus( pAigRes, 1 );
+ if ( RetValue == 1 )
+ printf( "Verification successful. " );
+ else if ( RetValue == 0 )
+ printf( "Verification failed with the counter-example. " );
+ else
+ printf( "Verification UNDECIDED. Remaining registers %d (total %d). ",
+ Aig_ManRegNum(pAigRes), Aig_ManRegNum(pAig) + Aig_ManRegNum(pAigNew) );
+ ABC_PRT( "Time", clock() - clk );
+ // cleanup
+ Aig_ManStop( pAigNew );
+ return pAigRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Runs inductive SEC for the miter of two AIGs with node pairs defined.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_SecWithPairs( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vIds1, Vec_Int_t * vIds2, Ssw_Pars_t * pPars )
+{
+ Aig_Man_t * pAigRes;
+ int RetValue, clk = clock();
+ assert( vIds1 != NULL && vIds2 != NULL );
+ // try the new AIGs
+ printf( "Performing specialized verification with node pairs.\n" );
+ pAigRes = Ssw_SignalCorrespondenceWithPairs( pAig1, pAig2, vIds1, vIds2, pPars );
+ // report the results
+ RetValue = Ssw_MiterStatus( pAigRes, 1 );
+ if ( RetValue == 1 )
+ printf( "Verification successful. " );
+ else if ( RetValue == 0 )
+ printf( "Verification failed with a counter-example. " );
+ else
+ printf( "Verification UNDECIDED. The number of remaining regs = %d (total = %d). ",
+ Aig_ManRegNum(pAigRes), Aig_ManRegNum(pAig1) + Aig_ManRegNum(pAig2) );
+ ABC_PRT( "Time", clock() - clk );
+ // cleanup
+ Aig_ManStop( pAigRes );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Runs inductive SEC for the miter of two AIGs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_SecGeneral( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Ssw_Pars_t * pPars )
+{
+ Aig_Man_t * pAigRes, * pMiter;
+ int RetValue, clk = clock();
+ // try the new AIGs
+ printf( "Performing general verification without node pairs.\n" );
+ pMiter = Saig_ManCreateMiter( pAig1, pAig2, 0 );
+ Aig_ManCleanup( pMiter );
+ pAigRes = Ssw_SignalCorrespondence( pMiter, pPars );
+ Aig_ManStop( pMiter );
+ // report the results
+ RetValue = Ssw_MiterStatus( pAigRes, 1 );
+ if ( RetValue == 1 )
+ printf( "Verification successful. " );
+ else if ( RetValue == 0 )
+ printf( "Verification failed with a counter-example. " );
+ else
+ printf( "Verification UNDECIDED. The number of remaining regs = %d (total = %d). ",
+ Aig_ManRegNum(pAigRes), Aig_ManRegNum(pAig1) + Aig_ManRegNum(pAig2) );
+ ABC_PRT( "Time", clock() - clk );
+ // cleanup
+ Aig_ManStop( pAigRes );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Runs inductive SEC for the miter of two AIGs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_SecGeneralMiter( Aig_Man_t * pMiter, Ssw_Pars_t * pPars )
+{
+ Aig_Man_t * pAigRes;
+ int RetValue, clk = clock();
+ // try the new AIGs
+// printf( "Performing general verification without node pairs.\n" );
+ pAigRes = Ssw_SignalCorrespondence( pMiter, pPars );
+ // report the results
+ RetValue = Ssw_MiterStatus( pAigRes, 1 );
+ if ( RetValue == 1 )
+ printf( "Verification successful. " );
+ else if ( RetValue == 0 )
+ printf( "Verification failed with a counter-example. " );
+ else
+ printf( "Verification UNDECIDED. The number of remaining regs = %d (total = %d). ",
+ Aig_ManRegNum(pAigRes), Aig_ManRegNum(pMiter) );
+ ABC_PRT( "Time", clock() - clk );
+ // cleanup
+ Aig_ManStop( pAigRes );
+ return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/ssw/sswPart.c b/src/proof/ssw/sswPart.c
new file mode 100644
index 00000000..d2f07dc8
--- /dev/null
+++ b/src/proof/ssw/sswPart.c
@@ -0,0 +1,141 @@
+/**CFile****************************************************************
+
+ FileName [sswPart.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Inductive prover with constraints.]
+
+ Synopsis [Partitioned signal correspondence.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 1, 2008.]
+
+ Revision [$Id: sswPart.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+#include "src/aig/ioa/ioa.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs partitioned sequential SAT sweeping.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Aig_Man_t * Ssw_SignalCorrespondencePart( Aig_Man_t * pAig, Ssw_Pars_t * pPars )
+{
+ int fPrintParts = 0;
+ char Buffer[100];
+ Aig_Man_t * pTemp, * pNew;
+ Vec_Ptr_t * vResult;
+ Vec_Int_t * vPart;
+ int * pMapBack;
+ int i, nCountPis, nCountRegs;
+ int nClasses, nPartSize, fVerbose;
+ int clk = clock();
+ if ( pPars->fConstrs )
+ {
+ printf( "Cannot use partitioned computation with constraints.\n" );
+ return NULL;
+ }
+ // save parameters
+ nPartSize = pPars->nPartSize; pPars->nPartSize = 0;
+ fVerbose = pPars->fVerbose; pPars->fVerbose = 0;
+ // generate partitions
+ if ( pAig->vClockDoms )
+ {
+ // divide large clock domains into separate partitions
+ vResult = Vec_PtrAlloc( 100 );
+ Vec_PtrForEachEntry( Vec_Int_t *, (Vec_Ptr_t *)pAig->vClockDoms, vPart, i )
+ {
+ if ( nPartSize && Vec_IntSize(vPart) > nPartSize )
+ Aig_ManPartDivide( vResult, vPart, nPartSize, pPars->nOverSize );
+ else
+ Vec_PtrPush( vResult, Vec_IntDup(vPart) );
+ }
+ }
+ else
+ vResult = Aig_ManRegPartitionSimple( pAig, nPartSize, pPars->nOverSize );
+// vResult = Aig_ManPartitionSmartRegisters( pAig, nPartSize, 0 );
+// vResult = Aig_ManRegPartitionSmart( pAig, nPartSize );
+ if ( fPrintParts )
+ {
+ // print partitions
+ printf( "Simple partitioning. %d partitions are saved:\n", Vec_PtrSize(vResult) );
+ Vec_PtrForEachEntry( Vec_Int_t *, vResult, vPart, i )
+ {
+// extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact );
+ sprintf( Buffer, "part%03d.aig", i );
+ pTemp = Aig_ManRegCreatePart( pAig, vPart, &nCountPis, &nCountRegs, NULL );
+ Ioa_WriteAiger( pTemp, Buffer, 0, 0 );
+ printf( "part%03d.aig : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d.\n",
+ i, Vec_IntSize(vPart), Aig_ManPiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Aig_ManNodeNum(pTemp) );
+ Aig_ManStop( pTemp );
+ }
+ }
+
+ // perform SSW with partitions
+ Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) );
+ Vec_PtrForEachEntry( Vec_Int_t *, vResult, vPart, i )
+ {
+ pTemp = Aig_ManRegCreatePart( pAig, vPart, &nCountPis, &nCountRegs, &pMapBack );
+ Aig_ManSetRegNum( pTemp, pTemp->nRegs );
+ // create the projection of 1-hot registers
+ if ( pAig->vOnehots )
+ pTemp->vOnehots = Aig_ManRegProjectOnehots( pAig, pTemp, pAig->vOnehots, fVerbose );
+ // run SSW
+ if (nCountPis>0) {
+ pNew = Ssw_SignalCorrespondence( pTemp, pPars );
+ nClasses = Aig_TransferMappedClasses( pAig, pTemp, pMapBack );
+ if ( fVerbose )
+ printf( "%3d : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d. It = %3d. Cl = %5d.\n",
+ i, Vec_IntSize(vPart), Aig_ManPiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Aig_ManNodeNum(pTemp), pPars->nIters, nClasses );
+ Aig_ManStop( pNew );
+ }
+ Aig_ManStop( pTemp );
+ ABC_FREE( pMapBack );
+ }
+ // remap the AIG
+ pNew = Aig_ManDupRepr( pAig, 0 );
+ Aig_ManSeqCleanup( pNew );
+// Aig_ManPrintStats( pAig );
+// Aig_ManPrintStats( pNew );
+ Vec_VecFree( (Vec_Vec_t *)vResult );
+ pPars->nPartSize = nPartSize;
+ pPars->fVerbose = fVerbose;
+ if ( fVerbose )
+ {
+ ABC_PRT( "Total time", clock() - clk );
+ }
+ return pNew;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/ssw/sswRarity.c b/src/proof/ssw/sswRarity.c
new file mode 100644
index 00000000..264bb2c8
--- /dev/null
+++ b/src/proof/ssw/sswRarity.c
@@ -0,0 +1,1158 @@
+/**CFile****************************************************************
+
+ FileName [sswRarity.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Inductive prover with constraints.]
+
+ Synopsis [Rarity-driven refinement of equivalence classes.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 1, 2008.]
+
+ Revision [$Id: sswRarity.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+#include "src/aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Ssw_RarMan_t_ Ssw_RarMan_t;
+struct Ssw_RarMan_t_
+{
+ // parameters
+ int nWords; // the number of words to simulate
+ int nFrames; // the number of frames to simulate
+ int nBinSize; // the number of flops in one group
+ int fVerbose; // the verbosiness flag
+ int nGroups; // the number of flop groups
+ int nWordsReg; // the number of words in the registers
+ // internal data
+ Aig_Man_t * pAig; // AIG with equivalence classes
+ Ssw_Cla_t * ppClasses; // equivalence classes
+ Vec_Int_t * vInits; // initial state
+ // simulation data
+ word * pObjData; // simulation info for each obj
+ word * pPatData; // pattern data for each reg
+ // candidates to update
+ Vec_Ptr_t * vUpdConst; // constant 1 candidates
+ Vec_Ptr_t * vUpdClass; // class representatives
+ // rarity data
+ int * pRarity; // occur counts for patterns in groups
+ double * pPatCosts; // pattern costs
+ // best patterns
+ Vec_Int_t * vPatBests; // best patterns
+ int iFailPo; // failed primary output
+ int iFailPat; // failed pattern
+};
+
+
+static inline int Ssw_RarGetBinPat( Ssw_RarMan_t * p, int iBin, int iPat )
+{
+ assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->nBinSize );
+ assert( iPat >= 0 && iPat < (1 << p->nBinSize) );
+ return p->pRarity[iBin * (1 << p->nBinSize) + iPat];
+}
+static inline void Ssw_RarSetBinPat( Ssw_RarMan_t * p, int iBin, int iPat, int Value )
+{
+ assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->nBinSize );
+ assert( iPat >= 0 && iPat < (1 << p->nBinSize) );
+ p->pRarity[iBin * (1 << p->nBinSize) + iPat] = Value;
+}
+static inline void Ssw_RarAddToBinPat( Ssw_RarMan_t * p, int iBin, int iPat )
+{
+ assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->nBinSize );
+ assert( iPat >= 0 && iPat < (1 << p->nBinSize) );
+ p->pRarity[iBin * (1 << p->nBinSize) + iPat]++;
+}
+
+static inline int Ssw_RarBitWordNum( int nBits ) { return (nBits>>6) + ((nBits&63) > 0); }
+
+static inline word * Ssw_RarObjSim( Ssw_RarMan_t * p, int Id ) { assert( Id < Aig_ManObjNumMax(p->pAig) ); return p->pObjData + p->nWords * Id; }
+static inline word * Ssw_RarPatSim( Ssw_RarMan_t * p, int Id ) { assert( Id < 64 * p->nWords ); return p->pPatData + p->nWordsReg * Id; }
+
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Prepares random number generator.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_RarManPrepareRandom( int nRandSeed )
+{
+ int i;
+ Aig_ManRandom( 1 );
+ for ( i = 0; i < nRandSeed; i++ )
+ Aig_ManRandom( 0 );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Initializes random primary inputs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_RarManAssingRandomPis( Ssw_RarMan_t * p )
+{
+ word * pSim;
+ Aig_Obj_t * pObj;
+ int w, i;
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ {
+ pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) );
+ for ( w = 0; w < p->nWords; w++ )
+ pSim[w] = Aig_ManRandom64(0);
+// pSim[0] <<= 1;
+// pSim[0] = (pSim[0] << 2) | 2;
+ pSim[0] = (pSim[0] << 4) | ((i & 1) ? 0xA : 0xC);
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Derives the counter-example.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Cex_t * Ssw_RarDeriveCex( Ssw_RarMan_t * p, int iFrame, int iPo, int iPatFinal, int fVerbose )
+{
+ Abc_Cex_t * pCex;
+ Aig_Obj_t * pObj;
+ Vec_Int_t * vTrace;
+ word * pSim;
+ int i, r, f, iBit, iPatThis;
+ // compute the pattern sequence
+ iPatThis = iPatFinal;
+ vTrace = Vec_IntStartFull( iFrame / p->nFrames + 1 );
+ Vec_IntWriteEntry( vTrace, iFrame / p->nFrames, iPatThis );
+ for ( r = iFrame / p->nFrames - 1; r >= 0; r-- )
+ {
+ iPatThis = Vec_IntEntry( p->vPatBests, r * p->nWords + iPatThis / 64 );
+ Vec_IntWriteEntry( vTrace, r, iPatThis );
+ }
+ // create counter-example
+ pCex = Abc_CexAlloc( Aig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), iFrame+1 );
+ pCex->iFrame = iFrame;
+ pCex->iPo = iPo;
+ // insert the bits
+ iBit = Aig_ManRegNum(p->pAig);
+ for ( f = 0; f <= iFrame; f++ )
+ {
+ Ssw_RarManAssingRandomPis( p );
+ iPatThis = Vec_IntEntry( vTrace, f / p->nFrames );
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ {
+ pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) );
+ if ( Abc_InfoHasBit( (unsigned *)pSim, iPatThis ) )
+ Abc_InfoSetBit( pCex->pData, iBit );
+ iBit++;
+ }
+ }
+ Vec_IntFree( vTrace );
+ assert( iBit == pCex->nBits );
+ // verify the counter example
+ if ( !Saig_ManVerifyCex( p->pAig, pCex ) )
+ {
+ printf( "Ssw_RarDeriveCex(): Counter-example is invalid.\n" );
+// Abc_CexFree( pCex );
+// pCex = NULL;
+ }
+ else
+ {
+// printf( "Counter-example verification is successful.\n" );
+ if ( fVerbose )
+ printf( "Output %d was asserted in frame %d (use \"write_counter\" to dump a witness). \n", pCex->iPo, pCex->iFrame );
+ }
+ return pCex;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Transposing 32-bit matrix.]
+
+ Description [Borrowed from "Hacker's Delight", by Henry Warren.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void transpose32( unsigned A[32] )
+{
+ int j, k;
+ unsigned t, m = 0x0000FFFF;
+ for ( j = 16; j != 0; j = j >> 1, m = m ^ (m << j) )
+ {
+ for ( k = 0; k < 32; k = (k + j + 1) & ~j )
+ {
+ t = (A[k] ^ (A[k+j] >> j)) & m;
+ A[k] = A[k] ^ t;
+ A[k+j] = A[k+j] ^ (t << j);
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transposing 64-bit matrix.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void transpose64( word A[64] )
+{
+ int j, k;
+ word t, m = 0x00000000FFFFFFFF;
+ for ( j = 32; j != 0; j = j >> 1, m = m ^ (m << j) )
+ {
+ for ( k = 0; k < 64; k = (k + j + 1) & ~j )
+ {
+ t = (A[k] ^ (A[k+j] >> j)) & m;
+ A[k] = A[k] ^ t;
+ A[k+j] = A[k+j] ^ (t << j);
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transposing 64-bit matrix.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void transpose64Simple( word A[64], word B[64] )
+{
+ int i, k;
+ for ( i = 0; i < 64; i++ )
+ B[i] = 0;
+ for ( i = 0; i < 64; i++ )
+ for ( k = 0; k < 64; k++ )
+ if ( (A[i] >> k) & 1 )
+ B[k] |= ((word)1 << (63-i));
+}
+
+/**Function*************************************************************
+
+ Synopsis [Testing the transposing code.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void TransposeTest()
+{
+ word M[64], N[64];
+ int i, clk;
+ Aig_ManRandom64( 1 );
+// for ( i = 0; i < 64; i++ )
+// M[i] = Aig_ManRandom64( 0 );
+ for ( i = 0; i < 64; i++ )
+ M[i] = i? (word)0 : ~(word)0;
+// for ( i = 0; i < 64; i++ )
+// Extra_PrintBinary( stdout, (unsigned *)&M[i], 64 ), printf( "\n" );
+
+ clk = clock();
+ for ( i = 0; i < 100001; i++ )
+ transpose64Simple( M, N );
+ Abc_PrintTime( 1, "Time", clock() - clk );
+
+ clk = clock();
+ for ( i = 0; i < 100001; i++ )
+ transpose64( M );
+ Abc_PrintTime( 1, "Time", clock() - clk );
+
+ for ( i = 0; i < 64; i++ )
+ if ( M[i] != N[i] )
+ printf( "Mismatch\n" );
+/*
+ printf( "\n" );
+ for ( i = 0; i < 64; i++ )
+ Extra_PrintBinary( stdout, (unsigned *)&M[i], 64 ), printf( "\n" );
+ printf( "\n" );
+ for ( i = 0; i < 64; i++ )
+ Extra_PrintBinary( stdout, (unsigned *)&N[i], 64 ), printf( "\n" );
+*/
+}
+
+/**Function*************************************************************
+
+ Synopsis [Transposing pObjData[ nRegs x nWords ] -> pPatData[ nWords x nRegs ].]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_RarTranspose( Ssw_RarMan_t * p )
+{
+ Aig_Obj_t * pObj;
+ word M[64];
+ int w, r, i;
+ for ( w = 0; w < p->nWords; w++ )
+ for ( r = 0; r < p->nWordsReg; r++ )
+ {
+ // save input
+ for ( i = 0; i < 64; i++ )
+ {
+ if ( r*64 + 63-i < Aig_ManRegNum(p->pAig) )
+ {
+ pObj = Saig_ManLi( p->pAig, r*64 + 63-i );
+ M[i] = Ssw_RarObjSim( p, Aig_ObjId(pObj) )[w];
+ }
+ else
+ M[i] = 0;
+ }
+ // transpose
+ transpose64( M );
+ // save output
+ for ( i = 0; i < 64; i++ )
+ Ssw_RarPatSim( p, w*64 + 63-i )[r] = M[i];
+ }
+/*
+ Saig_ManForEachLi( p->pAig, pObj, i )
+ {
+ word * pBitData = Ssw_RarObjSim( p, Aig_ObjId(pObj) );
+ Extra_PrintBinary( stdout, (unsigned *)pBitData, 64*p->nWords ); printf( "\n" );
+ }
+ printf( "\n" );
+ for ( i = 0; i < p->nWords*64; i++ )
+ {
+ word * pBitData = Ssw_RarPatSim( p, i );
+ Extra_PrintBinary( stdout, (unsigned *)pBitData, Aig_ManRegNum(p->pAig) ); printf( "\n" );
+ }
+ printf( "\n" );
+*/
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Sets random inputs and specialied flop outputs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_RarManInitialize( Ssw_RarMan_t * p, Vec_Int_t * vInit )
+{
+ Aig_Obj_t * pObj, * pObjLi;
+ word * pSim, * pSimLi;
+ int w, i;
+ // constant
+ pObj = Aig_ManConst1( p->pAig );
+ pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) );
+ for ( w = 0; w < p->nWords; w++ )
+ pSim[w] = ~(word)0;
+ // primary inputs
+ Ssw_RarManAssingRandomPis( p );
+ // flop outputs
+ if ( vInit )
+ {
+ assert( Vec_IntSize(vInit) == Saig_ManRegNum(p->pAig) * p->nWords );
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ {
+ pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) );
+ for ( w = 0; w < p->nWords; w++ )
+ pSim[w] = Vec_IntEntry(vInit, w * Saig_ManRegNum(p->pAig) + i) ? ~(word)0 : (word)0;
+ }
+ }
+ else
+ {
+ Saig_ManForEachLiLo( p->pAig, pObjLi, pObj, i )
+ {
+ pSimLi = Ssw_RarObjSim( p, Aig_ObjId(pObjLi) );
+ pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) );
+ for ( w = 0; w < p->nWords; w++ )
+ pSim[w] = pSimLi[w];
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if simulation info is composed of all zeros.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_RarManObjIsConst( void * pMan, Aig_Obj_t * pObj )
+{
+ Ssw_RarMan_t * p = (Ssw_RarMan_t *)pMan;
+ word * pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) );
+ word Flip = pObj->fPhase ? ~0 : 0;
+ int w;
+ for ( w = 0; w < p->nWords; w++ )
+ if ( pSim[w] ^ Flip )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if simulation infos are equal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_RarManObjsAreEqual( void * pMan, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
+{
+ Ssw_RarMan_t * p = (Ssw_RarMan_t *)pMan;
+ word * pSim0 = Ssw_RarObjSim( p, pObj0->Id );
+ word * pSim1 = Ssw_RarObjSim( p, pObj1->Id );
+ word Flip = (pObj0->fPhase != pObj1->fPhase) ? ~0 : 0;
+ int w;
+ for ( w = 0; w < p->nWords; w++ )
+ if ( pSim0[w] ^ pSim1[w] ^ Flip )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes hash value of the node using its simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Ssw_RarManObjHashWord( void * pMan, Aig_Obj_t * pObj )
+{
+ Ssw_RarMan_t * p = (Ssw_RarMan_t *)pMan;
+ static int s_SPrimes[128] = {
+ 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459,
+ 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997,
+ 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543,
+ 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089,
+ 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671,
+ 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243,
+ 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871,
+ 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471,
+ 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073,
+ 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689,
+ 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309,
+ 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933,
+ 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
+ };
+ unsigned * pSims;
+ unsigned uHash;
+ int i;
+ uHash = 0;
+ pSims = (unsigned *)Ssw_RarObjSim( p, pObj->Id );
+ for ( i = 0; i < 2 * p->nWords; i++ )
+ uHash ^= pSims[i] * s_SPrimes[i & 0x7F];
+ return uHash;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if simulation info is composed of all zeros.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_RarManObjWhichOne( Ssw_RarMan_t * p, Aig_Obj_t * pObj )
+{
+ word * pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) );
+ word Flip = pObj->fPhase ? ~0 : 0;
+ int w, i;
+ for ( w = 0; w < p->nWords; w++ )
+ if ( pSim[w] ^ Flip )
+ {
+ for ( i = 0; i < 64; i++ )
+ if ( ((pSim[w] ^ Flip) >> i) & 1 )
+ break;
+ assert( i < 64 );
+ return w * 64 + i;
+ }
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Check if any of the POs becomes non-constant.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_RarManCheckNonConstOutputs( Ssw_RarMan_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ p->iFailPo = -1;
+ p->iFailPat = -1;
+ Saig_ManForEachPo( p->pAig, pObj, i )
+ {
+ if ( p->pAig->nConstrs && i >= Saig_ManPoNum(p->pAig) - p->pAig->nConstrs )
+ return 0;
+ if ( !Ssw_RarManObjIsConst(p, pObj) )
+ {
+ p->iFailPo = i;
+ p->iFailPat = Ssw_RarManObjWhichOne( p, pObj );
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs one round of simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_RarManSimulate( Ssw_RarMan_t * p, Vec_Int_t * vInit, int fUpdate, int fFirst )
+{
+ Aig_Obj_t * pObj, * pRepr;
+ word * pSim, * pSim0, * pSim1;
+ word Flip, Flip0, Flip1;
+ int w, i;
+ // initialize
+ Ssw_RarManInitialize( p, vInit );
+ Vec_PtrClear( p->vUpdConst );
+ Vec_PtrClear( p->vUpdClass );
+ Aig_ManIncrementTravId( p->pAig );
+ // check comb inputs
+ if ( fUpdate )
+ Aig_ManForEachPi( p->pAig, pObj, i )
+ {
+ pRepr = Aig_ObjRepr(p->pAig, pObj);
+ if ( pRepr == NULL || Aig_ObjIsTravIdCurrent( p->pAig, pRepr ) )
+ continue;
+ if ( Ssw_RarManObjsAreEqual( p, pObj, pRepr ) )
+ continue;
+ // save for update
+ if ( pRepr == Aig_ManConst1(p->pAig) )
+ Vec_PtrPush( p->vUpdConst, pObj );
+ else
+ {
+ Vec_PtrPush( p->vUpdClass, pRepr );
+ Aig_ObjSetTravIdCurrent( p->pAig, pRepr );
+ }
+ }
+ // simulate
+ Aig_ManForEachNode( p->pAig, pObj, i )
+ {
+ pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) );
+ pSim0 = Ssw_RarObjSim( p, Aig_ObjFaninId0(pObj) );
+ pSim1 = Ssw_RarObjSim( p, Aig_ObjFaninId1(pObj) );
+ Flip0 = Aig_ObjFaninC0(pObj) ? ~0 : 0;
+ Flip1 = Aig_ObjFaninC1(pObj) ? ~0 : 0;
+ for ( w = 0; w < p->nWords; w++ )
+ pSim[w] = (Flip0 ^ pSim0[w]) & (Flip1 ^ pSim1[w]);
+ if ( !fUpdate )
+ continue;
+ // check classes
+ pRepr = Aig_ObjRepr(p->pAig, pObj);
+ if ( pRepr == NULL || Aig_ObjIsTravIdCurrent( p->pAig, pRepr ) )
+ continue;
+ if ( Ssw_RarManObjsAreEqual( p, pObj, pRepr ) )
+ continue;
+ // save for update
+ if ( pRepr == Aig_ManConst1(p->pAig) )
+ Vec_PtrPush( p->vUpdConst, pObj );
+ else
+ {
+ Vec_PtrPush( p->vUpdClass, pRepr );
+ Aig_ObjSetTravIdCurrent( p->pAig, pRepr );
+ }
+ }
+ // transfer to POs
+ Aig_ManForEachPo( p->pAig, pObj, i )
+ {
+ pSim = Ssw_RarObjSim( p, Aig_ObjId(pObj) );
+ pSim0 = Ssw_RarObjSim( p, Aig_ObjFaninId0(pObj) );
+ Flip = Aig_ObjFaninC0(pObj) ? ~0 : 0;
+ for ( w = 0; w < p->nWords; w++ )
+ pSim[w] = Flip ^ pSim0[w];
+ }
+ // refine classes
+ if ( fUpdate )
+ {
+ if ( fFirst )
+ {
+ Vec_Ptr_t * vCands = Vec_PtrAlloc( 1000 );
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ if ( Ssw_ObjIsConst1Cand( p->pAig, pObj ) )
+ Vec_PtrPush( vCands, pObj );
+ assert( Vec_PtrSize(vCands) == Ssw_ClassesCand1Num(p->ppClasses) );
+ Ssw_ClassesPrepareRehash( p->ppClasses, vCands, 0 );
+ Vec_PtrFree( vCands );
+ }
+ else
+ {
+ Ssw_ClassesRefineConst1Group( p->ppClasses, p->vUpdConst, 1 );
+ Ssw_ClassesRefineGroup( p->ppClasses, p->vUpdClass, 1 );
+ }
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static Ssw_RarMan_t * Ssw_RarManStart( Aig_Man_t * pAig, int nWords, int nFrames, int nBinSize, int fVerbose )
+{
+ Ssw_RarMan_t * p;
+// if ( Aig_ManRegNum(pAig) < nBinSize || nBinSize <= 0 )
+// return NULL;
+ p = ABC_CALLOC( Ssw_RarMan_t, 1 );
+ p->pAig = pAig;
+ p->nWords = nWords;
+ p->nFrames = nFrames;
+ p->nBinSize = nBinSize;
+ p->fVerbose = fVerbose;
+ p->nGroups = Aig_ManRegNum(pAig) / nBinSize;
+ p->pRarity = ABC_CALLOC( int, (1 << nBinSize) * p->nGroups );
+ p->pPatCosts = ABC_CALLOC( double, p->nWords * 64 );
+ p->nWordsReg = Ssw_RarBitWordNum( Aig_ManRegNum(pAig) );
+ p->pObjData = ABC_ALLOC( word, Aig_ManObjNumMax(pAig) * p->nWords );
+ p->pPatData = ABC_ALLOC( word, 64 * p->nWords * p->nWordsReg );
+ p->vUpdConst = Vec_PtrAlloc( 100 );
+ p->vUpdClass = Vec_PtrAlloc( 100 );
+ p->vPatBests = Vec_IntAlloc( 100 );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Ssw_RarManStop( Ssw_RarMan_t * p )
+{
+ if ( p->ppClasses ) Ssw_ClassesStop( p->ppClasses );
+ Vec_IntFreeP( &p->vInits );
+ Vec_IntFreeP( &p->vPatBests );
+ Vec_PtrFreeP( &p->vUpdConst );
+ Vec_PtrFreeP( &p->vUpdClass );
+ ABC_FREE( p->pObjData );
+ ABC_FREE( p->pPatData );
+ ABC_FREE( p->pPatCosts );
+ ABC_FREE( p->pRarity );
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Select best patterns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Ssw_RarTransferPatterns( Ssw_RarMan_t * p, Vec_Int_t * vInits )
+{
+// Aig_Obj_t * pObj;
+ unsigned char * pData;
+ unsigned * pPattern;
+ int i, k, Value;
+
+ // more data from regs to pats
+ Ssw_RarTranspose( p );
+
+ // update counters
+ for ( k = 0; k < p->nWords * 64; k++ )
+ {
+ pData = (unsigned char *)Ssw_RarPatSim( p, k );
+ for ( i = 0; i < p->nGroups; i++ )
+ Ssw_RarAddToBinPat( p, i, pData[i] );
+ }
+
+ // for each pattern
+ for ( k = 0; k < p->nWords * 64; k++ )
+ {
+ pData = (unsigned char *)Ssw_RarPatSim( p, k );
+ // find the cost of its values
+ p->pPatCosts[k] = 0.0;
+ for ( i = 0; i < p->nGroups; i++ )
+ {
+ Value = Ssw_RarGetBinPat( p, i, pData[i] );
+ assert( Value > 0 );
+ p->pPatCosts[k] += 1.0/(Value*Value);
+ }
+ // print the result
+//printf( "%3d : %9.6f\n", k, p->pPatCosts[k] );
+ }
+
+ // choose as many as there are words
+ Vec_IntClear( vInits );
+ for ( i = 0; i < p->nWords; i++ )
+ {
+ // select the best
+ int iPatBest = -1;
+ double iCostBest = -ABC_INFINITY;
+ for ( k = 0; k < p->nWords * 64; k++ )
+ if ( iCostBest < p->pPatCosts[k] )
+ {
+ iCostBest = p->pPatCosts[k];
+ iPatBest = k;
+ }
+ // remove from costs
+ assert( iPatBest >= 0 );
+ p->pPatCosts[iPatBest] = -ABC_INFINITY;
+ // set the flops
+ pPattern = (unsigned *)Ssw_RarPatSim( p, iPatBest );
+ for ( k = 0; k < Aig_ManRegNum(p->pAig); k++ )
+ Vec_IntPush( vInits, Abc_InfoHasBit(pPattern, k) );
+//printf( "Best pattern %5d\n", iPatBest );
+ Vec_IntPush( p->vPatBests, iPatBest );
+ }
+ assert( Vec_IntSize(vInits) == Aig_ManRegNum(p->pAig) * p->nWords );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging for one node.]
+
+ Description [Returns the fraiged node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static Vec_Int_t * Ssw_RarFindStartingState( Aig_Man_t * pAig, Abc_Cex_t * pCex )
+{
+ Vec_Int_t * vInit;
+ Aig_Obj_t * pObj, * pObjLi;
+ int f, i, iBit;
+ // assign register outputs
+ Saig_ManForEachLi( pAig, pObj, i )
+ pObj->fMarkB = Abc_InfoHasBit( pCex->pData, i );
+ // simulate the timeframes
+ iBit = pCex->nRegs;
+ for ( f = 0; f <= pCex->iFrame; f++ )
+ {
+ // set the PI simulation information
+ Aig_ManConst1(pAig)->fMarkB = 1;
+ Saig_ManForEachPi( pAig, pObj, i )
+ pObj->fMarkB = Abc_InfoHasBit( pCex->pData, iBit++ );
+ Saig_ManForEachLiLo( pAig, pObjLi, pObj, i )
+ pObj->fMarkB = pObjLi->fMarkB;
+ // simulate internal nodes
+ Aig_ManForEachNode( pAig, pObj, i )
+ pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) )
+ & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) );
+ // assign the COs
+ Aig_ManForEachPo( pAig, pObj, i )
+ pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) );
+ }
+ assert( iBit == pCex->nBits );
+ // check that the output failed as expected -- cannot check because it is not an SRM!
+// pObj = Aig_ManPo( pAig, pCex->iPo );
+// if ( pObj->fMarkB != 1 )
+// printf( "The counter-example does not refine the output.\n" );
+ // record the new pattern
+ vInit = Vec_IntAlloc( Saig_ManRegNum(pAig) );
+ Saig_ManForEachLo( pAig, pObj, i )
+ {
+//printf( "%d", pObj->fMarkB );
+ Vec_IntPush( vInit, pObj->fMarkB );
+ }
+//printf( "\n" );
+ Aig_ManCleanMarkB( pAig );
+ return vInit;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_RarCheckTrivial( Aig_Man_t * pAig, int fVerbose )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Saig_ManForEachPo( pAig, pObj, i )
+ {
+ if ( pAig->nConstrs && i >= Saig_ManPoNum(pAig) - pAig->nConstrs )
+ return 0;
+ if ( pObj->fPhase )
+ {
+ ABC_FREE( pAig->pSeqModel );
+ pAig->pSeqModel = Abc_CexAlloc( Aig_ManRegNum(pAig), Saig_ManPiNum(pAig), 1 );
+ pAig->pSeqModel->iPo = i;
+ if ( fVerbose )
+ printf( "Output %d is trivally SAT in frame 0. \n", i );
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Perform sequential simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_RarSimulate( Aig_Man_t * pAig, int nFrames, int nWords, int nBinSize, int nRounds, int nRandSeed, int TimeOut, int fVerbose )
+{
+ int fTryBmc = 0;
+ int fMiter = 1;
+ Ssw_RarMan_t * p;
+ int r, f, clk, clkTotal = clock();
+ int nTimeToStop = time(NULL) + TimeOut;
+ int RetValue = -1;
+ int iFrameFail = -1;
+ assert( Aig_ManRegNum(pAig) > 0 );
+ assert( Aig_ManConstrNum(pAig) == 0 );
+ // consider the case of empty AIG
+ if ( Aig_ManNodeNum(pAig) == 0 )
+ return -1;
+ // check trivially SAT miters
+ if ( fMiter && Ssw_RarCheckTrivial( pAig, fVerbose ) )
+ return 0;
+ if ( fVerbose )
+ printf( "Rarity simulation with %d words, %d frames, %d rounds, %d seed, and %d sec timeout.\n",
+ nWords, nFrames, nRounds, nRandSeed, TimeOut );
+ // reset random numbers
+ Ssw_RarManPrepareRandom( nRandSeed );
+
+ // create manager
+ p = Ssw_RarManStart( pAig, nWords, nFrames, nBinSize, fVerbose );
+ p->vInits = Vec_IntStart( Aig_ManRegNum(pAig) * nWords );
+
+ // perform simulation rounds
+ for ( r = 0; r < nRounds; r++ )
+ {
+ clk = clock();
+ if ( fTryBmc )
+ {
+ Aig_Man_t * pNewAig = Saig_ManDupWithPhase( pAig, p->vInits );
+ Saig_BmcPerform( pNewAig, 0, 100, 2000, 3, 0, 0, 1 /*fVerbose*/, 0, &iFrameFail );
+// if ( pNewAig->pSeqModel != NULL )
+// printf( "BMC has found a counter-example in frame %d.\n", iFrameFail );
+ Aig_ManStop( pNewAig );
+ }
+ // simulate
+ for ( f = 0; f < nFrames; f++ )
+ {
+ Ssw_RarManSimulate( p, f ? NULL : p->vInits, 0, 0 );
+ if ( fMiter && Ssw_RarManCheckNonConstOutputs(p) )
+ {
+ if ( fVerbose ) printf( "\n" );
+// printf( "Simulation asserted a PO in frame f: %d <= f < %d.\n", r * nFrames, (r+1) * nFrames );
+ Ssw_RarManPrepareRandom( nRandSeed );
+ ABC_FREE( pAig->pSeqModel );
+ pAig->pSeqModel = Ssw_RarDeriveCex( p, r * p->nFrames + f, p->iFailPo, p->iFailPat, fVerbose );
+ RetValue = 0;
+ goto finish;
+ }
+ // check timeout
+ if ( TimeOut && time(NULL) > nTimeToStop )
+ {
+ if ( fVerbose ) printf( "\n" );
+ printf( "Reached timeout (%d seconds).\n", TimeOut );
+ goto finish;
+ }
+ }
+ // get initialization patterns
+ Ssw_RarTransferPatterns( p, p->vInits );
+ // printout
+ if ( fVerbose )
+ {
+// printf( "Round %3d: ", r );
+// Abc_PrintTime( 1, "Time", clock() - clk );
+ printf( "." );
+ }
+ }
+finish:
+ if ( r == nRounds && f == nFrames )
+ {
+ if ( fVerbose ) printf( "\n" );
+ printf( "Simulation did not assert POs in the first %d frames. ", nRounds * nFrames );
+ Abc_PrintTime( 1, "Time", clock() - clkTotal );
+ }
+ // cleanup
+ Ssw_RarManStop( p );
+ return RetValue;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Perform sequential simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_RarSimulateGia( Gia_Man_t * p, int nFrames, int nWords, int nBinSize, int nRounds, int nRandSeed, int TimeOut, int fVerbose )
+{
+ Aig_Man_t * pAig;
+ int RetValue;
+ pAig = Gia_ManToAigSimple( p );
+ RetValue = Ssw_RarSimulate( pAig, nFrames, nWords, nBinSize, nRounds, nRandSeed, TimeOut, fVerbose );
+ // save counter-example
+ Abc_CexFree( p->pCexSeq );
+ p->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL;
+ Aig_ManStop( pAig );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Filter equivalence classes of nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_RarSignalFilter( Aig_Man_t * pAig, int nFrames, int nWords, int nBinSize, int nRounds, int nRandSeed, int TimeOut, int fMiter, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose )
+{
+ Ssw_RarMan_t * p;
+ int r, f, i, k, clkTotal = clock();
+ int nTimeToStop = time(NULL) + TimeOut;
+ int RetValue = -1;
+ assert( Aig_ManRegNum(pAig) > 0 );
+ assert( Aig_ManConstrNum(pAig) == 0 );
+ // consider the case of empty AIG
+ if ( Aig_ManNodeNum(pAig) == 0 )
+ return -1;
+ // check trivially SAT miters
+ if ( fMiter && Ssw_RarCheckTrivial( pAig, 1 ) )
+ return 0;
+ if ( fVerbose )
+ printf( "Rarity equiv filtering with %d words, %d frames, %d rounds, %d seed, and %d sec timeout.\n",
+ nWords, nFrames, nRounds, nRandSeed, TimeOut );
+ // reset random numbers
+ Ssw_RarManPrepareRandom( nRandSeed );
+
+ // create manager
+ p = Ssw_RarManStart( pAig, nWords, nFrames, nBinSize, fVerbose );
+ // compute starting state if needed
+ assert( p->vInits == NULL );
+ if ( pCex )
+ {
+ p->vInits = Ssw_RarFindStartingState( pAig, pCex );
+ printf( "Beginning simulation from the state derived using the counter-example.\n" );
+ }
+ else
+ p->vInits = Vec_IntStart( Aig_ManRegNum(pAig) );
+ // duplicate the array
+ for ( i = 1; i < nWords; i++ )
+ for ( k = 0; k < Aig_ManRegNum(pAig); k++ )
+ Vec_IntPush( p->vInits, Vec_IntEntry(p->vInits, k) );
+ assert( Vec_IntSize(p->vInits) == Aig_ManRegNum(pAig) * nWords );
+
+ // create trivial equivalence classes with all nodes being candidates for constant 1
+ if ( pAig->pReprs == NULL )
+ p->ppClasses = Ssw_ClassesPrepareSimple( pAig, fLatchOnly, 0 );
+ else
+ p->ppClasses = Ssw_ClassesPrepareFromReprs( pAig );
+ Ssw_ClassesSetData( p->ppClasses, p, Ssw_RarManObjHashWord, Ssw_RarManObjIsConst, Ssw_RarManObjsAreEqual );
+ // print the stats
+ if ( fVerbose )
+ {
+ printf( "Initial : " );
+ Ssw_ClassesPrint( p->ppClasses, 0 );
+ }
+ // refine classes using BMC
+ for ( r = 0; r < nRounds; r++ )
+ {
+ // start filtering equivalence classes
+ if ( Ssw_ClassesCand1Num(p->ppClasses) == 0 && Ssw_ClassesClassNum(p->ppClasses) == 0 )
+ {
+ printf( "All equivalences are refined away.\n" );
+ break;
+ }
+ // simulate
+ for ( f = 0; f < nFrames; f++ )
+ {
+ Ssw_RarManSimulate( p, f ? NULL : p->vInits, 1, !r && !f );
+ if ( fMiter && Ssw_RarManCheckNonConstOutputs(p) )
+ {
+ if ( !fVerbose )
+ printf( "\r" );
+// printf( "Simulation asserted a PO in frame f: %d <= f < %d.\n", r * nFrames, (r+1) * nFrames );
+ Ssw_RarManPrepareRandom( nRandSeed );
+ Abc_CexFree( pAig->pSeqModel );
+ pAig->pSeqModel = Ssw_RarDeriveCex( p, r * p->nFrames + f, p->iFailPo, p->iFailPat, 1 );
+ RetValue = 0;
+ goto finish;
+ }
+ // check timeout
+ if ( TimeOut && time(NULL) > nTimeToStop )
+ {
+ if ( fVerbose ) printf( "\n" );
+ printf( "Reached timeout (%d seconds).\n", TimeOut );
+ goto finish;
+ }
+ }
+ // get initialization patterns
+ Ssw_RarTransferPatterns( p, p->vInits );
+ // printout
+ if ( fVerbose )
+ {
+ printf( "Round %3d: ", r );
+ Ssw_ClassesPrint( p->ppClasses, 0 );
+ }
+ else
+ {
+ printf( "." );
+ }
+ }
+finish:
+ // report
+ if ( r == nRounds && f == nFrames )
+ {
+ if ( !fVerbose )
+ printf( "\r" );
+ printf( "Simulation did not assert POs in the first %d frames. ", nRounds * nFrames );
+ Abc_PrintTime( 1, "Time", clock() - clkTotal );
+ }
+ // cleanup
+ Ssw_RarManStop( p );
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Filter equivalence classes of nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_RarSignalFilterGia( Gia_Man_t * p, int nFrames, int nWords, int nBinSize, int nRounds, int nRandSeed, int TimeOut, int fMiter, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose )
+{
+ Aig_Man_t * pAig;
+ int RetValue;
+ pAig = Gia_ManToAigSimple( p );
+ if ( p->pReprs != NULL )
+ {
+ Gia_ManReprToAigRepr2( pAig, p );
+ ABC_FREE( p->pReprs );
+ ABC_FREE( p->pNexts );
+ }
+ RetValue = Ssw_RarSignalFilter( pAig, nFrames, nWords, nBinSize, nRounds, nRandSeed, TimeOut, fMiter, pCex, fLatchOnly, fVerbose );
+ Gia_ManReprFromAigRepr( pAig, p );
+ // save counter-example
+ Abc_CexFree( p->pCexSeq );
+ p->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL;
+ Aig_ManStop( pAig );
+ return RetValue;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/ssw/sswRarity2.c b/src/proof/ssw/sswRarity2.c
new file mode 100644
index 00000000..ac22b0d5
--- /dev/null
+++ b/src/proof/ssw/sswRarity2.c
@@ -0,0 +1,517 @@
+/**CFile****************************************************************
+
+ FileName [sswRarity.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Inductive prover with constraints.]
+
+ Synopsis [Rarity-driven refinement of equivalence classes.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 1, 2008.]
+
+ Revision [$Id: sswRarity.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+#include "src/aig/gia/giaAig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Ssw_RarMan_t_ Ssw_RarMan_t;
+struct Ssw_RarMan_t_
+{
+ // parameters
+ int nWords; // the number of words to simulate
+ int nFrames; // the number of frames to simulate
+ int nBinSize; // the number of flops in one group
+ int fVerbose; // the verbosiness flag
+ int nGroups; // the number of flop groups
+ // internal data
+ Aig_Man_t * pAig; // AIG with equivalence classes
+ Ssw_Cla_t * ppClasses; // equivalence classes
+ Ssw_Sml_t * pSml; // simulation manager
+ Vec_Ptr_t * vSimInfo; // simulation info from pSml manager
+ Vec_Int_t * vInits; // initial state
+ // rarity data
+ int * pRarity; // occur counts for patterns in groups
+ int * pGroupValues; // occur counts in each group
+ double * pPatCosts; // pattern costs
+
+};
+
+static inline int Ssw_RarGetBinPat( Ssw_RarMan_t * p, int iBin, int iPat )
+{
+ assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->nBinSize );
+ assert( iPat >= 0 && iPat < (1 << p->nBinSize) );
+ return p->pRarity[iBin * (1 << p->nBinSize) + iPat];
+}
+static inline void Ssw_RarSetBinPat( Ssw_RarMan_t * p, int iBin, int iPat, int Value )
+{
+ assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->nBinSize );
+ assert( iPat >= 0 && iPat < (1 << p->nBinSize) );
+ p->pRarity[iBin * (1 << p->nBinSize) + iPat] = Value;
+}
+static inline void Ssw_RarAddToBinPat( Ssw_RarMan_t * p, int iBin, int iPat )
+{
+ assert( iBin >= 0 && iBin < Aig_ManRegNum(p->pAig) / p->nBinSize );
+ assert( iPat >= 0 && iPat < (1 << p->nBinSize) );
+ p->pRarity[iBin * (1 << p->nBinSize) + iPat]++;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static Ssw_RarMan_t * Ssw_RarManStart( Aig_Man_t * pAig, int nWords, int nFrames, int nBinSize, int fVerbose )
+{
+ Ssw_RarMan_t * p;
+ if ( Aig_ManRegNum(pAig) < nBinSize || nBinSize <= 0 )
+ return NULL;
+ p = ABC_CALLOC( Ssw_RarMan_t, 1 );
+ p->pAig = pAig;
+ p->nWords = nWords;
+ p->nFrames = nFrames;
+ p->nBinSize = nBinSize;
+ p->fVerbose = fVerbose;
+ p->nGroups = Aig_ManRegNum(pAig) / nBinSize;
+ p->pRarity = ABC_CALLOC( int, (1 << nBinSize) * p->nGroups );
+ p->pGroupValues = ABC_CALLOC( int, p->nGroups );
+ p->pPatCosts = ABC_CALLOC( double, p->nWords * 32 );
+ p->pSml = Ssw_SmlStart( pAig, 0, nFrames, nWords );
+ p->vSimInfo = Ssw_SmlSimDataPointers( p->pSml );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Ssw_RarManStop( Ssw_RarMan_t * p )
+{
+ if ( p->pSml ) Ssw_SmlStop( p->pSml );
+ if ( p->ppClasses ) Ssw_ClassesStop( p->ppClasses );
+ Vec_PtrFreeP( &p->vSimInfo );
+ Vec_IntFreeP( &p->vInits );
+ ABC_FREE( p->pGroupValues );
+ ABC_FREE( p->pPatCosts );
+ ABC_FREE( p->pRarity );
+ ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Updates rarity counters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Ssw_RarUpdateCounters( Ssw_RarMan_t * p )
+{
+ Aig_Obj_t * pObj;
+ unsigned * pData;
+ int i, k;
+/*
+ Saig_ManForEachLi( p->pAig, pObj, i )
+ {
+ pData = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjId(pObj) ) + p->nWords * (p->nFrames - 1);
+ Extra_PrintBinary( stdout, pData, 32 ); printf( "\n" );
+ }
+*/
+ for ( k = 0; k < p->nWords * 32; k++ )
+ {
+ for ( i = 0; i < p->nGroups; i++ )
+ p->pGroupValues[i] = 0;
+ Saig_ManForEachLi( p->pAig, pObj, i )
+ {
+ pData = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjId(pObj) ) + p->nWords * (p->nFrames - 1);
+ if ( Abc_InfoHasBit(pData, k) && i / p->nBinSize < p->nGroups )
+ p->pGroupValues[i / p->nBinSize] |= (1 << (i % p->nBinSize));
+ }
+ for ( i = 0; i < p->nGroups; i++ )
+ Ssw_RarAddToBinPat( p, i, p->pGroupValues[i] );
+ }
+/*
+ for ( i = 0; i < p->nGroups; i++ )
+ {
+ for ( k = 0; k < (1 << p->nBinSize); k++ )
+ printf( "%d ", Ssw_RarGetBinPat(p, i, k) );
+ printf( "\n" );
+ }
+*/
+}
+
+/**Function*************************************************************
+
+ Synopsis [Select best patterns.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static void Ssw_RarTransferPatterns( Ssw_RarMan_t * p, Vec_Int_t * vInits )
+{
+ Aig_Obj_t * pObj;
+ unsigned * pData;
+ int i, k, Value;
+
+ // for each pattern
+ for ( k = 0; k < p->nWords * 32; k++ )
+ {
+ for ( i = 0; i < p->nGroups; i++ )
+ p->pGroupValues[i] = 0;
+ // compute its group values
+ Saig_ManForEachLi( p->pAig, pObj, i )
+ {
+ pData = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjId(pObj) ) + p->nWords * (p->nFrames - 1);
+ if ( Abc_InfoHasBit(pData, k) && i / p->nBinSize < p->nGroups )
+ p->pGroupValues[i / p->nBinSize] |= (1 << (i % p->nBinSize));
+ }
+ // find the cost of its values
+ p->pPatCosts[k] = 0.0;
+ for ( i = 0; i < p->nGroups; i++ )
+ {
+ Value = Ssw_RarGetBinPat( p, i, p->pGroupValues[i] );
+ assert( Value > 0 );
+ p->pPatCosts[k] += 1.0/(Value*Value);
+ }
+ // print the result
+// printf( "%3d : %9.6f\n", k, p->pPatCosts[k] );
+ }
+
+ // choose as many as there are words
+ Vec_IntClear( vInits );
+ for ( i = 0; i < p->nWords; i++ )
+ {
+ // select the best
+ int iPatBest = -1;
+ double iCostBest = -ABC_INFINITY;
+ for ( k = 0; k < p->nWords * 32; k++ )
+ if ( iCostBest < p->pPatCosts[k] )
+ {
+ iCostBest = p->pPatCosts[k];
+ iPatBest = k;
+ }
+ // remove from costs
+ assert( iPatBest >= 0 );
+ p->pPatCosts[iPatBest] = -ABC_INFINITY;
+ // set the flops
+ Saig_ManForEachLi( p->pAig, pObj, k )
+ {
+ pData = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjId(pObj) ) + p->nWords * (p->nFrames - 1);
+ Vec_IntPush( vInits, Abc_InfoHasBit(pData, iPatBest) );
+ }
+//printf( "Best pattern %5d\n", iPatBest );
+ }
+ assert( Vec_IntSize(vInits) == Aig_ManRegNum(p->pAig) * p->nWords );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging for one node.]
+
+ Description [Returns the fraiged node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static Vec_Int_t * Ssw_RarFindStartingState( Aig_Man_t * pAig, Abc_Cex_t * pCex )
+{
+ Vec_Int_t * vInit;
+ Aig_Obj_t * pObj, * pObjLi;
+ int f, i, iBit;
+ // assign register outputs
+ Saig_ManForEachLi( pAig, pObj, i )
+ pObj->fMarkB = Abc_InfoHasBit( pCex->pData, i );
+ // simulate the timeframes
+ iBit = pCex->nRegs;
+ for ( f = 0; f <= pCex->iFrame; f++ )
+ {
+ // set the PI simulation information
+ Aig_ManConst1(pAig)->fMarkB = 1;
+ Saig_ManForEachPi( pAig, pObj, i )
+ pObj->fMarkB = Abc_InfoHasBit( pCex->pData, iBit++ );
+ Saig_ManForEachLiLo( pAig, pObjLi, pObj, i )
+ pObj->fMarkB = pObjLi->fMarkB;
+ // simulate internal nodes
+ Aig_ManForEachNode( pAig, pObj, i )
+ pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) )
+ & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) );
+ // assign the COs
+ Aig_ManForEachPo( pAig, pObj, i )
+ pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) );
+ }
+ assert( iBit == pCex->nBits );
+ // check that the output failed as expected -- cannot check because it is not an SRM!
+// pObj = Aig_ManPo( pAig, pCex->iPo );
+// if ( pObj->fMarkB != 1 )
+// printf( "The counter-example does not refine the output.\n" );
+ // record the new pattern
+ vInit = Vec_IntAlloc( Saig_ManRegNum(pAig) );
+ Saig_ManForEachLo( pAig, pObj, i )
+ Vec_IntPush( vInit, pObj->fMarkB );
+ return vInit;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Perform sequential simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_RarSimulate2( Aig_Man_t * pAig, int nFrames, int nWords, int nBinSize, int nRounds, int TimeOut, int fVerbose )
+{
+ int fMiter = 1;
+ Ssw_RarMan_t * p;
+ int r, clk, clkTotal = clock();
+ int nTimeToStop = time(NULL) + TimeOut;
+ int RetValue = -1;
+ assert( Aig_ManRegNum(pAig) > 0 );
+ assert( Aig_ManConstrNum(pAig) == 0 );
+ // consider the case of empty AIG
+ if ( Aig_ManNodeNum(pAig) == 0 )
+ return -1;
+ if ( fVerbose )
+ printf( "Simulating %d words through %d frames with %d binsize, %d rounds, and %d sec timeout.\n",
+ nWords, nFrames, nBinSize, nRounds, TimeOut );
+ // reset random numbers
+ Aig_ManRandom( 1 );
+
+ // create manager
+ p = Ssw_RarManStart( pAig, nWords, nFrames, nBinSize, fVerbose );
+ p->vInits = Vec_IntStart( Aig_ManRegNum(pAig) * nWords );
+ Ssw_SmlInitializeSpecial( p->pSml, p->vInits );
+
+ // perform simulation rounds
+ for ( r = 0; r < nRounds; r++ )
+ {
+ clk = clock();
+ // simulate
+ Ssw_SmlSimulateOne( p->pSml );
+ if ( fMiter && Ssw_SmlCheckNonConstOutputs(p->pSml) )
+ {
+ if ( fVerbose ) printf( "\n" );
+ printf( "Simulation asserted a PO in frame f: %d <= f < %d.\n", r * nFrames, (r+1) * nFrames );
+ RetValue = 0;
+ break;
+ }
+ // get initialization patterns
+ Ssw_RarUpdateCounters( p );
+ Ssw_RarTransferPatterns( p, p->vInits );
+ Ssw_SmlInitializeSpecial( p->pSml, p->vInits );
+ // printout
+ if ( fVerbose )
+ {
+// printf( "Round %3d: ", r );
+// Abc_PrintTime( 1, "Time", clock() - clk );
+ printf( "." );
+ }
+ // check timeout
+ if ( TimeOut && time(NULL) > nTimeToStop )
+ {
+ if ( fVerbose ) printf( "\n" );
+ printf( "Reached timeout (%d seconds).\n", TimeOut );
+ break;
+ }
+ }
+ if ( r == nRounds )
+ {
+ if ( fVerbose ) printf( "\n" );
+ printf( "Simulation did not assert POs in the first %d frames. ", nRounds * nFrames );
+ Abc_PrintTime( 1, "Time", clock() - clkTotal );
+ }
+ // cleanup
+ Ssw_RarManStop( p );
+ return RetValue;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Filter equivalence classes of nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_RarSignalFilter2( Aig_Man_t * pAig, int nFrames, int nWords, int nBinSize, int nRounds, int TimeOut, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose )
+{
+ int fMiter = 0;
+ Ssw_RarMan_t * p;
+ int r, i, k, clkTotal = clock();
+ int nTimeToStop = time(NULL) + TimeOut;
+ int RetValue = -1;
+ assert( Aig_ManRegNum(pAig) > 0 );
+ assert( Aig_ManConstrNum(pAig) == 0 );
+ // consider the case of empty AIG
+ if ( Aig_ManNodeNum(pAig) == 0 )
+ return -1;
+ if ( fVerbose )
+ printf( "Filtering equivs with %d words through %d frames with %d binsize, %d rounds, and %d sec timeout.\n",
+ nWords, nFrames, nBinSize, nRounds, TimeOut );
+ // reset random numbers
+ Aig_ManRandom( 1 );
+
+ // create manager
+ p = Ssw_RarManStart( pAig, nWords, nFrames, nBinSize, fVerbose );
+ // compute starting state if needed
+ assert( p->vInits == NULL );
+ if ( pCex )
+ p->vInits = Ssw_RarFindStartingState( pAig, pCex );
+ else
+ p->vInits = Vec_IntStart( Aig_ManRegNum(pAig) );
+ // duplicate the array
+ for ( i = 1; i < nWords; i++ )
+ for ( k = 0; k < Aig_ManRegNum(pAig); k++ )
+ Vec_IntPush( p->vInits, Vec_IntEntry(p->vInits, k) );
+ assert( Vec_IntSize(p->vInits) == Aig_ManRegNum(pAig) * nWords );
+ // initialize simulation manager
+ Ssw_SmlInitializeSpecial( p->pSml, p->vInits );
+
+ // create trivial equivalence classes with all nodes being candidates for constant 1
+ if ( pAig->pReprs == NULL )
+ p->ppClasses = Ssw_ClassesPrepareSimple( pAig, fLatchOnly, 0 );
+ else
+ p->ppClasses = Ssw_ClassesPrepareFromReprs( pAig );
+ Ssw_ClassesSetData( p->ppClasses, p->pSml, NULL, (int(*)(void *,Aig_Obj_t *))Ssw_SmlObjIsConstWord, (int(*)(void *,Aig_Obj_t *,Aig_Obj_t *))Ssw_SmlObjsAreEqualWord );
+ // print the stats
+ if ( fVerbose )
+ {
+ printf( "Initial : " );
+ Ssw_ClassesPrint( p->ppClasses, 0 );
+ }
+ // refine classes using BMC
+ for ( r = 0; r < nRounds; r++ )
+ {
+ // start filtering equivalence classes
+ if ( Ssw_ClassesCand1Num(p->ppClasses) == 0 && Ssw_ClassesClassNum(p->ppClasses) == 0 )
+ {
+ printf( "All equivalences are refined away.\n" );
+ break;
+ }
+ // simulate
+ Ssw_SmlSimulateOne( p->pSml );
+ if ( fMiter && Ssw_SmlCheckNonConstOutputs(p->pSml) )
+ {
+ if ( fVerbose ) printf( "\n" );
+ printf( "Simulation asserted a PO in frame f: %d <= f < %d.\n", r * nFrames, (r+1) * nFrames );
+ RetValue = 0;
+ break;
+ }
+ // check equivalence classes
+ Ssw_ClassesRefineConst1( p->ppClasses, 1 );
+ Ssw_ClassesRefine( p->ppClasses, 1 );
+ // printout
+ if ( fVerbose )
+ {
+ printf( "Round %3d: ", r );
+ Ssw_ClassesPrint( p->ppClasses, 0 );
+ }
+ // get initialization patterns
+ Ssw_RarUpdateCounters( p );
+ Ssw_RarTransferPatterns( p, p->vInits );
+ Ssw_SmlInitializeSpecial( p->pSml, p->vInits );
+ // check timeout
+ if ( TimeOut && time(NULL) > nTimeToStop )
+ {
+ if ( fVerbose ) printf( "\n" );
+ printf( "Reached timeout (%d seconds).\n", TimeOut );
+ break;
+ }
+ }
+ if ( r == nRounds )
+ {
+ printf( "Simulation did not assert POs in the first %d frames. ", nRounds * nFrames );
+ Abc_PrintTime( 1, "Time", clock() - clkTotal );
+ }
+ // cleanup
+ Ssw_RarManStop( p );
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Filter equivalence classes of nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_RarSignalFilterGia2( Gia_Man_t * p, int nFrames, int nWords, int nBinSize, int nRounds, int TimeOut, Abc_Cex_t * pCex, int fLatchOnly, int fVerbose )
+{
+ Aig_Man_t * pAig;
+ int RetValue;
+ pAig = Gia_ManToAigSimple( p );
+ if ( p->pReprs != NULL )
+ {
+ Gia_ManReprToAigRepr2( pAig, p );
+ ABC_FREE( p->pReprs );
+ ABC_FREE( p->pNexts );
+ }
+ RetValue = Ssw_RarSignalFilter2( pAig, nFrames, nWords, nBinSize, nRounds, TimeOut, pCex, fLatchOnly, fVerbose );
+ Gia_ManReprFromAigRepr( pAig, p );
+ Aig_ManStop( pAig );
+ return RetValue;
+}
+
+
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/ssw/sswSat.c b/src/proof/ssw/sswSat.c
new file mode 100644
index 00000000..7d371cac
--- /dev/null
+++ b/src/proof/ssw/sswSat.c
@@ -0,0 +1,306 @@
+/**CFile****************************************************************
+
+ FileName [sswSat.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Inductive prover with constraints.]
+
+ Synopsis [Calls to the SAT solver.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 1, 2008.]
+
+ Revision [$Id: sswSat.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Runs equivalence test for the two nodes.]
+
+ Description [Both nodes should be regular and different from each other.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_NodesAreEquiv( Ssw_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew )
+{
+ int nBTLimit = p->pPars->nBTLimit;
+ int pLits[3], nLits, RetValue, RetValue1, clk;//, status;
+ p->nSatCalls++;
+ p->pMSat->nSolverCalls++;
+
+ // sanity checks
+ assert( !Aig_IsComplement(pOld) );
+ assert( !Aig_IsComplement(pNew) );
+ assert( pOld != pNew );
+ assert( p->pMSat != NULL );
+
+ // if the nodes do not have SAT variables, allocate them
+ Ssw_CnfNodeAddToSolver( p->pMSat, pOld );
+ Ssw_CnfNodeAddToSolver( p->pMSat, pNew );
+
+ // solve under assumptions
+ // A = 1; B = 0 OR A = 1; B = 1
+ nLits = 2;
+ pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pOld), 0 );
+ pLits[1] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), pOld->fPhase == pNew->fPhase );
+ if ( p->iOutputLit > -1 )
+ pLits[nLits++] = p->iOutputLit;
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( pOld->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( pNew->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ }
+//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 );
+
+ if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead )
+ {
+ RetValue = sat_solver_simplify(p->pMSat->pSat);
+ assert( RetValue != 0 );
+ }
+
+clk = clock();
+ RetValue1 = sat_solver_solve( p->pMSat->pSat, pLits, pLits + nLits,
+ (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+p->timeSat += clock() - clk;
+ if ( RetValue1 == l_False )
+ {
+p->timeSatUnsat += clock() - clk;
+ if ( nLits == 2 )
+ {
+ pLits[0] = lit_neg( pLits[0] );
+ pLits[1] = lit_neg( pLits[1] );
+ RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 2 );
+ assert( RetValue );
+/*
+ if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead )
+ {
+ RetValue = sat_solver_simplify(p->pMSat->pSat);
+ assert( RetValue != 0 );
+ }
+*/
+ }
+ p->nSatCallsUnsat++;
+ }
+ else if ( RetValue1 == l_True )
+ {
+p->timeSatSat += clock() - clk;
+ p->nSatCallsSat++;
+ return 0;
+ }
+ else // if ( RetValue1 == l_Undef )
+ {
+p->timeSatUndec += clock() - clk;
+ p->nSatFailsReal++;
+ return -1;
+ }
+
+ // if the old node was constant 0, we already know the answer
+ if ( pOld == Aig_ManConst1(p->pFrames) )
+ {
+ p->nSatProof++;
+ return 1;
+ }
+
+ // solve under assumptions
+ // A = 0; B = 1 OR A = 0; B = 0
+ nLits = 2;
+ pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pOld), 1 );
+ pLits[1] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), pOld->fPhase ^ pNew->fPhase );
+ if ( p->iOutputLit > -1 )
+ pLits[nLits++] = p->iOutputLit;
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( pOld->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( pNew->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ }
+
+ if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead )
+ {
+ RetValue = sat_solver_simplify(p->pMSat->pSat);
+ assert( RetValue != 0 );
+ }
+
+clk = clock();
+ RetValue1 = sat_solver_solve( p->pMSat->pSat, pLits, pLits + nLits,
+ (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
+p->timeSat += clock() - clk;
+ if ( RetValue1 == l_False )
+ {
+p->timeSatUnsat += clock() - clk;
+ if ( nLits == 2 )
+ {
+ pLits[0] = lit_neg( pLits[0] );
+ pLits[1] = lit_neg( pLits[1] );
+ RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 2 );
+ assert( RetValue );
+/*
+ if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead )
+ {
+ RetValue = sat_solver_simplify(p->pMSat->pSat);
+ assert( RetValue != 0 );
+ }
+*/
+ }
+ p->nSatCallsUnsat++;
+ }
+ else if ( RetValue1 == l_True )
+ {
+p->timeSatSat += clock() - clk;
+ p->nSatCallsSat++;
+ return 0;
+ }
+ else // if ( RetValue1 == l_Undef )
+ {
+p->timeSatUndec += clock() - clk;
+ p->nSatFailsReal++;
+ return -1;
+ }
+ // return SAT proof
+ p->nSatProof++;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Constrains two nodes to be equivalent in the SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_NodesAreConstrained( Ssw_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew )
+{
+ int pLits[2], RetValue, fComplNew;
+ Aig_Obj_t * pTemp;
+
+ // sanity checks
+ assert( Aig_Regular(pOld) != Aig_Regular(pNew) );
+ assert( p->pPars->fConstrs || Aig_ObjPhaseReal(pOld) == Aig_ObjPhaseReal(pNew) );
+
+ // move constant to the old node
+ if ( Aig_Regular(pNew) == Aig_ManConst1(p->pFrames) )
+ {
+ assert( Aig_Regular(pOld) != Aig_ManConst1(p->pFrames) );
+ pTemp = pOld;
+ pOld = pNew;
+ pNew = pTemp;
+ }
+
+ // move complement to the new node
+ if ( Aig_IsComplement(pOld) )
+ {
+ pOld = Aig_Regular(pOld);
+ pNew = Aig_Not(pNew);
+ }
+ assert( p->pMSat != NULL );
+
+ // if the nodes do not have SAT variables, allocate them
+ Ssw_CnfNodeAddToSolver( p->pMSat, pOld );
+ Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pNew) );
+
+ // transform the new node
+ fComplNew = Aig_IsComplement( pNew );
+ pNew = Aig_Regular( pNew );
+
+ // consider the constant 1 case
+ if ( pOld == Aig_ManConst1(p->pFrames) )
+ {
+ // add constraint A = 1 ----> A
+ pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), fComplNew );
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( pNew->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ }
+ RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 1 );
+ assert( RetValue );
+ }
+ else
+ {
+ // add constraint A = B ----> (A v !B)(!A v B)
+
+ // (A v !B)
+ pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pOld), 0 );
+ pLits[1] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), !fComplNew );
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( pOld->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( pNew->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ }
+ pLits[0] = lit_neg( pLits[0] );
+ pLits[1] = lit_neg( pLits[1] );
+ RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 2 );
+ assert( RetValue );
+
+ // (!A v B)
+ pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pOld), 1 );
+ pLits[1] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), fComplNew);
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( pOld->fPhase ) pLits[0] = lit_neg( pLits[0] );
+ if ( pNew->fPhase ) pLits[1] = lit_neg( pLits[1] );
+ }
+ pLits[0] = lit_neg( pLits[0] );
+ pLits[1] = lit_neg( pLits[1] );
+ RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 2 );
+ assert( RetValue );
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Constrains one node in the SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_NodeIsConstrained( Ssw_Man_t * p, Aig_Obj_t * pPoObj )
+{
+ int RetValue, Lit;
+ Ssw_CnfNodeAddToSolver( p->pMSat, Aig_ObjFanin0(pPoObj) );
+ // add constraint A = 1 ----> A
+ Lit = toLitCond( Ssw_ObjSatNum(p->pMSat,Aig_ObjFanin0(pPoObj)), !Aig_ObjFaninC0(pPoObj) );
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( Aig_ObjFanin0(pPoObj)->fPhase ) Lit = lit_neg( Lit );
+ }
+ RetValue = sat_solver_addclause( p->pMSat->pSat, &Lit, &Lit + 1 );
+ assert( RetValue );
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/ssw/sswSemi.c b/src/proof/ssw/sswSemi.c
new file mode 100644
index 00000000..74305adf
--- /dev/null
+++ b/src/proof/ssw/sswSemi.c
@@ -0,0 +1,322 @@
+/**CFile****************************************************************
+
+ FileName [sswSemi.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Inductive prover with constraints.]
+
+ Synopsis [Semiformal for equivalence clases.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 1, 2008.]
+
+ Revision [$Id: sswSemi.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Ssw_Sem_t_ Ssw_Sem_t; // BMC manager
+
+struct Ssw_Sem_t_
+{
+ // parameters
+ int nConfMaxStart; // the starting conflict limit
+ int nConfMax; // the intermediate conflict limit
+ int nFramesSweep; // the number of frames to sweep
+ int fVerbose; // prints output statistics
+ // equivalences considered
+ Ssw_Man_t * pMan; // SAT sweeping manager
+ Vec_Ptr_t * vTargets; // the nodes that are watched
+ // storage for patterns
+ int nPatternsAlloc; // the max number of interesting states
+ int nPatterns; // the number of patterns
+ Vec_Ptr_t * vPatterns; // storage for the interesting states
+ Vec_Int_t * vHistory; // what state and how many steps
+};
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ssw_Sem_t * Ssw_SemManStart( Ssw_Man_t * pMan, int nConfMax, int fVerbose )
+{
+ Ssw_Sem_t * p;
+ Aig_Obj_t * pObj;
+ int i;
+ // create interpolation manager
+ p = ABC_ALLOC( Ssw_Sem_t, 1 );
+ memset( p, 0, sizeof(Ssw_Sem_t) );
+ p->nConfMaxStart = nConfMax;
+ p->nConfMax = nConfMax;
+ p->nFramesSweep = Abc_MaxInt( (1<<21)/Aig_ManNodeNum(pMan->pAig), pMan->nFrames );
+ p->fVerbose = fVerbose;
+ // equivalences considered
+ p->pMan = pMan;
+ p->vTargets = Vec_PtrAlloc( Saig_ManPoNum(p->pMan->pAig) );
+ Saig_ManForEachPo( p->pMan->pAig, pObj, i )
+ Vec_PtrPush( p->vTargets, Aig_ObjFanin0(pObj) );
+ // storage for patterns
+ p->nPatternsAlloc = 512;
+ p->nPatterns = 1;
+ p->vPatterns = Vec_PtrAllocSimInfo( Aig_ManRegNum(p->pMan->pAig), Abc_BitWordNum(p->nPatternsAlloc) );
+ Vec_PtrCleanSimInfo( p->vPatterns, 0, Abc_BitWordNum(p->nPatternsAlloc) );
+ p->vHistory = Vec_IntAlloc( 100 );
+ Vec_IntPush( p->vHistory, 0 );
+ // update arrays of the manager
+ assert( 0 );
+/*
+ ABC_FREE( p->pMan->pNodeToFrames );
+ Vec_IntFree( p->pMan->vSatVars );
+ p->pMan->pNodeToFrames = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pMan->pAig) * p->nFramesSweep );
+ p->pMan->vSatVars = Vec_IntStart( Aig_ManObjNumMax(p->pMan->pAig) * (p->nFramesSweep+1) );
+*/
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SemManStop( Ssw_Sem_t * p )
+{
+ Vec_PtrFree( p->vTargets );
+ Vec_PtrFree( p->vPatterns );
+ Vec_IntFree( p->vHistory );
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_SemCheckTargets( Ssw_Sem_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vTargets, pObj, i )
+ if ( !Ssw_ObjIsConst1Cand(p->pMan->pAig, pObj) )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ManFilterBmcSavePattern( Ssw_Sem_t * p )
+{
+ unsigned * pInfo;
+ Aig_Obj_t * pObj;
+ int i;
+ if ( p->nPatterns >= p->nPatternsAlloc )
+ return;
+ Saig_ManForEachLo( p->pMan->pAig, pObj, i )
+ {
+ pInfo = (unsigned *)Vec_PtrEntry( p->vPatterns, i );
+ if ( Abc_InfoHasBit( p->pMan->pPatWords, Saig_ManPiNum(p->pMan->pAig) + i ) )
+ Abc_InfoSetBit( pInfo, p->nPatterns );
+ }
+ p->nPatterns++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging for the internal nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ManFilterBmc( Ssw_Sem_t * pBmc, int iPat, int fCheckTargets )
+{
+ Ssw_Man_t * p = pBmc->pMan;
+ Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo;
+ unsigned * pInfo;
+ int i, f, clk, RetValue, fFirst = 0;
+clk = clock();
+
+ // start initialized timeframes
+ p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * 3 );
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ {
+ pInfo = (unsigned *)Vec_PtrEntry( pBmc->vPatterns, i );
+ pObjNew = Aig_NotCond( Aig_ManConst1(p->pFrames), !Abc_InfoHasBit(pInfo, iPat) );
+ Ssw_ObjSetFrame( p, pObj, 0, pObjNew );
+ }
+
+ // sweep internal nodes
+ RetValue = pBmc->nFramesSweep;
+ for ( f = 0; f < pBmc->nFramesSweep; f++ )
+ {
+ // map constants and PIs
+ Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) );
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ Ssw_ObjSetFrame( p, pObj, f, Aig_ObjCreatePi(p->pFrames) );
+ // sweep internal nodes
+ Aig_ManForEachNode( p->pAig, pObj, i )
+ {
+ pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) );
+ Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+ if ( Ssw_ManSweepNode( p, pObj, f, 1, NULL ) )
+ {
+ Ssw_ManFilterBmcSavePattern( pBmc );
+ if ( fFirst == 0 )
+ {
+ fFirst = 1;
+ pBmc->nConfMax *= 10;
+ }
+ }
+ if ( f > 0 && p->pMSat->pSat->stats.conflicts >= pBmc->nConfMax )
+ {
+ RetValue = -1;
+ break;
+ }
+ }
+ // quit if this is the last timeframe
+ if ( p->pMSat->pSat->stats.conflicts >= pBmc->nConfMax )
+ {
+ RetValue += f + 1;
+ break;
+ }
+ if ( fCheckTargets && Ssw_SemCheckTargets( pBmc ) )
+ break;
+ // transfer latch input to the latch outputs
+ // build logic cones for register outputs
+ Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+ {
+ pObjNew = Ssw_ObjChild0Fra(p, pObjLi,f);
+ Ssw_ObjSetFrame( p, pObjLo, f+1, pObjNew );
+ Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pObjNew) );
+ }
+//printf( "Frame %2d : Conflicts = %6d. \n", f, p->pSat->stats.conflicts );
+ }
+ if ( fFirst )
+ pBmc->nConfMax /= 10;
+
+ // cleanup
+ Ssw_ClassesCheck( p->ppClasses );
+p->timeBmc += clock() - clk;
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if one of the targets has failed.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_FilterUsingSemi( Ssw_Man_t * pMan, int fCheckTargets, int nConfMax, int fVerbose )
+{
+ Ssw_Sem_t * p;
+ int RetValue, Frames, Iter, clk = clock();
+ p = Ssw_SemManStart( pMan, nConfMax, fVerbose );
+ if ( fCheckTargets && Ssw_SemCheckTargets( p ) )
+ {
+ assert( 0 );
+ Ssw_SemManStop( p );
+ return 1;
+ }
+ if ( fVerbose )
+ {
+ printf( "AIG : C = %6d. Cl = %6d. Nodes = %6d. ConfMax = %6d. FramesMax = %6d.\n",
+ Ssw_ClassesCand1Num(p->pMan->ppClasses), Ssw_ClassesClassNum(p->pMan->ppClasses),
+ Aig_ManNodeNum(p->pMan->pAig), p->nConfMax, p->nFramesSweep );
+ }
+ RetValue = 0;
+ for ( Iter = 0; Iter < p->nPatterns; Iter++ )
+ {
+clk = clock();
+ pMan->pMSat = Ssw_SatStart( 0 );
+ Frames = Ssw_ManFilterBmc( p, Iter, fCheckTargets );
+ if ( fVerbose )
+ {
+ printf( "%3d : C = %6d. Cl = %6d. NR = %6d. F = %3d. C = %5d. P = %3d. %s ",
+ Iter, Ssw_ClassesCand1Num(p->pMan->ppClasses), Ssw_ClassesClassNum(p->pMan->ppClasses),
+ Aig_ManNodeNum(p->pMan->pFrames), Frames, (int)p->pMan->pMSat->pSat->stats.conflicts, p->nPatterns,
+ p->pMan->nSatFailsReal? "f" : " " );
+ ABC_PRT( "T", clock() - clk );
+ }
+ Ssw_ManCleanup( p->pMan );
+ if ( fCheckTargets && Ssw_SemCheckTargets( p ) )
+ {
+ printf( "Target is hit!!!\n" );
+ RetValue = 1;
+ }
+ if ( p->nPatterns >= p->nPatternsAlloc )
+ break;
+ }
+ Ssw_SemManStop( p );
+
+ pMan->nStrangers = 0;
+ pMan->nSatCalls = 0;
+ pMan->nSatProof = 0;
+ pMan->nSatFailsReal = 0;
+ pMan->nSatCallsUnsat = 0;
+ pMan->nSatCallsSat = 0;
+ pMan->timeSimSat = 0;
+ pMan->timeSat = 0;
+ pMan->timeSatSat = 0;
+ pMan->timeSatUnsat = 0;
+ pMan->timeSatUndec = 0;
+ return RetValue;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/ssw/sswSim.c b/src/proof/ssw/sswSim.c
new file mode 100644
index 00000000..9ce89a71
--- /dev/null
+++ b/src/proof/ssw/sswSim.c
@@ -0,0 +1,1405 @@
+/**CFile****************************************************************
+
+ FileName [sswSim.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Inductive prover with constraints.]
+
+ Synopsis [Sequential simulator used by the inductive prover.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 1, 2008.]
+
+ Revision [$Id: sswSim.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+// simulation manager
+struct Ssw_Sml_t_
+{
+ Aig_Man_t * pAig; // the original AIG manager
+ int nPref; // the number of timeframes in the prefix
+ int nFrames; // the number of timeframes
+ int nWordsFrame; // the number of words in each timeframe
+ int nWordsTotal; // the total number of words at a node
+ int nWordsPref; // the number of word in the prefix
+ int fNonConstOut; // have seen a non-const-0 output during simulation
+ int nSimRounds; // statistics
+ int timeSim; // statistics
+ unsigned pData[0]; // simulation data for the nodes
+};
+
+static inline unsigned * Ssw_ObjSim( Ssw_Sml_t * p, int Id ) { return p->pData + p->nWordsTotal * Id; }
+static inline unsigned Ssw_ObjRandomSim() { return Aig_ManRandom(0); }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Computes hash value of the node using its simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned Ssw_SmlObjHashWord( Ssw_Sml_t * p, Aig_Obj_t * pObj )
+{
+ static int s_SPrimes[128] = {
+ 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459,
+ 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997,
+ 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543,
+ 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089,
+ 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671,
+ 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243,
+ 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871,
+ 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471,
+ 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073,
+ 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689,
+ 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309,
+ 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933,
+ 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147
+ };
+ unsigned * pSims;
+ unsigned uHash;
+ int i;
+// assert( p->nWordsTotal <= 128 );
+ uHash = 0;
+ pSims = Ssw_ObjSim(p, pObj->Id);
+ for ( i = p->nWordsPref; i < p->nWordsTotal; i++ )
+ uHash ^= pSims[i] * s_SPrimes[i & 0x7F];
+ return uHash;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if simulation info is composed of all zeros.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_SmlObjIsConstWord( Ssw_Sml_t * p, Aig_Obj_t * pObj )
+{
+ unsigned * pSims;
+ int i;
+ pSims = Ssw_ObjSim(p, pObj->Id);
+ for ( i = p->nWordsPref; i < p->nWordsTotal; i++ )
+ if ( pSims[i] )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if simulation infos are equal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_SmlObjsAreEqualWord( Ssw_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
+{
+ unsigned * pSims0, * pSims1;
+ int i;
+ pSims0 = Ssw_ObjSim(p, pObj0->Id);
+ pSims1 = Ssw_ObjSim(p, pObj1->Id);
+ for ( i = p->nWordsPref; i < p->nWordsTotal; i++ )
+ if ( pSims0[i] != pSims1[i] )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the node appears to be constant 1 candidate.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_SmlObjIsConstBit( void * p, Aig_Obj_t * pObj )
+{
+ return pObj->fPhase == pObj->fMarkB;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the nodes appear equal.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_SmlObjsAreEqualBit( void * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 )
+{
+ return (pObj0->fPhase == pObj1->fPhase) == (pObj0->fMarkB == pObj1->fMarkB);
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of 1s in the XOR of simulation data.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_SmlNodeNotEquWeight( Ssw_Sml_t * p, int Left, int Right )
+{
+ unsigned * pSimL, * pSimR;
+ int k, Counter = 0;
+ pSimL = Ssw_ObjSim( p, Left );
+ pSimR = Ssw_ObjSim( p, Right );
+ for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
+ Counter += Aig_WordCountOnes( pSimL[k] ^ pSimR[k] );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks implication.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_SmlCheckXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand )
+{
+ unsigned * pSimLi, * pSimLo, * pSimCand;
+ int k;
+ assert( pObjLo->fPhase == 0 );
+ // pObjLi->fPhase may be 1, but the LI simulation data is not complemented!
+ pSimCand = Ssw_ObjSim( p, Aig_Regular(pCand)->Id );
+ pSimLi = Ssw_ObjSim( p, pObjLi->Id );
+ pSimLo = Ssw_ObjSim( p, pObjLo->Id );
+ if ( Aig_Regular(pCand)->fPhase ^ Aig_IsComplement(pCand) )
+ {
+ for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
+ if ( ~pSimCand[k] & (pSimLi[k] ^ pSimLo[k]) )
+ return 0;
+ }
+ else
+ {
+ for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
+ if ( pSimCand[k] & (pSimLi[k] ^ pSimLo[k]) )
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of 1s in the implication.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_SmlCountXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand )
+{
+ unsigned * pSimLi, * pSimLo, * pSimCand;
+ int k, Counter = 0;
+ assert( pObjLo->fPhase == 0 );
+ // pObjLi->fPhase may be 1, but the LI simulation data is not complemented!
+ pSimCand = Ssw_ObjSim( p, Aig_Regular(pCand)->Id );
+ pSimLi = Ssw_ObjSim( p, pObjLi->Id );
+ pSimLo = Ssw_ObjSim( p, pObjLo->Id );
+ if ( Aig_Regular(pCand)->fPhase ^ Aig_IsComplement(pCand) )
+ {
+ for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
+ Counter += Aig_WordCountOnes(~pSimCand[k] & ~(pSimLi[k] ^ pSimLo[k]));
+ }
+ else
+ {
+ for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
+ Counter += Aig_WordCountOnes(pSimCand[k] & ~(pSimLi[k] ^ pSimLo[k]));
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of 1s in the implication.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_SmlCountEqual( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo )
+{
+ unsigned * pSimLi, * pSimLo;
+ int k, Counter = 0;
+ assert( pObjLo->fPhase == 0 );
+ // pObjLi->fPhase may be 1, but the LI simulation data is not complemented!
+ pSimLi = Ssw_ObjSim( p, pObjLi->Id );
+ pSimLo = Ssw_ObjSim( p, pObjLo->Id );
+ for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
+ Counter += Aig_WordCountOnes( ~(pSimLi[k] ^ pSimLo[k]) );
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if simulation info is composed of all zeros.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_SmlNodeIsZero( Ssw_Sml_t * p, Aig_Obj_t * pObj )
+{
+ unsigned * pSims;
+ int i;
+ pSims = Ssw_ObjSim(p, pObj->Id);
+ for ( i = p->nWordsPref; i < p->nWordsTotal; i++ )
+ if ( pSims[i] )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if simulation info is composed of all zeros.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_SmlNodeIsZeroFrame( Ssw_Sml_t * p, Aig_Obj_t * pObj, int f )
+{
+ unsigned * pSims = Ssw_ObjSim(p, pObj->Id);
+ return pSims[f] == 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of one's in the patten the object.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_SmlNodeCountOnesReal( Ssw_Sml_t * p, Aig_Obj_t * pObj )
+{
+ unsigned * pSims;
+ int i, Counter = 0;
+ pSims = Ssw_ObjSim(p, Aig_Regular(pObj)->Id);
+ if ( Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) )
+ {
+ for ( i = 0; i < p->nWordsTotal; i++ )
+ Counter += Aig_WordCountOnes( ~pSims[i] );
+ }
+ else
+ {
+ for ( i = 0; i < p->nWordsTotal; i++ )
+ Counter += Aig_WordCountOnes( pSims[i] );
+ }
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Counts the number of one's in the patten the object.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_SmlNodeCountOnesRealVec( Ssw_Sml_t * p, Vec_Ptr_t * vObjs )
+{
+ Aig_Obj_t * pObj;
+ unsigned * pSims, uWord;
+ int i, k, Counter = 0;
+ if ( Vec_PtrSize(vObjs) == 0 )
+ return 0;
+ for ( i = 0; i < p->nWordsTotal; i++ )
+ {
+ uWord = 0;
+ Vec_PtrForEachEntry( Aig_Obj_t *, vObjs, pObj, k )
+ {
+ pSims = Ssw_ObjSim(p, Aig_Regular(pObj)->Id);
+ if ( Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) )
+ uWord |= ~pSims[i];
+ else
+ uWord |= pSims[i];
+ }
+ Counter += Aig_WordCountOnes( uWord );
+ }
+ return Counter;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Generated const 0 pattern.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlSavePattern0( Ssw_Man_t * p, int fInit )
+{
+ memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords );
+}
+
+/**Function*************************************************************
+
+ Synopsis [[Generated const 1 pattern.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlSavePattern1( Ssw_Man_t * p, int fInit )
+{
+ Aig_Obj_t * pObj;
+ int i, k, nTruePis;
+ memset( p->pPatWords, 0xff, sizeof(unsigned) * p->nPatWords );
+ if ( !fInit )
+ return;
+ // clear the state bits to correspond to all-0 initial state
+ nTruePis = Saig_ManPiNum(p->pAig);
+ k = 0;
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ Abc_InfoXorBit( p->pPatWords, nTruePis * p->nFrames + k++ );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Creates the counter-example from the successful pattern.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int * Ssw_SmlCheckOutputSavePattern( Ssw_Sml_t * p, Aig_Obj_t * pObjPo )
+{
+ Aig_Obj_t * pFanin, * pObjPi;
+ unsigned * pSims;
+ int i, k, BestPat, * pModel;
+ // find the word of the pattern
+ pFanin = Aig_ObjFanin0(pObjPo);
+ pSims = Ssw_ObjSim(p, pFanin->Id);
+ for ( i = 0; i < p->nWordsTotal; i++ )
+ if ( pSims[i] )
+ break;
+ assert( i < p->nWordsTotal );
+ // find the bit of the pattern
+ for ( k = 0; k < 32; k++ )
+ if ( pSims[i] & (1 << k) )
+ break;
+ assert( k < 32 );
+ // determine the best pattern
+ BestPat = i * 32 + k;
+ // fill in the counter-example data
+ pModel = ABC_ALLOC( int, Aig_ManPiNum(p->pAig)+1 );
+ Aig_ManForEachPi( p->pAig, pObjPi, i )
+ {
+ pModel[i] = Abc_InfoHasBit(Ssw_ObjSim(p, pObjPi->Id), BestPat);
+// printf( "%d", pModel[i] );
+ }
+ pModel[Aig_ManPiNum(p->pAig)] = pObjPo->Id;
+// printf( "\n" );
+ return pModel;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the one of the output is already non-constant 0.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int * Ssw_SmlCheckOutput( Ssw_Sml_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ // make sure the reference simulation pattern does not detect the bug
+ pObj = Aig_ManPo( p->pAig, 0 );
+ assert( Aig_ObjFanin0(pObj)->fPhase == (unsigned)Aig_ObjFaninC0(pObj) );
+ Aig_ManForEachPo( p->pAig, pObj, i )
+ {
+ if ( !Ssw_SmlObjIsConstWord( p, Aig_ObjFanin0(pObj) ) )
+ {
+ // create the counter-example from this pattern
+ return Ssw_SmlCheckOutputSavePattern( p, pObj );
+ }
+ }
+ return NULL;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Assigns random patterns to the PI node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlAssignRandom( Ssw_Sml_t * p, Aig_Obj_t * pObj )
+{
+ unsigned * pSims;
+ int i, f;
+ assert( Aig_ObjIsPi(pObj) );
+ pSims = Ssw_ObjSim( p, pObj->Id );
+ for ( i = 0; i < p->nWordsTotal; i++ )
+ pSims[i] = Ssw_ObjRandomSim();
+ // set the first bit 0 in each frame
+ assert( p->nWordsFrame * p->nFrames == p->nWordsTotal );
+ for ( f = 0; f < p->nFrames; f++ )
+ pSims[p->nWordsFrame*f] <<= 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Assigns random patterns to the PI node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlAssignRandomFrame( Ssw_Sml_t * p, Aig_Obj_t * pObj, int iFrame )
+{
+ unsigned * pSims;
+ int i;
+ assert( iFrame < p->nFrames );
+ assert( Aig_ObjIsPi(pObj) );
+ pSims = Ssw_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame;
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = Ssw_ObjRandomSim();
+}
+
+/**Function*************************************************************
+
+ Synopsis [Assigns constant patterns to the PI node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlObjAssignConst( Ssw_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame )
+{
+ unsigned * pSims;
+ int i;
+ assert( iFrame < p->nFrames );
+ assert( Aig_ObjIsPi(pObj) );
+ pSims = Ssw_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame;
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = fConst1? ~(unsigned)0 : 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Assigns constant patterns to the PI node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlObjAssignConstWord( Ssw_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame, int iWord )
+{
+ unsigned * pSims;
+ assert( iFrame < p->nFrames );
+ assert( iWord < p->nWordsFrame );
+ assert( Aig_ObjIsPi(pObj) );
+ pSims = Ssw_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame;
+ pSims[iWord] = fConst1? ~(unsigned)0 : 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Assigns constant patterns to the PI node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlObjSetWord( Ssw_Sml_t * p, Aig_Obj_t * pObj, unsigned Word, int iWord, int iFrame )
+{
+ unsigned * pSims;
+ assert( iFrame < p->nFrames );
+ assert( Aig_ObjIsPi(pObj) );
+ pSims = Ssw_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame;
+ pSims[iWord] = Word;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Assings distance-1 simulation info for the PIs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlAssignDist1( Ssw_Sml_t * p, unsigned * pPat )
+{
+ Aig_Obj_t * pObj;
+ int f, i, k, Limit, nTruePis;
+ assert( p->nFrames > 0 );
+ if ( p->nFrames == 1 )
+ {
+ // copy the PI info
+ Aig_ManForEachPi( p->pAig, pObj, i )
+ Ssw_SmlObjAssignConst( p, pObj, Abc_InfoHasBit(pPat, i), 0 );
+ // flip one bit
+ Limit = Abc_MinInt( Aig_ManPiNum(p->pAig), p->nWordsTotal * 32 - 1 );
+ for ( i = 0; i < Limit; i++ )
+ Abc_InfoXorBit( Ssw_ObjSim( p, Aig_ManPi(p->pAig,i)->Id ), i+1 );
+ }
+ else
+ {
+ int fUseDist1 = 0;
+
+ // copy the PI info for each frame
+ nTruePis = Aig_ManPiNum(p->pAig) - Aig_ManRegNum(p->pAig);
+ for ( f = 0; f < p->nFrames; f++ )
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ Ssw_SmlObjAssignConst( p, pObj, Abc_InfoHasBit(pPat, nTruePis * f + i), f );
+ // copy the latch info
+ k = 0;
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ Ssw_SmlObjAssignConst( p, pObj, Abc_InfoHasBit(pPat, nTruePis * p->nFrames + k++), 0 );
+// assert( p->pFrames == NULL || nTruePis * p->nFrames + k == Aig_ManPiNum(p->pFrames) );
+
+ // flip one bit of the last frame
+ if ( fUseDist1 ) //&& p->nFrames == 2 )
+ {
+ Limit = Abc_MinInt( nTruePis, p->nWordsFrame * 32 - 1 );
+ for ( i = 0; i < Limit; i++ )
+ Abc_InfoXorBit( Ssw_ObjSim( p, Aig_ManPi(p->pAig, i)->Id ) + p->nWordsFrame*(p->nFrames-1), i+1 );
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Assings distance-1 simulation info for the PIs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlAssignDist1Plus( Ssw_Sml_t * p, unsigned * pPat )
+{
+ Aig_Obj_t * pObj;
+ int f, i, Limit;
+ assert( p->nFrames > 0 );
+
+ // copy the pattern into the primary inputs
+ Aig_ManForEachPi( p->pAig, pObj, i )
+ Ssw_SmlObjAssignConst( p, pObj, Abc_InfoHasBit(pPat, i), 0 );
+
+ // set distance one PIs for the first frame
+ Limit = Abc_MinInt( Saig_ManPiNum(p->pAig), p->nWordsFrame * 32 - 1 );
+ for ( i = 0; i < Limit; i++ )
+ Abc_InfoXorBit( Ssw_ObjSim( p, Aig_ManPi(p->pAig, i)->Id ), i+1 );
+
+ // create random info for the remaining timeframes
+ for ( f = 1; f < p->nFrames; f++ )
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ Ssw_SmlAssignRandomFrame( p, pObj, f );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlNodeSimulate( Ssw_Sml_t * p, Aig_Obj_t * pObj, int iFrame )
+{
+ unsigned * pSims, * pSims0, * pSims1;
+ int fCompl, fCompl0, fCompl1, i;
+ assert( iFrame < p->nFrames );
+ assert( !Aig_IsComplement(pObj) );
+ assert( Aig_ObjIsNode(pObj) );
+ assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal );
+ // get hold of the simulation information
+ pSims = Ssw_ObjSim(p, pObj->Id) + p->nWordsFrame * iFrame;
+ pSims0 = Ssw_ObjSim(p, Aig_ObjFanin0(pObj)->Id) + p->nWordsFrame * iFrame;
+ pSims1 = Ssw_ObjSim(p, Aig_ObjFanin1(pObj)->Id) + p->nWordsFrame * iFrame;
+ // get complemented attributes of the children using their random info
+ fCompl = pObj->fPhase;
+ fCompl0 = Aig_ObjPhaseReal(Aig_ObjChild0(pObj));
+ fCompl1 = Aig_ObjPhaseReal(Aig_ObjChild1(pObj));
+ // simulate
+ if ( fCompl0 && fCompl1 )
+ {
+ if ( fCompl )
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = (pSims0[i] | pSims1[i]);
+ else
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = ~(pSims0[i] | pSims1[i]);
+ }
+ else if ( fCompl0 && !fCompl1 )
+ {
+ if ( fCompl )
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = (pSims0[i] | ~pSims1[i]);
+ else
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = (~pSims0[i] & pSims1[i]);
+ }
+ else if ( !fCompl0 && fCompl1 )
+ {
+ if ( fCompl )
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = (~pSims0[i] | pSims1[i]);
+ else
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = (pSims0[i] & ~pSims1[i]);
+ }
+ else // if ( !fCompl0 && !fCompl1 )
+ {
+ if ( fCompl )
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = ~(pSims0[i] & pSims1[i]);
+ else
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = (pSims0[i] & pSims1[i]);
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_SmlNodesCompareInFrame( Ssw_Sml_t * p, Aig_Obj_t * pObj0, Aig_Obj_t * pObj1, int iFrame0, int iFrame1 )
+{
+ unsigned * pSims0, * pSims1;
+ int i;
+ assert( iFrame0 < p->nFrames );
+ assert( iFrame1 < p->nFrames );
+ assert( !Aig_IsComplement(pObj0) );
+ assert( !Aig_IsComplement(pObj1) );
+ assert( iFrame0 == 0 || p->nWordsFrame < p->nWordsTotal );
+ assert( iFrame1 == 0 || p->nWordsFrame < p->nWordsTotal );
+ // get hold of the simulation information
+ pSims0 = Ssw_ObjSim(p, pObj0->Id) + p->nWordsFrame * iFrame0;
+ pSims1 = Ssw_ObjSim(p, pObj1->Id) + p->nWordsFrame * iFrame1;
+ // compare
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ if ( pSims0[i] != pSims1[i] )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlNodeCopyFanin( Ssw_Sml_t * p, Aig_Obj_t * pObj, int iFrame )
+{
+ unsigned * pSims, * pSims0;
+ int fCompl, fCompl0, i;
+ assert( iFrame < p->nFrames );
+ assert( !Aig_IsComplement(pObj) );
+ assert( Aig_ObjIsPo(pObj) );
+ assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal );
+ // get hold of the simulation information
+ pSims = Ssw_ObjSim(p, pObj->Id) + p->nWordsFrame * iFrame;
+ pSims0 = Ssw_ObjSim(p, Aig_ObjFanin0(pObj)->Id) + p->nWordsFrame * iFrame;
+ // get complemented attributes of the children using their random info
+ fCompl = pObj->fPhase;
+ fCompl0 = Aig_ObjPhaseReal(Aig_ObjChild0(pObj));
+ // copy information as it is
+ if ( fCompl0 )
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = ~pSims0[i];
+ else
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = pSims0[i];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlNodeTransferNext( Ssw_Sml_t * p, Aig_Obj_t * pOut, Aig_Obj_t * pIn, int iFrame )
+{
+ unsigned * pSims0, * pSims1;
+ int i;
+ assert( iFrame < p->nFrames );
+ assert( !Aig_IsComplement(pOut) );
+ assert( !Aig_IsComplement(pIn) );
+ assert( Aig_ObjIsPo(pOut) );
+ assert( Aig_ObjIsPi(pIn) );
+ assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal );
+ // get hold of the simulation information
+ pSims0 = Ssw_ObjSim(p, pOut->Id) + p->nWordsFrame * iFrame;
+ pSims1 = Ssw_ObjSim(p, pIn->Id) + p->nWordsFrame * (iFrame+1);
+ // copy information as it is
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims1[i] = pSims0[i];
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates one node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlNodeTransferFirst( Ssw_Sml_t * p, Aig_Obj_t * pOut, Aig_Obj_t * pIn )
+{
+ unsigned * pSims0, * pSims1;
+ int i;
+ assert( !Aig_IsComplement(pOut) );
+ assert( !Aig_IsComplement(pIn) );
+ assert( Aig_ObjIsPo(pOut) );
+ assert( Aig_ObjIsPi(pIn) );
+ assert( p->nWordsFrame < p->nWordsTotal );
+ // get hold of the simulation information
+ pSims0 = Ssw_ObjSim(p, pOut->Id) + p->nWordsFrame * (p->nFrames-1);
+ pSims1 = Ssw_ObjSim(p, pIn->Id);
+ // copy information as it is
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims1[i] = pSims0[i];
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Assings random simulation info for the PIs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlInitialize( Ssw_Sml_t * p, int fInit )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ if ( fInit )
+ {
+ assert( Aig_ManRegNum(p->pAig) > 0 );
+ assert( Aig_ManRegNum(p->pAig) <= Aig_ManPiNum(p->pAig) );
+ // assign random info for primary inputs
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ Ssw_SmlAssignRandom( p, pObj );
+ // assign the initial state for the latches
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ Ssw_SmlObjAssignConst( p, pObj, 0, 0 );
+ }
+ else
+ {
+ Aig_ManForEachPi( p->pAig, pObj, i )
+ Ssw_SmlAssignRandom( p, pObj );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Assings random simulation info for the PIs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlInitializeSpecial( Ssw_Sml_t * p, Vec_Int_t * vInit )
+{
+ Aig_Obj_t * pObj;
+ int Entry, i, nRegs;
+ nRegs = Aig_ManRegNum(p->pAig);
+ assert( nRegs > 0 );
+ assert( nRegs <= Aig_ManPiNum(p->pAig) );
+ assert( Vec_IntSize(vInit) == nRegs * p->nWordsFrame );
+ // assign random info for primary inputs
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ Ssw_SmlAssignRandom( p, pObj );
+ // assign the initial state for the latches
+ Vec_IntForEachEntry( vInit, Entry, i )
+ Ssw_SmlObjAssignConstWord( p, Saig_ManLo(p->pAig, i % nRegs), Entry, 0, i / nRegs );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Assings random simulation info for the PIs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlReinitialize( Ssw_Sml_t * p )
+{
+ Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+ int i;
+ assert( Aig_ManRegNum(p->pAig) > 0 );
+ assert( Aig_ManRegNum(p->pAig) < Aig_ManPiNum(p->pAig) );
+ // assign random info for primary inputs
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ Ssw_SmlAssignRandom( p, pObj );
+ // copy simulation info into the inputs
+ Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+ Ssw_SmlNodeTransferFirst( p, pObjLi, pObjLo );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Check if any of the POs becomes non-constant.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_SmlCheckNonConstOutputs( Ssw_Sml_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Saig_ManForEachPo( p->pAig, pObj, i )
+ {
+ if ( p->pAig->nConstrs && i >= Saig_ManPoNum(p->pAig) - p->pAig->nConstrs )
+ return 0;
+ if ( !Ssw_SmlNodeIsZero(p, pObj) )
+ return 1;
+ }
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates AIG manager.]
+
+ Description [Assumes that the PI simulation info is attached.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlSimulateOne( Ssw_Sml_t * p )
+{
+ Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+ int f, i, clk;
+clk = clock();
+ for ( f = 0; f < p->nFrames; f++ )
+ {
+ // simulate the nodes
+ Aig_ManForEachNode( p->pAig, pObj, i )
+ Ssw_SmlNodeSimulate( p, pObj, f );
+ // copy simulation info into outputs
+ Saig_ManForEachPo( p->pAig, pObj, i )
+ Ssw_SmlNodeCopyFanin( p, pObj, f );
+ // copy simulation info into outputs
+ Saig_ManForEachLi( p->pAig, pObj, i )
+ Ssw_SmlNodeCopyFanin( p, pObj, f );
+ // quit if this is the last timeframe
+ if ( f == p->nFrames - 1 )
+ break;
+ // copy simulation info into the inputs
+ Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+ Ssw_SmlNodeTransferNext( p, pObjLi, pObjLo, f );
+ }
+p->timeSim += clock() - clk;
+p->nSimRounds++;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts simulation information to be not normallized.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlUnnormalize( Ssw_Sml_t * p )
+{
+ Aig_Obj_t * pObj;
+ unsigned * pSims;
+ int i, k;
+ // convert constant 1
+ pSims = Ssw_ObjSim( p, 0 );
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = ~pSims[i];
+ // convert internal nodes
+ Aig_ManForEachNode( p->pAig, pObj, k )
+ {
+ if ( pObj->fPhase == 0 )
+ continue;
+ pSims = Ssw_ObjSim( p, pObj->Id );
+ for ( i = 0; i < p->nWordsFrame; i++ )
+ pSims[i] = ~pSims[i];
+ }
+ // PIs/POs are always stored in their natural state
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates AIG manager.]
+
+ Description [Assumes that the PI simulation info is attached.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlSimulateOneDyn_rec( Ssw_Sml_t * p, Aig_Obj_t * pObj, int f, int * pVisited, int nVisCounter )
+{
+// if ( Aig_ObjIsTravIdCurrent(p->pAig, pObj) )
+// return;
+// Aig_ObjSetTravIdCurrent(p->pAig, pObj);
+ if ( pVisited[p->nFrames*pObj->Id+f] == nVisCounter )
+ return;
+ pVisited[p->nFrames*pObj->Id+f] = nVisCounter;
+ if ( Saig_ObjIsPi( p->pAig, pObj ) || Aig_ObjIsConst1(pObj) )
+ return;
+ if ( Saig_ObjIsLo( p->pAig, pObj ) )
+ {
+ if ( f == 0 )
+ return;
+ Ssw_SmlSimulateOneDyn_rec( p, Saig_ObjLoToLi(p->pAig, pObj), f-1, pVisited, nVisCounter );
+ Ssw_SmlNodeTransferNext( p, Saig_ObjLoToLi(p->pAig, pObj), pObj, f-1 );
+ return;
+ }
+ if ( Saig_ObjIsLi( p->pAig, pObj ) )
+ {
+ Ssw_SmlSimulateOneDyn_rec( p, Aig_ObjFanin0(pObj), f, pVisited, nVisCounter );
+ Ssw_SmlNodeCopyFanin( p, pObj, f );
+ return;
+ }
+ assert( Aig_ObjIsNode(pObj) );
+ Ssw_SmlSimulateOneDyn_rec( p, Aig_ObjFanin0(pObj), f, pVisited, nVisCounter );
+ Ssw_SmlSimulateOneDyn_rec( p, Aig_ObjFanin1(pObj), f, pVisited, nVisCounter );
+ Ssw_SmlNodeSimulate( p, pObj, f );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Simulates AIG manager.]
+
+ Description [Assumes that the PI simulation info is attached.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlSimulateOneFrame( Ssw_Sml_t * p )
+{
+ Aig_Obj_t * pObj, * pObjLi, * pObjLo;
+ int i, clk;
+clk = clock();
+ // simulate the nodes
+ Aig_ManForEachNode( p->pAig, pObj, i )
+ Ssw_SmlNodeSimulate( p, pObj, 0 );
+ // copy simulation info into outputs
+ Saig_ManForEachLi( p->pAig, pObj, i )
+ Ssw_SmlNodeCopyFanin( p, pObj, 0 );
+ // copy simulation info into the inputs
+ Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+ Ssw_SmlNodeTransferNext( p, pObjLi, pObjLo, 0 );
+p->timeSim += clock() - clk;
+p->nSimRounds++;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Allocates simulation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ssw_Sml_t * Ssw_SmlStart( Aig_Man_t * pAig, int nPref, int nFrames, int nWordsFrame )
+{
+ Ssw_Sml_t * p;
+ p = (Ssw_Sml_t *)ABC_ALLOC( char, sizeof(Ssw_Sml_t) + sizeof(unsigned) * Aig_ManObjNumMax(pAig) * (nPref + nFrames) * nWordsFrame );
+ memset( p, 0, sizeof(Ssw_Sml_t) + sizeof(unsigned) * (nPref + nFrames) * nWordsFrame );
+ p->pAig = pAig;
+ p->nPref = nPref;
+ p->nFrames = nPref + nFrames;
+ p->nWordsFrame = nWordsFrame;
+ p->nWordsTotal = (nPref + nFrames) * nWordsFrame;
+ p->nWordsPref = nPref * nWordsFrame;
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Allocates simulation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlClean( Ssw_Sml_t * p )
+{
+ memset( p->pData, 0, sizeof(unsigned) * Aig_ManObjNumMax(p->pAig) * p->nWordsTotal );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Get simulation data.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Ptr_t * Ssw_SmlSimDataPointers( Ssw_Sml_t * p )
+{
+ Vec_Ptr_t * vSimInfo;
+ Aig_Obj_t * pObj;
+ int i;
+ vSimInfo = Vec_PtrStart( Aig_ManObjNumMax(p->pAig) );
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ Vec_PtrWriteEntry( vSimInfo, i, Ssw_ObjSim(p, i) );
+ return vSimInfo;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Deallocates simulation manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlStop( Ssw_Sml_t * p )
+{
+ ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs simulation of the uninitialized circuit.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ssw_Sml_t * Ssw_SmlSimulateComb( Aig_Man_t * pAig, int nWords )
+{
+ Ssw_Sml_t * p;
+ p = Ssw_SmlStart( pAig, 0, 1, nWords );
+ Ssw_SmlInitialize( p, 0 );
+ Ssw_SmlSimulateOne( p );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs simulation of the initialized circuit.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ssw_Sml_t * Ssw_SmlSimulateSeq( Aig_Man_t * pAig, int nPref, int nFrames, int nWords )
+{
+ Ssw_Sml_t * p;
+ p = Ssw_SmlStart( pAig, nPref, nFrames, nWords );
+ Ssw_SmlInitialize( p, 1 );
+ Ssw_SmlSimulateOne( p );
+ p->fNonConstOut = Ssw_SmlCheckNonConstOutputs( p );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs next round of sequential simulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlResimulateSeq( Ssw_Sml_t * p )
+{
+ Ssw_SmlReinitialize( p );
+ Ssw_SmlSimulateOne( p );
+ p->fNonConstOut = Ssw_SmlCheckNonConstOutputs( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of frames simulated in the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_SmlNumFrames( Ssw_Sml_t * p )
+{
+ return p->nFrames;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the total number of simulation words.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_SmlNumWordsTotal( Ssw_Sml_t * p )
+{
+ return p->nWordsTotal;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the pointer to the simulation info of the node.]
+
+ Description [The simulation info is normalized unless procedure
+ Ssw_SmlUnnormalize() is called in advance.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+unsigned * Ssw_SmlSimInfo( Ssw_Sml_t * p, Aig_Obj_t * pObj )
+{
+ assert( !Aig_IsComplement(pObj) );
+ return Ssw_ObjSim( p, pObj->Id );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Creates sequential counter-example from the simulation info.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Cex_t * Ssw_SmlGetCounterExample( Ssw_Sml_t * p )
+{
+ Abc_Cex_t * pCex;
+ Aig_Obj_t * pObj;
+ unsigned * pSims;
+ int iPo, iFrame, iBit, i, k;
+
+ // make sure the simulation manager has it
+ assert( p->fNonConstOut );
+
+ // find the first output that failed
+ iPo = -1;
+ iBit = -1;
+ iFrame = -1;
+ Saig_ManForEachPo( p->pAig, pObj, iPo )
+ {
+ if ( Ssw_SmlNodeIsZero(p, pObj) )
+ continue;
+ pSims = Ssw_ObjSim( p, pObj->Id );
+ for ( i = p->nWordsPref; i < p->nWordsTotal; i++ )
+ if ( pSims[i] )
+ {
+ iFrame = i / p->nWordsFrame;
+ iBit = 32 * (i % p->nWordsFrame) + Aig_WordFindFirstBit( pSims[i] );
+ break;
+ }
+ break;
+ }
+ assert( iPo < Aig_ManPoNum(p->pAig)-Aig_ManRegNum(p->pAig) );
+ assert( iFrame < p->nFrames );
+ assert( iBit < 32 * p->nWordsFrame );
+
+ // allocate the counter example
+ pCex = Abc_CexAlloc( Aig_ManRegNum(p->pAig), Aig_ManPiNum(p->pAig) - Aig_ManRegNum(p->pAig), iFrame + 1 );
+ pCex->iPo = iPo;
+ pCex->iFrame = iFrame;
+
+ // copy the bit data
+ Saig_ManForEachLo( p->pAig, pObj, k )
+ {
+ pSims = Ssw_ObjSim( p, pObj->Id );
+ if ( Abc_InfoHasBit( pSims, iBit ) )
+ Abc_InfoSetBit( pCex->pData, k );
+ }
+ for ( i = 0; i <= iFrame; i++ )
+ {
+ Saig_ManForEachPi( p->pAig, pObj, k )
+ {
+ pSims = Ssw_ObjSim( p, pObj->Id );
+ if ( Abc_InfoHasBit( pSims, 32 * p->nWordsFrame * i + iBit ) )
+ Abc_InfoSetBit( pCex->pData, pCex->nRegs + pCex->nPis * i + k );
+ }
+ }
+ // verify the counter example
+ if ( !Saig_ManVerifyCex( p->pAig, pCex ) )
+ {
+ printf( "Ssw_SmlGetCounterExample(): Counter-example is invalid.\n" );
+ Abc_CexFree( pCex );
+ pCex = NULL;
+ }
+ return pCex;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/ssw/sswSimSat.c b/src/proof/ssw/sswSimSat.c
new file mode 100644
index 00000000..4c094a2d
--- /dev/null
+++ b/src/proof/ssw/sswSimSat.c
@@ -0,0 +1,123 @@
+/**CFile****************************************************************
+
+ FileName [sswSimSat.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Inductive prover with constraints.]
+
+ Synopsis [Performs resimulation using counter-examples.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 1, 2008.]
+
+ Revision [$Id: sswSimSat.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Handle the counter-example.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ManResimulateBit( Ssw_Man_t * p, Aig_Obj_t * pCand, Aig_Obj_t * pRepr )
+{
+ Aig_Obj_t * pObj;
+ int i, RetValue1, RetValue2, clk = clock();
+ // set the PI simulation information
+ Aig_ManConst1(p->pAig)->fMarkB = 1;
+ Aig_ManForEachPi( p->pAig, pObj, i )
+ pObj->fMarkB = Abc_InfoHasBit( p->pPatWords, i );
+ // simulate internal nodes
+ Aig_ManForEachNode( p->pAig, pObj, i )
+ pObj->fMarkB = ( Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj) )
+ & ( Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj) );
+ // if repr is given, perform refinement
+ if ( pRepr )
+ {
+ // check equivalence classes
+ RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 0 );
+ RetValue2 = Ssw_ClassesRefine( p->ppClasses, 0 );
+ // make sure refinement happened
+ if ( Aig_ObjIsConst1(pRepr) )
+ {
+ assert( RetValue1 );
+ if ( RetValue1 == 0 )
+ printf( "\nSsw_ManResimulateBit() Error: RetValue1 does not hold.\n" );
+ }
+ else
+ {
+ assert( RetValue2 );
+ if ( RetValue2 == 0 )
+ printf( "\nSsw_ManResimulateBit() Error: RetValue2 does not hold.\n" );
+ }
+ }
+p->timeSimSat += clock() - clk;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Handle the counter-example.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ManResimulateWord( Ssw_Man_t * p, Aig_Obj_t * pCand, Aig_Obj_t * pRepr, int f )
+{
+ int RetValue1, RetValue2, clk = clock();
+ // set the PI simulation information
+ Ssw_SmlAssignDist1Plus( p->pSml, p->pPatWords );
+ // simulate internal nodes
+ Ssw_SmlSimulateOne( p->pSml );
+ // check equivalence classes
+ RetValue1 = Ssw_ClassesRefineConst1( p->ppClasses, 1 );
+ RetValue2 = Ssw_ClassesRefine( p->ppClasses, 1 );
+ // make sure refinement happened
+ if ( Aig_ObjIsConst1(pRepr) )
+ {
+ assert( RetValue1 );
+ if ( RetValue1 == 0 )
+ printf( "\nSsw_ManResimulateWord() Error: RetValue1 does not hold.\n" );
+ }
+ else
+ {
+ assert( RetValue2 );
+ if ( RetValue2 == 0 )
+ printf( "\nSsw_ManResimulateWord() Error: RetValue2 does not hold.\n" );
+ }
+p->timeSimSat += clock() - clk;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/ssw/sswSweep.c b/src/proof/ssw/sswSweep.c
new file mode 100644
index 00000000..e2a4f65d
--- /dev/null
+++ b/src/proof/ssw/sswSweep.c
@@ -0,0 +1,435 @@
+/**CFile****************************************************************
+
+ FileName [sswSweep.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Inductive prover with constraints.]
+
+ Synopsis [One round of SAT sweeping.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 1, 2008.]
+
+ Revision [$Id: sswSweep.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+#include "src/misc/bar/bar.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Retrives value of the PI in the original AIG.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ManGetSatVarValue( Ssw_Man_t * p, Aig_Obj_t * pObj, int f )
+{
+ int fUseNoBoundary = 0;
+ Aig_Obj_t * pObjFraig;
+ int Value;
+// assert( Aig_ObjIsPi(pObj) );
+ pObjFraig = Ssw_ObjFrame( p, pObj, f );
+ if ( fUseNoBoundary )
+ {
+ Value = Ssw_CnfGetNodeValue( p->pMSat, Aig_Regular(pObjFraig) );
+ Value ^= Aig_IsComplement(pObjFraig);
+ }
+ else
+ {
+ int nVarNum = Ssw_ObjSatNum( p->pMSat, Aig_Regular(pObjFraig) );
+ Value = (!nVarNum)? 0 : (Aig_IsComplement(pObjFraig) ^ sat_solver_var_value( p->pMSat->pSat, nVarNum ));
+ }
+
+// Value = (Aig_IsComplement(pObjFraig) ^ ((!nVarNum)? 0 : sat_solver_var_value( p->pSat, nVarNum )));
+// Value = (!nVarNum)? Aig_ManRandom(0) & 1 : (Aig_IsComplement(pObjFraig) ^ sat_solver_var_value( p->pSat, nVarNum ));
+ if ( p->pPars->fPolarFlip )
+ {
+ if ( Aig_Regular(pObjFraig)->fPhase ) Value ^= 1;
+ }
+ return Value;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging for the internal nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_CheckConstraints( Ssw_Man_t * p )
+{
+ Aig_Obj_t * pObj, * pObj2;
+ int nConstrPairs, i;
+ int Counter = 0;
+ nConstrPairs = Aig_ManPoNum(p->pFrames)-Aig_ManRegNum(p->pAig);
+ assert( (nConstrPairs & 1) == 0 );
+ for ( i = 0; i < nConstrPairs; i += 2 )
+ {
+ pObj = Aig_ManPo( p->pFrames, i );
+ pObj2 = Aig_ManPo( p->pFrames, i+1 );
+ if ( Ssw_NodesAreEquiv( p, Aig_ObjFanin0(pObj), Aig_ObjFanin0(pObj2) ) != 1 )
+ {
+ Ssw_NodesAreConstrained( p, Aig_ObjChild0(pObj), Aig_ObjChild0(pObj2) );
+ Counter++;
+ }
+ }
+ printf( "Total constraints = %d. Added constraints = %d.\n", nConstrPairs/2, Counter );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Copy pattern from the solver into the internal storage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlSavePatternAigPhase( Ssw_Man_t * p, int f )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords );
+ Aig_ManForEachPi( p->pAig, pObj, i )
+ if ( Aig_ObjPhaseReal( Ssw_ObjFrame(p, pObj, f) ) )
+ Abc_InfoSetBit( p->pPatWords, i );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Copy pattern from the solver into the internal storage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlSavePatternAig( Ssw_Man_t * p, int f )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords );
+ Aig_ManForEachPi( p->pAig, pObj, i )
+ if ( Ssw_ManGetSatVarValue( p, pObj, f ) )
+ Abc_InfoSetBit( p->pPatWords, i );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Saves one counter-example into internal storage.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_SmlAddPatternDyn( Ssw_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ unsigned * pInfo;
+ int i, nVarNum;
+ // iterate through the PIs of the frames
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->pMSat->vUsedPis, pObj, i )
+ {
+ assert( Aig_ObjIsPi(pObj) );
+ nVarNum = Ssw_ObjSatNum( p->pMSat, pObj );
+ assert( nVarNum > 0 );
+ if ( sat_solver_var_value( p->pMSat->pSat, nVarNum ) )
+ {
+ pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjPioNum(pObj) );
+ Abc_InfoSetBit( pInfo, p->nPatterns );
+ }
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging for one node.]
+
+ Description [Returns the fraiged node.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ManSweepNode( Ssw_Man_t * p, Aig_Obj_t * pObj, int f, int fBmc, Vec_Int_t * vPairs )
+{
+ Aig_Obj_t * pObjRepr, * pObjFraig, * pObjFraig2, * pObjReprFraig;
+ int RetValue, clk;
+ // get representative of this class
+ pObjRepr = Aig_ObjRepr( p->pAig, pObj );
+ if ( pObjRepr == NULL )
+ return 0;
+ // get the fraiged node
+ pObjFraig = Ssw_ObjFrame( p, pObj, f );
+ // get the fraiged representative
+ pObjReprFraig = Ssw_ObjFrame( p, pObjRepr, f );
+ // check if constant 0 pattern distinquishes these nodes
+ assert( pObjFraig != NULL && pObjReprFraig != NULL );
+ assert( (pObj->fPhase == pObjRepr->fPhase) == (Aig_ObjPhaseReal(pObjFraig) == Aig_ObjPhaseReal(pObjReprFraig)) );
+ // if the fraiged nodes are the same, return
+ if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) )
+ return 0;
+ // add constraints on demand
+ if ( !fBmc && p->pPars->fDynamic )
+ {
+clk = clock();
+ Ssw_ManLoadSolver( p, pObjRepr, pObj );
+ p->nRecycleCalls++;
+p->timeMarkCones += clock() - clk;
+ }
+ // call equivalence checking
+ if ( Aig_Regular(pObjFraig) != Aig_ManConst1(p->pFrames) )
+ RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) );
+ else
+ RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjFraig), Aig_Regular(pObjReprFraig) );
+ if ( RetValue == 1 ) // proved equivalent
+ {
+ pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase );
+ Ssw_ObjSetFrame( p, pObj, f, pObjFraig2 );
+ return 0;
+ }
+ if ( vPairs )
+ {
+ Vec_IntPush( vPairs, pObjRepr->Id );
+ Vec_IntPush( vPairs, pObj->Id );
+ }
+ if ( RetValue == -1 ) // timed out
+ {
+ Ssw_ClassesRemoveNode( p->ppClasses, pObj );
+ return 1;
+ }
+ // disproved the equivalence
+ if ( !fBmc && p->pPars->fDynamic )
+ {
+ Ssw_SmlAddPatternDyn( p );
+ p->nPatterns++;
+ return 1;
+ }
+ else
+ Ssw_SmlSavePatternAig( p, f );
+ if ( !p->pPars->fConstrs )
+ Ssw_ManResimulateWord( p, pObj, pObjRepr, f );
+ else
+ Ssw_ManResimulateBit( p, pObj, pObjRepr );
+ assert( Aig_ObjRepr( p->pAig, pObj ) != pObjRepr );
+ if ( Aig_ObjRepr( p->pAig, pObj ) == pObjRepr )
+ {
+ printf( "Ssw_ManSweepNode(): Failed to refine representative.\n" );
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging for the internal nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ManSweepBmc( Ssw_Man_t * p )
+{
+ Bar_Progress_t * pProgress = NULL;
+ Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo;
+ int i, f, clk;
+clk = clock();
+
+ // start initialized timeframes
+ p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK );
+ Saig_ManForEachLo( p->pAig, pObj, i )
+ Ssw_ObjSetFrame( p, pObj, 0, Aig_ManConst0(p->pFrames) );
+
+ // sweep internal nodes
+ p->fRefined = 0;
+ if ( p->pPars->fVerbose )
+ pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK );
+ for ( f = 0; f < p->pPars->nFramesK; f++ )
+ {
+ // map constants and PIs
+ Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) );
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ Ssw_ObjSetFrame( p, pObj, f, Aig_ObjCreatePi(p->pFrames) );
+ // sweep internal nodes
+ Aig_ManForEachNode( p->pAig, pObj, i )
+ {
+ if ( p->pPars->fVerbose )
+ Bar_ProgressUpdate( pProgress, Aig_ManObjNumMax(p->pAig) * f + i, NULL );
+ pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) );
+ Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+ p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 1, NULL );
+ }
+ // quit if this is the last timeframe
+ if ( f == p->pPars->nFramesK - 1 )
+ break;
+ // transfer latch input to the latch outputs
+ Aig_ManForEachPo( p->pAig, pObj, i )
+ Ssw_ObjSetFrame( p, pObj, f, Ssw_ObjChild0Fra(p, pObj, f) );
+ // build logic cones for register outputs
+ Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
+ {
+ pObjNew = Ssw_ObjFrame( p, pObjLi, f );
+ Ssw_ObjSetFrame( p, pObjLo, f+1, pObjNew );
+ Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pObjNew) );//
+ }
+ }
+ if ( p->pPars->fVerbose )
+ Bar_ProgressStop( pProgress );
+
+ // cleanup
+// Ssw_ClassesCheck( p->ppClasses );
+p->timeBmc += clock() - clk;
+ return p->fRefined;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Generates AIG with the following nodes put into seq miters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_ManDumpEquivMiter( Aig_Man_t * p, Vec_Int_t * vPairs, int Num )
+{
+ FILE * pFile;
+ char pBuffer[16];
+ Aig_Man_t * pNew;
+ sprintf( pBuffer, "equiv%03d.aig", Num );
+ pFile = fopen( pBuffer, "w" );
+ if ( pFile == NULL )
+ {
+ printf( "Cannot open file %s for writing.\n", pBuffer );
+ return;
+ }
+ fclose( pFile );
+ pNew = Saig_ManCreateEquivMiter( p, vPairs );
+ Ioa_WriteAiger( pNew, pBuffer, 0, 0 );
+ Aig_ManStop( pNew );
+ printf( "AIG with %4d disproved equivs is dumped into file \"%s\".\n", Vec_IntSize(vPairs)/2, pBuffer );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs fraiging for the internal nodes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ManSweep( Ssw_Man_t * p )
+{
+ static int Counter;
+ Bar_Progress_t * pProgress = NULL;
+ Aig_Obj_t * pObj, * pObj2, * pObjNew;
+ int nConstrPairs, clk, i, f;
+ Vec_Int_t * vDisproved;
+
+ // perform speculative reduction
+clk = clock();
+ // create timeframes
+ p->pFrames = Ssw_FramesWithClasses( p );
+ // add constants
+ nConstrPairs = Aig_ManPoNum(p->pFrames)-Aig_ManRegNum(p->pAig);
+ assert( (nConstrPairs & 1) == 0 );
+ for ( i = 0; i < nConstrPairs; i += 2 )
+ {
+ pObj = Aig_ManPo( p->pFrames, i );
+ pObj2 = Aig_ManPo( p->pFrames, i+1 );
+ Ssw_NodesAreConstrained( p, Aig_ObjChild0(pObj), Aig_ObjChild0(pObj2) );
+ }
+ // build logic cones for register inputs
+ for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ )
+ {
+ pObj = Aig_ManPo( p->pFrames, nConstrPairs + i );
+ Ssw_CnfNodeAddToSolver( p->pMSat, Aig_ObjFanin0(pObj) );//
+ }
+ sat_solver_simplify( p->pMSat->pSat );
+
+ // map constants and PIs of the last frame
+ f = p->pPars->nFramesK;
+ Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) );
+ Saig_ManForEachPi( p->pAig, pObj, i )
+ Ssw_ObjSetFrame( p, pObj, f, Aig_ObjCreatePi(p->pFrames) );
+p->timeReduce += clock() - clk;
+
+ // sweep internal nodes
+ p->fRefined = 0;
+ Ssw_ClassesClearRefined( p->ppClasses );
+ if ( p->pPars->fVerbose )
+ pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) );
+ vDisproved = p->pPars->fEquivDump? Vec_IntAlloc(1000) : NULL;
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ {
+ if ( p->pPars->fVerbose )
+ Bar_ProgressUpdate( pProgress, i, NULL );
+ if ( Saig_ObjIsLo(p->pAig, pObj) )
+ p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 0, vDisproved );
+ else if ( Aig_ObjIsNode(pObj) )
+ {
+ pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) );
+ Ssw_ObjSetFrame( p, pObj, f, pObjNew );
+ p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 0, vDisproved );
+ }
+ }
+ if ( p->pPars->fVerbose )
+ Bar_ProgressStop( pProgress );
+
+ // cleanup
+// Ssw_ClassesCheck( p->ppClasses );
+ if ( p->pPars->fEquivDump )
+ Ssw_ManDumpEquivMiter( p->pAig, vDisproved, Counter++ );
+ Vec_IntFreeP( &vDisproved );
+ return p->fRefined;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/proof/ssw/sswUnique.c b/src/proof/ssw/sswUnique.c
new file mode 100644
index 00000000..b5f6a853
--- /dev/null
+++ b/src/proof/ssw/sswUnique.c
@@ -0,0 +1,197 @@
+/**CFile****************************************************************
+
+ FileName [sswSat.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Inductive prover with constraints.]
+
+ Synopsis [On-demand uniqueness constraints.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - September 1, 2008.]
+
+ Revision [$Id: sswSat.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sswInt.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Performs computation of signal correspondence with constraints.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ssw_UniqueRegisterPairInfo( Ssw_Man_t * p )
+{
+ Aig_Obj_t * pObjLo, * pObj0, * pObj1;
+ int i, RetValue, Counter;
+ if ( p->vDiffPairs == NULL )
+ p->vDiffPairs = Vec_IntAlloc( Saig_ManRegNum(p->pAig) );
+ Vec_IntClear( p->vDiffPairs );
+ Saig_ManForEachLo( p->pAig, pObjLo, i )
+ {
+ pObj0 = Ssw_ObjFrame( p, pObjLo, 0 );
+ pObj1 = Ssw_ObjFrame( p, pObjLo, 1 );
+ if ( pObj0 == pObj1 )
+ Vec_IntPush( p->vDiffPairs, 0 );
+ else if ( pObj0 == Aig_Not(pObj1) )
+ Vec_IntPush( p->vDiffPairs, 1 );
+// else
+// Vec_IntPush( p->vDiffPairs, 1 );
+ else if ( Aig_ObjPhaseReal(pObj0) != Aig_ObjPhaseReal(pObj1) )
+ Vec_IntPush( p->vDiffPairs, 1 );
+ else
+ {
+ RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObj0), Aig_Regular(pObj1) );
+ Vec_IntPush( p->vDiffPairs, RetValue!=1 );
+ }
+ }
+ assert( Vec_IntSize(p->vDiffPairs) == Saig_ManRegNum(p->pAig) );
+ // count the number of ones
+ Counter = 0;
+ Vec_IntForEachEntry( p->vDiffPairs, RetValue, i )
+ Counter += RetValue;
+// printf( "The number of different register pairs = %d.\n", Counter );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if uniqueness constraints can be added.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ManUniqueOne( Ssw_Man_t * p, Aig_Obj_t * pRepr, Aig_Obj_t * pObj, int fVerbose )
+{
+ Aig_Obj_t * ppObjs[2], * pTemp;
+ int i, k, Value0, Value1, RetValue, fFeasible;
+
+ assert( p->pPars->nFramesK > 1 );
+ assert( p->vDiffPairs && Vec_IntSize(p->vDiffPairs) == Saig_ManRegNum(p->pAig) );
+
+ // compute the first support in terms of LOs
+ ppObjs[0] = pRepr;
+ ppObjs[1] = pObj;
+ Aig_SupportNodes( p->pAig, ppObjs, 2, p->vCommon );
+ // keep only LOs
+ RetValue = Vec_PtrSize( p->vCommon );
+ fFeasible = 0;
+ k = 0;
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vCommon, pTemp, i )
+ {
+ assert( Aig_ObjIsPi(pTemp) );
+ if ( !Saig_ObjIsLo(p->pAig, pTemp) )
+ continue;
+ assert( Aig_ObjPioNum(pTemp) > 0 );
+ Vec_PtrWriteEntry( p->vCommon, k++, pTemp );
+ if ( Vec_IntEntry(p->vDiffPairs, Aig_ObjPioNum(pTemp) - Saig_ManPiNum(p->pAig)) )
+ fFeasible = 1;
+ }
+ Vec_PtrShrink( p->vCommon, k );
+
+ if ( fVerbose )
+ printf( "Node = %5d : Supp = %3d. Regs = %3d. Feasible = %s. ",
+ Aig_ObjId(pObj), RetValue, Vec_PtrSize(p->vCommon),
+ fFeasible? "yes": "no " );
+
+ // check the current values
+ RetValue = 1;
+ Vec_PtrForEachEntry( Aig_Obj_t *, p->vCommon, pTemp, i )
+ {
+ Value0 = Ssw_ManGetSatVarValue( p, pTemp, 0 );
+ Value1 = Ssw_ManGetSatVarValue( p, pTemp, 1 );
+ if ( Value0 != Value1 )
+ RetValue = 0;
+ if ( fVerbose )
+ printf( "%d", Value0 ^ Value1 );
+ }
+ if ( fVerbose )
+ printf( "\n" );
+
+ return RetValue && fFeasible;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns the output of the uniqueness constraint.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ssw_ManUniqueAddConstraint( Ssw_Man_t * p, Vec_Ptr_t * vCommon, int f1, int f2 )
+{
+ Aig_Obj_t * pObj, * pObj1New, * pObj2New, * pMiter, * pTotal;
+ int i, pLits[2];
+// int RetValue;
+ assert( Vec_PtrSize(vCommon) > 0 );
+ // generate the constraint
+ pTotal = Aig_ManConst0(p->pFrames);
+ Vec_PtrForEachEntry( Aig_Obj_t *, vCommon, pObj, i )
+ {
+ assert( Saig_ObjIsLo(p->pAig, pObj) );
+ pObj1New = Ssw_ObjFrame( p, pObj, f1 );
+ pObj2New = Ssw_ObjFrame( p, pObj, f2 );
+ pMiter = Aig_Exor( p->pFrames, pObj1New, pObj2New );
+ pTotal = Aig_Or( p->pFrames, pTotal, pMiter );
+ }
+ if ( Aig_ObjIsConst1(Aig_Regular(pTotal)) )
+ {
+// printf( "Skipped\n" );
+ return 0;
+ }
+ // create CNF
+ Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pTotal) );
+ // add output constraint
+ pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,Aig_Regular(pTotal)), Aig_IsComplement(pTotal) );
+/*
+ RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 1 );
+ assert( RetValue );
+ // simplify the solver
+ if ( p->pSat->qtail != p->pSat->qhead )
+ {
+ RetValue = sat_solver_simplify(p->pSat);
+ assert( RetValue != 0 );
+ }
+*/
+ assert( p->iOutputLit == -1 );
+ p->iOutputLit = pLits[0];
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+