From eb75697fe00a8668f74b3c710dcbf5658e07d167 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 4 Oct 2008 08:01:00 -0700 Subject: [PATCH] Version abc81004 --- abc.dsp | 16 +- src/aig/aig/aig.h | 15 +- src/aig/cec/cecSat.c | 284 +++++++ src/aig/saig/saig.h | 6 +- src/aig/saig/saigMiter.c | 617 ++++++++++++++- src/aig/saig/saigSynch.c | 34 + src/aig/ssw/ssw.h | 3 + src/aig/ssw/sswPart.c | 14 +- src/aig/ssw_old/module.make | 14 + src/aig/ssw_old/ssw.h | 117 +++ src/aig/ssw_old/sswAig.c | 205 +++++ src/aig/ssw_old/sswBmc.c | 315 ++++++++ src/aig/ssw_old/sswClass.c | 941 ++++++++++++++++++++++ src/aig/ssw_old/sswCnf.c | 335 ++++++++ src/aig/ssw_old/sswCore.c | 293 +++++++ src/aig/ssw_old/sswInt.h | 232 ++++++ src/aig/ssw_old/sswLcorr.c | 364 +++++++++ src/aig/ssw_old/sswMan.c | 237 ++++++ src/aig/ssw_old/sswPairs.c | 470 +++++++++++ src/aig/ssw_old/sswPart.c | 129 +++ src/aig/ssw_old/sswSat.c | 264 +++++++ src/aig/ssw_old/sswSim.c | 1334 ++++++++++++++++++++++++++++++++ src/aig/ssw_old/sswSimSat.c | 199 +++++ src/aig/ssw_old/sswSweep.c | 473 +++++++++++ src/aig/ssw_old/sswUnique.c | 290 +++++++ src/base/abci/abc.c | 116 ++- src/base/abci/abc.zip | Bin 0 -> 62408 bytes src/base/abci/abcDar.c | 145 +++- src/base/cmd/cmd.c | 20 +- src/base/cmd/cmd.h | 13 +- src/base/io/io.c | 48 +- src/base/main/mainUtils.c | 18 +- src/misc/extra/extra.h | 36 +- src/sat/bsat/satChecker.c | 187 +++++ src/sat/bsat/satInterA.c | 26 + src/sat/bsat/satInterA_mod.c | 1104 ++++++++++++++++++++++++++ src/sat/bsat/satInterA_old.c | 1047 +++++++++++++++++++++++++ src/sat/bsat/satInterA_yu_hu.c | 87 ++- src/sat/lsat/solver.h | 124 +++ 39 files changed, 10033 insertions(+), 139 deletions(-) create mode 100644 src/aig/cec/cecSat.c create mode 100644 src/aig/ssw_old/module.make create mode 100644 src/aig/ssw_old/ssw.h create mode 100644 src/aig/ssw_old/sswAig.c create mode 100644 src/aig/ssw_old/sswBmc.c create mode 100644 src/aig/ssw_old/sswClass.c create mode 100644 src/aig/ssw_old/sswCnf.c create mode 100644 src/aig/ssw_old/sswCore.c create mode 100644 src/aig/ssw_old/sswInt.h create mode 100644 src/aig/ssw_old/sswLcorr.c create mode 100644 src/aig/ssw_old/sswMan.c create mode 100644 src/aig/ssw_old/sswPairs.c create mode 100644 src/aig/ssw_old/sswPart.c create mode 100644 src/aig/ssw_old/sswSat.c create mode 100644 src/aig/ssw_old/sswSim.c create mode 100644 src/aig/ssw_old/sswSimSat.c create mode 100644 src/aig/ssw_old/sswSweep.c create mode 100644 src/aig/ssw_old/sswUnique.c create mode 100644 src/base/abci/abc.zip create mode 100644 src/sat/bsat/satChecker.c create mode 100644 src/sat/bsat/satInterA_mod.c create mode 100644 src/sat/bsat/satInterA_old.c create mode 100644 src/sat/lsat/solver.h diff --git a/abc.dsp b/abc.dsp index 8f3cfbe23..9ef7952a4 100644 --- a/abc.dsp +++ b/abc.dsp @@ -42,7 +42,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O2 /I "src/base/abc" /I "src/base/abci" /I "src/base/cmd" /I "src/base/io" /I "src/base/main" /I "src/base/ver" /I "src/bdd/cudd" /I "src/bdd/dsd" /I "src/bdd/epd" /I "src/bdd/mtr" /I "src/bdd/parse" /I "src/bdd/reo" /I "src/bdd/cas" /I "src/map/fpga" /I "src/map/mapper" /I "src/map/mio" /I "src/map/super" /I "src/map/if" /I "src/map/pcm" /I "src/map/ply" /I "src/misc/extra" /I "src/misc/mvc" /I "src/misc/st" /I "src/misc/util" /I "src/misc/espresso" /I "src/misc/nm" /I "src/misc/vec" /I "src/misc/hash" /I "src/misc/bzlib" /I "src/misc/zlib" /I "src/opt/cut" /I "src/opt/dec" /I "src/opt/fxu" /I "src/opt/rwr" /I "src/opt/sim" /I "src/opt/ret" /I "src/opt/res" /I "src/opt/lpk" /I "src/sat/bsat" /I "src/sat/csat" /I "src/sat/msat" /I "src/sat/fraig" /I "src/sat/nsat" /I "src/sat/psat" /I "src/aig/ivy" /I "src/aig/hop" /I "src/aig/rwt" /I "src/aig/deco" /I "src/aig/mem" /I "src/aig/dar" /I "src/aig/fra" /I "src/aig/cnf" /I "src/aig/csw" /I "src/aig/ioa" /I "src/aig/aig" /I "src/aig/kit" /I "src/aig/bdc" /I "src/aig/bar" /I "src/aig/ntl" /I "src/aig/nwk" /I "src/aig/tim" /I "src/opt/mfs" /I "src/aig/mfx" /I "src/aig/saig" /I "src/aig/bbr" /I "src/aig/int" /I "src/aig/dch" /I "src/aig/ssw" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /D ABC_DLL=DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /D "ABC_USE_LIBRARIES" /FR /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "src/base/abc" /I "src/base/abci" /I "src/base/cmd" /I "src/base/io" /I "src/base/main" /I "src/base/ver" /I "src/bdd/cudd" /I "src/bdd/dsd" /I "src/bdd/epd" /I "src/bdd/mtr" /I "src/bdd/parse" /I "src/bdd/reo" /I "src/bdd/cas" /I "src/map/fpga" /I "src/map/mapper" /I "src/map/mio" /I "src/map/super" /I "src/map/if" /I "src/map/pcm" /I "src/map/ply" /I "src/misc/extra" /I "src/misc/mvc" /I "src/misc/st" /I "src/misc/util" /I "src/misc/espresso" /I "src/misc/nm" /I "src/misc/vec" /I "src/misc/hash" /I "src/misc/bzlib" /I "src/misc/zlib" /I "src/opt/cut" /I "src/opt/dec" /I "src/opt/fxu" /I "src/opt/rwr" /I "src/opt/sim" /I "src/opt/ret" /I "src/opt/res" /I "src/opt/lpk" /I "src/sat/bsat" /I "src/sat/csat" /I "src/sat/msat" /I "src/sat/fraig" /I "src/sat/nsat" /I "src/sat/psat" /I "src/aig/ivy" /I "src/aig/hop" /I "src/aig/rwt" /I "src/aig/deco" /I "src/aig/mem" /I "src/aig/dar" /I "src/aig/fra" /I "src/aig/cnf" /I "src/aig/csw" /I "src/aig/ioa" /I "src/aig/aig" /I "src/aig/kit" /I "src/aig/bdc" /I "src/aig/bar" /I "src/aig/ntl" /I "src/aig/nwk" /I "src/aig/tim" /I "src/opt/mfs" /I "src/aig/mfx" /I "src/aig/saig" /I "src/aig/bbr" /I "src/aig/int" /I "src/aig/dch" /I "src/aig/ssw" /I "src/sat/lsat" /I "src/aig/cec" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /D ABC_DLL=DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /D "ABC_USE_LIBRARIES" /FR /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -66,7 +66,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "src/base/abc" /I "src/base/abci" /I "src/base/cmd" /I "src/base/io" /I "src/base/main" /I "src/base/ver" /I "src/bdd/cudd" /I "src/bdd/dsd" /I "src/bdd/epd" /I "src/bdd/mtr" /I "src/bdd/parse" /I "src/bdd/reo" /I "src/bdd/cas" /I "src/map/fpga" /I "src/map/mapper" /I "src/map/mio" /I "src/map/super" /I "src/map/if" /I "src/map/pcm" /I "src/map/ply" /I "src/misc/extra" /I "src/misc/mvc" /I "src/misc/st" /I "src/misc/util" /I "src/misc/espresso" /I "src/misc/nm" /I "src/misc/vec" /I "src/misc/hash" /I "src/misc/bzlib" /I "src/misc/zlib" /I "src/opt/cut" /I "src/opt/dec" /I "src/opt/fxu" /I "src/opt/rwr" /I "src/opt/sim" /I "src/opt/ret" /I "src/opt/res" /I "src/opt/lpk" /I "src/sat/bsat" /I "src/sat/csat" /I "src/sat/msat" /I "src/sat/fraig" /I "src/sat/nsat" /I "src/sat/psat" /I "src/aig/ivy" /I "src/aig/hop" /I "src/aig/rwt" /I "src/aig/deco" /I "src/aig/mem" /I "src/aig/dar" /I "src/aig/fra" /I "src/aig/cnf" /I "src/aig/csw" /I "src/aig/ioa" /I "src/aig/aig" /I "src/aig/kit" /I "src/aig/bdc" /I "src/aig/bar" /I "src/aig/ntl" /I "src/aig/nwk" /I "src/aig/tim" /I "src/opt/mfs" /I "src/aig/mfx" /I "src/aig/saig" /I "src/aig/bbr" /I "src/aig/int" /I "src/aig/dch" /I "src/aig/ssw" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /D ABC_DLL=DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /D "ABC_USE_LIBRARIES" /FR /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "src/base/abc" /I "src/base/abci" /I "src/base/cmd" /I "src/base/io" /I "src/base/main" /I "src/base/ver" /I "src/bdd/cudd" /I "src/bdd/dsd" /I "src/bdd/epd" /I "src/bdd/mtr" /I "src/bdd/parse" /I "src/bdd/reo" /I "src/bdd/cas" /I "src/map/fpga" /I "src/map/mapper" /I "src/map/mio" /I "src/map/super" /I "src/map/if" /I "src/map/pcm" /I "src/map/ply" /I "src/misc/extra" /I "src/misc/mvc" /I "src/misc/st" /I "src/misc/util" /I "src/misc/espresso" /I "src/misc/nm" /I "src/misc/vec" /I "src/misc/hash" /I "src/misc/bzlib" /I "src/misc/zlib" /I "src/opt/cut" /I "src/opt/dec" /I "src/opt/fxu" /I "src/opt/rwr" /I "src/opt/sim" /I "src/opt/ret" /I "src/opt/res" /I "src/opt/lpk" /I "src/sat/bsat" /I "src/sat/csat" /I "src/sat/msat" /I "src/sat/fraig" /I "src/sat/nsat" /I "src/sat/psat" /I "src/aig/ivy" /I "src/aig/hop" /I "src/aig/rwt" /I "src/aig/deco" /I "src/aig/mem" /I "src/aig/dar" /I "src/aig/fra" /I "src/aig/cnf" /I "src/aig/csw" /I "src/aig/ioa" /I "src/aig/aig" /I "src/aig/kit" /I "src/aig/bdc" /I "src/aig/bar" /I "src/aig/ntl" /I "src/aig/nwk" /I "src/aig/tim" /I "src/opt/mfs" /I "src/aig/mfx" /I "src/aig/saig" /I "src/aig/bbr" /I "src/aig/int" /I "src/aig/dch" /I "src/aig/ssw" /I "src/sat/lsat" /I "src/aig/cec" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /D ABC_DLL=DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /D "ABC_USE_LIBRARIES" /FR /YX /FD /GZ /c # SUBTRACT CPP /X # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" @@ -1261,6 +1261,14 @@ SOURCE=.\src\sat\psat\m114p_types.h # PROP Default_Filter "" # End Group +# Begin Group "lsat" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\lsat\solver.h +# End Source File +# End Group # End Group # Begin Group "opt" @@ -3501,6 +3509,10 @@ SOURCE=.\src\aig\ssw\sswSweep.c SOURCE=.\src\aig\ssw\sswUnique.c # End Source File # End Group +# Begin Group "cec" + +# PROP Default_Filter "" +# End Group # End Group # End Group # Begin Group "Header Files" diff --git a/src/aig/aig/aig.h b/src/aig/aig/aig.h index 503985b74..7480df78c 100644 --- a/src/aig/aig/aig.h +++ b/src/aig/aig/aig.h @@ -194,6 +194,17 @@ struct Aig_ManCut_t_ unsigned * puTemp[4]; // used for the truth table computation }; +#ifdef WIN32 +#define DLLEXPORT __declspec(dllexport) +#define DLLIMPORT __declspec(dllimport) +#else /* defined(WIN32) */ +#define DLLIMPORT +#endif /* defined(WIN32) */ + +#ifndef ABC_DLL +#define ABC_DLL DLLIMPORT +#endif + static inline Aig_Cut_t * Aig_ObjCuts( Aig_ManCut_t * p, Aig_Obj_t * pObj ) { return p->pCuts[pObj->Id]; } static inline void Aig_ObjSetCuts( Aig_ManCut_t * p, Aig_Obj_t * pObj, Aig_Cut_t * pCuts ) { p->pCuts[pObj->Id] = pCuts; } @@ -452,7 +463,7 @@ static inline int Aig_ObjFanoutNext( Aig_Man_t * p, int iFan ) { assert(iF //////////////////////////////////////////////////////////////////////// /*=== aigCheck.c ========================================================*/ -extern int Aig_ManCheck( Aig_Man_t * p ); +extern ABC_DLL int Aig_ManCheck( Aig_Man_t * p ); extern void Aig_ManCheckMarkA( Aig_Man_t * p ); extern void Aig_ManCheckPhase( Aig_Man_t * p ); /*=== aigCuts.c ========================================================*/ @@ -502,7 +513,7 @@ extern Aig_Man_t * Aig_ManFrames( Aig_Man_t * pAig, int nFs, int fInit, int extern Aig_Man_t * Aig_ManStart( int nNodesMax ); extern Aig_Man_t * Aig_ManStartFrom( Aig_Man_t * p ); extern Aig_Man_t * Aig_ManExtractMiter( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 ); -extern void Aig_ManStop( Aig_Man_t * p ); +extern ABC_DLL void Aig_ManStop( Aig_Man_t * p ); extern int Aig_ManCleanup( Aig_Man_t * p ); extern int Aig_ManAntiCleanup( Aig_Man_t * p ); extern int Aig_ManPiCleanup( Aig_Man_t * p ); diff --git a/src/aig/cec/cecSat.c b/src/aig/cec/cecSat.c new file mode 100644 index 000000000..37f63f05e --- /dev/null +++ b/src/aig/cec/cecSat.c @@ -0,0 +1,284 @@ +/**CFile**************************************************************** + + FileName [cecSat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Combinational equivalence checking.] + + Synopsis [Backend calling the SAT solver.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 30, 2007.] + + Revision [$Id: cecSat.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" +#include "cnf.h" +#include "solver.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes CNF into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +solver * Cnf_WriteIntoSolverNew( Cnf_Dat_t * p ) +{ + solver * pSat; + int i, status; + pSat = solver_new(); + for ( i = 0; i < p->nVars; i++ ) + solver_newVar( pSat ); + for ( i = 0; i < p->nClauses; i++ ) + { + if ( !solver_addClause( pSat, p->pClauses[i+1]-p->pClauses[i], p->pClauses[i] ) ) + { + solver_delete( pSat ); + return NULL; + } + } + status = solver_simplify(pSat); + if ( status == 0 ) + { + solver_delete( pSat ); + return NULL; + } + return pSat; +} + +/**Function************************************************************* + + Synopsis [Adds the OR-clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cnf_DataWriteAndClausesNew( void * p, Cnf_Dat_t * pCnf ) +{ +/* + sat_solver * pSat = p; + Aig_Obj_t * pObj; + int i, Lit; + Aig_ManForEachPo( pCnf->pMan, pObj, i ) + { + Lit = toLitCond( pCnf->pVarNums[pObj->Id], 0 ); + if ( !sat_solver_addclause( pSat, &Lit, &Lit+1 ) ) + return 0; + } +*/ + return 1; +} + +/**Function************************************************************* + + Synopsis [Adds the OR-clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cnf_DataWriteOrClauseNew( solver * pSat, Cnf_Dat_t * pCnf ) +{ + Aig_Obj_t * pObj; + int i, * pLits; + pLits = ALLOC( int, Aig_ManPoNum(pCnf->pMan) ); + Aig_ManForEachPo( pCnf->pMan, pObj, i ) + pLits[i] = solver_mkLit_args( pCnf->pVarNums[pObj->Id], 0 ); + if ( !solver_addClause( pSat, Aig_ManPoNum(pCnf->pMan), pLits ) ) + { + free( pLits ); + return 0; + } + free( pLits ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Writes the given clause in a file in DIMACS format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sat_SolverPrintStatsNew( FILE * pFile, solver * pSat ) +{ +// printf( "starts : %8d\n", solver_num_assigns(pSat) ); + printf( "vars : %8d\n", solver_num_vars(pSat) ); + printf( "clauses : %8d\n", solver_num_clauses(pSat) ); + printf( "conflicts : %8d\n", solver_num_learnts(pSat) ); +} + +/**Function************************************************************* + + Synopsis [Returns a counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Sat_SolverGetModelNew( solver * pSat, int * pVars, int nVars ) +{ + int * pModel; + int i; + pModel = ALLOC( int, nVars+1 ); + for ( i = 0; i < nVars; i++ ) + { + assert( pVars[i] >= 0 && pVars[i] < solver_num_vars(pSat) ); + pModel[i] = (int)(solver_modelValue_Var( pSat, pVars[i] ) == solver_l_True); + } + return pModel; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec_RunSat( Aig_Man_t * pMan, sint64 nConfLimit, sint64 nInsLimit, int fFlipBits, int fAndOuts, int fVerbose ) +{ + 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) ); + + // convert into SAT solver + pSat = Cnf_WriteIntoSolverNew( pCnf ); + if ( pSat == NULL ) + { + Cnf_DataFree( pCnf ); + return 1; + } + + + if ( fAndOuts ) + { + assert( 0 ); + // assert each output independently + if ( !Cnf_DataWriteAndClausesNew( pSat, pCnf ) ) + { + solver_delete( pSat ); + Cnf_DataFree( pCnf ); + return 1; + } + } + else + { + // add the OR clause for the outputs + if ( !Cnf_DataWriteOrClauseNew( pSat, pCnf ) ) + { + 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) ); +// PRT( "Time", clock() - clk ); + + // simplify the problem + clk = clock(); + status = solver_simplify(pSat); +// printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) ); +// PRT( "Time", clock() - clk ); + if ( status == 0 ) + { + Vec_IntFree( vCiIds ); + solver_delete( pSat ); +// printf( "The problem is UNSATISFIABLE after simplification.\n" ); + return 1; + } + + // solve the miter + clk = clock(); + if ( fVerbose ) + solver_set_verbosity( pSat, 1 ); + status = solver_solve( pSat, 0, NULL ); + if ( status == solver_l_Undef ) + { +// printf( "The problem timed out.\n" ); + RetValue = -1; + } + else if ( status == solver_l_True ) + { +// printf( "The problem is SATISFIABLE.\n" ); + RetValue = 0; + } + else if ( status == solver_l_False ) + { +// printf( "The problem is UNSATISFIABLE.\n" ); + RetValue = 1; + } + else + assert( 0 ); +// PRT( "SAT sat_solver time", clock() - clk ); +// printf( "The number of conflicts = %d.\n", (int)pSat->sat_solver_stats.conflicts ); + + // if the problem is SAT, get the counterexample + if ( status == solver_l_True ) + { + pMan->pData = Sat_SolverGetModelNew( pSat, vCiIds->pArray, vCiIds->nSize ); + } + // free the sat_solver + if ( fVerbose ) + Sat_SolverPrintStatsNew( stdout, pSat ); +//sat_solver_store_write( pSat, "trace.cnf" ); +//sat_solver_store_free( pSat ); + solver_delete( pSat ); + Vec_IntFree( vCiIds ); + return RetValue; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/aig/saig/saig.h b/src/aig/saig/saig.h index c7a40f969..ddae07e0e 100644 --- a/src/aig/saig/saig.h +++ b/src/aig/saig/saig.h @@ -94,7 +94,9 @@ extern Aig_Man_t * Saig_ManReadBlif( char * pFileName ); extern int Saig_Interpolate( Aig_Man_t * pAig, Inter_ManParams_t * pPars, int * pDepth ); /*=== saigMiter.c ==========================================================*/ extern Aig_Man_t * Saig_ManCreateMiter( Aig_Man_t * p1, Aig_Man_t * p2, int Oper ); -extern Aig_Man_t * Saig_ManDupInitZero( Aig_Man_t * p ); +extern Aig_Man_t * Saig_ManCreateMiterComb( Aig_Man_t * p1, Aig_Man_t * p2, int Oper ); +extern Aig_Man_t * Saig_ManCreateMiterTwo( Aig_Man_t * pOld, Aig_Man_t * pNew, int nFrames ); +extern int Saig_ManDemiterSimple( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 ); /*=== saigPhase.c ==========================================================*/ extern Aig_Man_t * Saig_ManPhaseAbstract( Aig_Man_t * p, Vec_Int_t * vInits, int nFrames, int fIgnore, int fPrint, int fVerbose ); /*=== saigRetFwd.c ==========================================================*/ @@ -107,6 +109,8 @@ extern Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, in extern int Saig_ManRetimeSteps( Aig_Man_t * p, int nSteps, int fForward, int fAddBugs ); /*=== saigScl.c ==========================================================*/ extern void Saig_ManReportUselessRegisters( Aig_Man_t * pAig ); +/*=== saigSynch.c ==========================================================*/ +extern Aig_Man_t * Saig_ManDupInitZero( Aig_Man_t * p ); /*=== saigTrans.c ==========================================================*/ extern Aig_Man_t * Saig_ManTimeframeSimplify( Aig_Man_t * pAig, int nFrames, int nFramesMax, int fInit, int fVerbose ); diff --git a/src/aig/saig/saigMiter.c b/src/aig/saig/saigMiter.c index 5b18db6e5..5efcd24dd 100644 --- a/src/aig/saig/saigMiter.c +++ b/src/aig/saig/saigMiter.c @@ -30,7 +30,7 @@ /**Function************************************************************* - Synopsis [] + Synopsis [Creates sequential miter.] Description [] @@ -39,56 +39,268 @@ SeeAlso [] ***********************************************************************/ -Aig_Man_t * Saig_ManCreateMiter( Aig_Man_t * p1, Aig_Man_t * p2, int Oper ) +Aig_Man_t * Saig_ManCreateMiter( Aig_Man_t * p0, Aig_Man_t * p1, int Oper ) { Aig_Man_t * pNew; Aig_Obj_t * pObj; int i; - assert( Saig_ManRegNum(p1) > 0 || Saig_ManRegNum(p2) > 0 ); - assert( Saig_ManPiNum(p1) == Saig_ManPiNum(p2) ); - assert( Saig_ManPoNum(p1) == Saig_ManPoNum(p2) ); - pNew = Aig_ManStart( Aig_ManObjNumMax(p1) + Aig_ManObjNumMax(p2) ); + assert( Saig_ManRegNum(p0) > 0 || Saig_ManRegNum(p1) > 0 ); + assert( Saig_ManPiNum(p0) == Saig_ManPiNum(p1) ); + assert( Saig_ManPoNum(p0) == Saig_ManPoNum(p1) ); + pNew = Aig_ManStart( Aig_ManObjNumMax(p0) + Aig_ManObjNumMax(p1) ); pNew->pName = Aig_UtilStrsav( "miter" ); // map constant nodes + Aig_ManConst1(p0)->pData = Aig_ManConst1(pNew); Aig_ManConst1(p1)->pData = Aig_ManConst1(pNew); - Aig_ManConst1(p2)->pData = Aig_ManConst1(pNew); // map primary inputs - Saig_ManForEachPi( p1, pObj, i ) + Saig_ManForEachPi( p0, pObj, i ) pObj->pData = Aig_ObjCreatePi( pNew ); - Saig_ManForEachPi( p2, pObj, i ) + Saig_ManForEachPi( p1, pObj, i ) pObj->pData = Aig_ManPi( pNew, i ); // map register outputs + Saig_ManForEachLo( p0, pObj, i ) + pObj->pData = Aig_ObjCreatePi( pNew ); Saig_ManForEachLo( p1, pObj, i ) pObj->pData = Aig_ObjCreatePi( pNew ); - Saig_ManForEachLo( p2, pObj, i ) - pObj->pData = Aig_ObjCreatePi( pNew ); // map internal nodes + Aig_ManForEachNode( p0, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); Aig_ManForEachNode( p1, pObj, i ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - Aig_ManForEachNode( p2, pObj, i ) - pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // create primary outputs - Saig_ManForEachPo( p1, pObj, i ) + Saig_ManForEachPo( p0, pObj, i ) { if ( Oper == 0 ) // XOR - pObj = Aig_Exor( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild0Copy(Aig_ManPo(p2,i)) ); - else if ( Oper == 1 ) // implication is PO(p1) -> PO(p2) ... complement is PO(p1) & !PO(p2) - pObj = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_Not(Aig_ObjChild0Copy(Aig_ManPo(p2,i))) ); + pObj = Aig_Exor( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild0Copy(Aig_ManPo(p1,i)) ); + else if ( Oper == 1 ) // implication is PO(p0) -> PO(p1) ... complement is PO(p0) & !PO(p1) + pObj = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_Not(Aig_ObjChild0Copy(Aig_ManPo(p1,i))) ); else assert( 0 ); Aig_ObjCreatePo( pNew, pObj ); } // create register inputs + Saig_ManForEachLi( p0, pObj, i ) + pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); Saig_ManForEachLi( p1, pObj, i ) pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); - Saig_ManForEachLi( p2, pObj, i ) - pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); // cleanup - Aig_ManSetRegNum( pNew, Saig_ManRegNum(p1) + Saig_ManRegNum(p2) ); + Aig_ManSetRegNum( pNew, Saig_ManRegNum(p0) + Saig_ManRegNum(p1) ); Aig_ManCleanup( pNew ); return pNew; } +/**Function************************************************************* + + Synopsis [Creates combinational miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManCreateMiterComb( Aig_Man_t * p0, Aig_Man_t * p1, int Oper ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj; + int i; + assert( Aig_ManPiNum(p0) == Aig_ManPiNum(p1) ); + assert( Aig_ManPoNum(p0) == Aig_ManPoNum(p1) ); + pNew = Aig_ManStart( Aig_ManObjNumMax(p0) + Aig_ManObjNumMax(p1) ); + pNew->pName = Aig_UtilStrsav( "miter" ); + // map constant nodes + Aig_ManConst1(p0)->pData = Aig_ManConst1(pNew); + Aig_ManConst1(p1)->pData = Aig_ManConst1(pNew); + // map primary inputs and register outputs + Aig_ManForEachPi( p0, pObj, i ) + pObj->pData = Aig_ObjCreatePi( pNew ); + Aig_ManForEachPi( p1, pObj, i ) + pObj->pData = Aig_ManPi( pNew, i ); + // map internal nodes + Aig_ManForEachNode( p0, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + Aig_ManForEachNode( p1, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // create primary outputs + Aig_ManForEachPo( p0, pObj, i ) + { + if ( Oper == 0 ) // XOR + pObj = Aig_Exor( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild0Copy(Aig_ManPo(p1,i)) ); + else if ( Oper == 1 ) // implication is PO(p0) -> PO(p1) ... complement is PO(p0) & !PO(p1) + pObj = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_Not(Aig_ObjChild0Copy(Aig_ManPo(p1,i))) ); + else + assert( 0 ); + Aig_ObjCreatePo( pNew, pObj ); + } + // cleanup + Aig_ManSetRegNum( pNew, 0 ); + Aig_ManCleanup( pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Create combinational timeframes by unrolling sequential circuits.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManUnrollTwo( Aig_Man_t * pBot, Aig_Man_t * pTop, int nFrames ) +{ + Aig_Man_t * p, * pAig; + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + int i, f; + assert( nFrames > 1 ); + assert( Saig_ManPiNum(pBot) == Saig_ManPiNum(pTop) ); + assert( Saig_ManPoNum(pBot) == Saig_ManPoNum(pTop) ); + assert( Saig_ManRegNum(pBot) == Saig_ManRegNum(pTop) ); + assert( Saig_ManRegNum(pBot) > 0 || Saig_ManRegNum(pTop) > 0 ); + // start timeframes + p = Aig_ManStart( nFrames * AIG_MAX(Aig_ManObjNumMax(pBot), Aig_ManObjNumMax(pTop)) ); + p->pName = Aig_UtilStrsav( "frames" ); + // create variables for register outputs + pAig = pBot; + Saig_ManForEachLo( pAig, pObj, i ) + pObj->pData = Aig_ObjCreatePi( p ); + // add timeframes + for ( f = 0; f < nFrames; f++ ) + { + // create PI nodes for this frame + Aig_ManConst1(pAig)->pData = Aig_ManConst1( p ); + Saig_ManForEachPi( pAig, pObj, i ) + pObj->pData = Aig_ObjCreatePi( p ); + // add internal nodes of this frame + Aig_ManForEachNode( pAig, pObj, i ) + pObj->pData = Aig_And( p, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + if ( f == nFrames - 1 ) + { + // create POs for this frame + Aig_ManForEachPo( pAig, pObj, i ) + Aig_ObjCreatePo( p, Aig_ObjChild0Copy(pObj) ); + 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; + if ( f == 0 ) + { + // transfer from pOld to pNew + Saig_ManForEachLo( pAig, pObj, i ) + Saig_ManLo(pTop, i)->pData = pObj->pData; + pAig = pTop; + } + } + Aig_ManCleanup( p ); + return p; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG while creating POs from the set.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupNodes_old( Aig_Man_t * p, Vec_Ptr_t * vSet ) +{ + Aig_Man_t * pNew, * pCopy; + Aig_Obj_t * pObj; + int i; + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Aig_UtilStrsav( p->pName ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachPi( p, pObj, i ) + pObj->pData = Aig_ObjCreatePi( pNew ); + Aig_ManForEachNode( p, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); +// Saig_ManForEachPo( p, pObj, i ) +// pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); + Vec_PtrForEachEntry( vSet, pObj, i ) + Aig_ObjCreatePo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_Regular(pObj)->pData, Aig_IsComplement(pObj)) ); + Saig_ManForEachLi( p, pObj, i ) + pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); + Aig_ManSetRegNum( pNew, Saig_ManRegNum(p) ); + // cleanup and return a copy + Aig_ManSeqCleanup( pNew ); + pCopy = Aig_ManDupSimpleDfs( pNew ); + Aig_ManStop( pNew ); + return pCopy; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG while creating POs from the set.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupNodes( Aig_Man_t * p, Vec_Ptr_t * vSet, int iPart ) +{ + Aig_Man_t * pNew, * pCopy; + Aig_Obj_t * pObj; + int i; + Aig_ManCleanData( p ); + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Aig_UtilStrsav( p->pName ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Saig_ManForEachPi( p, pObj, i ) + pObj->pData = Aig_ObjCreatePi( pNew ); + if ( iPart == 0 ) + { + Saig_ManForEachLo( p, pObj, i ) + if ( i < Saig_ManRegNum(p)/2 ) + pObj->pData = Aig_ObjCreatePi( pNew ); + } + else + { + Saig_ManForEachLo( p, pObj, i ) + if ( i >= Saig_ManRegNum(p)/2 ) + pObj->pData = Aig_ObjCreatePi( pNew ); + } + Aig_ManForEachNode( p, pObj, i ) + if ( Aig_ObjFanin0(pObj)->pData && Aig_ObjFanin1(pObj)->pData ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); +// Saig_ManForEachPo( p, pObj, i ) +// pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); + Vec_PtrForEachEntry( vSet, pObj, i ) + Aig_ObjCreatePo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_Regular(pObj)->pData, Aig_IsComplement(pObj)) ); + if ( iPart == 0 ) + { + Saig_ManForEachLi( p, pObj, i ) + if ( i < Saig_ManRegNum(p)/2 ) + pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); + } + else + { + Saig_ManForEachLi( p, pObj, i ) + if ( i >= Saig_ManRegNum(p)/2 ) + pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); + } + Aig_ManSetRegNum( pNew, Saig_ManRegNum(p)/2 ); + // cleanup and return a copy +// Aig_ManSeqCleanup( pNew ); + Aig_ManCleanup( pNew ); + pCopy = Aig_ManDupSimpleDfs( pNew ); + Aig_ManStop( pNew ); + return pCopy; +} + /**Function************************************************************* Synopsis [Duplicates the AIG to have constant-0 initial state.] @@ -100,29 +312,356 @@ Aig_Man_t * Saig_ManCreateMiter( Aig_Man_t * p1, Aig_Man_t * p2, int Oper ) SeeAlso [] ***********************************************************************/ -Aig_Man_t * Saig_ManDupInitZero( Aig_Man_t * p ) +int Saig_ManDemiterSimple( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 ) { - Aig_Man_t * pNew; - Aig_Obj_t * pObj; - int i; - pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); - Saig_ManForEachPi( p, pObj, i ) - pObj->pData = Aig_ObjCreatePi( pNew ); - Saig_ManForEachLo( p, pObj, i ) - pObj->pData = Aig_NotCond( Aig_ObjCreatePi( pNew ), pObj->fMarkA ); - Aig_ManForEachNode( p, pObj, i ) - pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + Vec_Ptr_t * vSet0, * vSet1; + Aig_Obj_t * pObj, * pFanin, * pObj0, * pObj1; + int i, Counter = 0; + assert( Saig_ManRegNum(p) % 2 == 0 ); + vSet0 = Vec_PtrAlloc( Saig_ManPoNum(p) ); + vSet1 = Vec_PtrAlloc( Saig_ManPoNum(p) ); Saig_ManForEachPo( p, pObj, i ) - pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); - Saig_ManForEachLi( p, pObj, i ) - pObj->pData = Aig_ObjCreatePo( pNew, Aig_NotCond( Aig_ObjChild0Copy(pObj), pObj->fMarkA ) ); - Aig_ManSetRegNum( pNew, Saig_ManRegNum(p) ); - assert( Aig_ManNodeNum(pNew) == Aig_ManNodeNum(p) ); - return pNew; + { + pFanin = Aig_ObjFanin0(pObj); + if ( Aig_ObjIsConst1( pFanin ) ) + { + if ( !Aig_ObjFaninC0(pObj) ) + printf( "The output number %d of the miter is constant 1.\n", i ); + Counter++; + continue; + } + if ( !Aig_ObjIsNode(pFanin) || !Aig_ObjRecognizeExor( pFanin, &pObj0, &pObj1 ) ) + { + printf( "The miter cannot be demitered.\n" ); + Vec_PtrFree( vSet0 ); + Vec_PtrFree( vSet1 ); + return 0; + } +// printf( "%d %d ", Aig_Regular(pObj0)->Id, Aig_Regular(pObj1)->Id ); + if ( Aig_Regular(pObj0)->Id < Aig_Regular(pObj1)->Id ) + { + Vec_PtrPush( vSet0, pObj0 ); + Vec_PtrPush( vSet1, pObj1 ); + } + else + { + Vec_PtrPush( vSet0, pObj1 ); + Vec_PtrPush( vSet1, pObj0 ); + } + } +// printf( "Miter has %d constant outputs.\n", Counter ); +// printf( "\n" ); + if ( ppAig0 ) + { + *ppAig0 = Aig_ManDupNodes( p, vSet0, 0 ); + FREE( (*ppAig0)->pName ); + (*ppAig0)->pName = Aig_UtilStrsav( "part0" ); + } + if ( ppAig1 ) + { + *ppAig1 = Aig_ManDupNodes( p, vSet1, 1 ); + FREE( (*ppAig1)->pName ); + (*ppAig1)->pName = Aig_UtilStrsav( "part1" ); + } + Vec_PtrFree( vSet0 ); + Vec_PtrFree( vSet1 ); + return 1; } +/**Function************************************************************* + + Synopsis [Labels logic reachable from the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManDemiterLabel_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int Value ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Value ) + pObj->fMarkB = 1; + else + pObj->fMarkA = 1; + if ( Saig_ObjIsPi(p, pObj) ) + return; + if ( Saig_ObjIsLo(p, pObj) ) + { + Saig_ManDemiterLabel_rec( p, Aig_ObjFanin0( Saig_ObjLoToLi(p, pObj) ), Value ); + return; + } + assert( Aig_ObjIsNode(pObj) ); + Saig_ManDemiterLabel_rec( p, Aig_ObjFanin0(pObj), Value ); + Saig_ManDemiterLabel_rec( p, Aig_ObjFanin1(pObj), Value ); +} + +/**Function************************************************************* + + Synopsis [Returns the first labeled register encountered during traversal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Saig_ManGetLabeledRegister_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pResult; + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return NULL; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Saig_ObjIsPi(p, pObj) ) + return NULL; + if ( Saig_ObjIsLo(p, pObj) ) + { + if ( pObj->fMarkA || pObj->fMarkB ) + return pObj; + return Saig_ManGetLabeledRegister_rec( p, Aig_ObjFanin0( Saig_ObjLoToLi(p, pObj) ) ); + } + assert( Aig_ObjIsNode(pObj) ); + pResult = Saig_ManGetLabeledRegister_rec( p, Aig_ObjFanin0(pObj) ); + if ( pResult ) + return pResult; + return Saig_ManGetLabeledRegister_rec( p, Aig_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG to have constant-0 initial state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManDemiter( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 ) +{ + Vec_Ptr_t * vPairs, * vSet0, * vSet1; + Aig_Obj_t * pObj, * pObj0, * pObj1, * pFlop0, * pFlop1; + int i, Counter; + assert( Saig_ManRegNum(p) > 0 ); + Aig_ManSetPioNumbers( p ); + // check if demitering is possible + vPairs = Vec_PtrAlloc( 2 * Saig_ManPoNum(p) ); + Saig_ManForEachPo( p, pObj, i ) + { + if ( !Aig_ObjRecognizeExor( Aig_ObjFanin0(pObj), &pObj0, &pObj1 ) ) + { + Vec_PtrFree( vPairs ); + return 0; + } + Vec_PtrPush( vPairs, pObj0 ); + Vec_PtrPush( vPairs, pObj1 ); + } + // start array of outputs + vSet0 = Vec_PtrAlloc( Saig_ManPoNum(p) ); + vSet1 = Vec_PtrAlloc( Saig_ManPoNum(p) ); + // get the first pair of outputs + pObj0 = Vec_PtrEntry( vPairs, 0 ); + pObj1 = Vec_PtrEntry( vPairs, 1 ); + // label registers reachable from the outputs + Aig_ManIncrementTravId( p ); + Saig_ManDemiterLabel_rec( p, Aig_Regular(pObj0), 0 ); + Vec_PtrPush( vSet0, pObj0 ); + Aig_ManIncrementTravId( p ); + Saig_ManDemiterLabel_rec( p, Aig_Regular(pObj1), 1 ); + Vec_PtrPush( vSet1, pObj1 ); + // find where each output belongs + for ( i = 2; i < Vec_PtrSize(vPairs); i += 2 ) + { + pObj0 = Vec_PtrEntry( vPairs, i ); + pObj1 = Vec_PtrEntry( vPairs, i+1 ); + + Aig_ManIncrementTravId( p ); + pFlop0 = Saig_ManGetLabeledRegister_rec( p, Aig_Regular(pObj0) ); + + Aig_ManIncrementTravId( p ); + pFlop1 = Saig_ManGetLabeledRegister_rec( p, Aig_Regular(pObj1) ); + + if ( (pFlop0->fMarkA && pFlop0->fMarkB) || (pFlop1->fMarkA && pFlop1->fMarkB) || + (pFlop0->fMarkA && pFlop1->fMarkA) || (pFlop0->fMarkB && pFlop1->fMarkB) ) + printf( "Ouput pair %4d: Difficult case...\n", i/2 ); + + if ( pFlop0->fMarkB ) + { + Saig_ManDemiterLabel_rec( p, pObj0, 1 ); + Vec_PtrPush( vSet0, pObj0 ); + } + else // if ( pFlop0->fMarkA ) or none + { + Saig_ManDemiterLabel_rec( p, pObj0, 0 ); + Vec_PtrPush( vSet1, pObj0 ); + } + + if ( pFlop1->fMarkB ) + { + Saig_ManDemiterLabel_rec( p, pObj1, 1 ); + Vec_PtrPush( vSet0, pObj1 ); + } + else // if ( pFlop1->fMarkA ) or none + { + Saig_ManDemiterLabel_rec( p, pObj1, 0 ); + Vec_PtrPush( vSet1, pObj1 ); + } + } + // check if there are any flops in common + Counter = 0; + Saig_ManForEachLo( p, pObj, i ) + if ( pObj->fMarkA && pObj->fMarkB ) + Counter++; + if ( Counter > 0 ) + printf( "The miters contains %d flops reachable from both AIGs.\n", Counter ); + + // produce two miters + if ( ppAig0 ) + { + assert( 0 ); + *ppAig0 = Aig_ManDupNodes( p, vSet0, 0 ); // not ready + FREE( (*ppAig0)->pName ); + (*ppAig0)->pName = Aig_UtilStrsav( "part0" ); + } + if ( ppAig1 ) + { + assert( 0 ); + *ppAig1 = Aig_ManDupNodes( p, vSet1, 1 ); // not ready + FREE( (*ppAig1)->pName ); + (*ppAig1)->pName = Aig_UtilStrsav( "part1" ); + } + Vec_PtrFree( vSet0 ); + Vec_PtrFree( vSet1 ); + Vec_PtrFree( vPairs ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Create specialized miter by unrolling two circuits.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManCreateMiterTwo( Aig_Man_t * pOld, Aig_Man_t * pNew, int nFrames ) +{ + Aig_Man_t * pFrames0, * pFrames1, * pMiter; + assert( Aig_ManNodeNum(pOld) <= Aig_ManNodeNum(pNew) ); + pFrames0 = Saig_ManUnrollTwo( pOld, pOld, nFrames ); + pFrames1 = Saig_ManUnrollTwo( pNew, pOld, nFrames ); + pMiter = Saig_ManCreateMiterComb( pFrames0, pFrames1, 0 ); + Aig_ManStop( pFrames0 ); + Aig_ManStop( pFrames1 ); + return pMiter; +} + +/**Function************************************************************* + + Synopsis [Reduces SEC to CEC for the special case of seq synthesis.] + + Description [The first circuit (pPart0) should be circuit before synthesis. + The second circuit (pPart1) should be circuit after synthesis.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SecSpecial( Aig_Man_t * pPart0, Aig_Man_t * pPart1, int fVerbose ) +{ + extern int Fra_FraigCec( Aig_Man_t ** ppAig, int nConfLimit, int fVerbose ); + int nFrames = 2; // modify to enable comparison over any number of frames + Aig_Man_t * pMiterCec; + int RetValue, clkTotal = clock(); +// assert( Aig_ManNodeNum(pPart0) <= Aig_ManNodeNum(pPart1) ); + if ( Aig_ManNodeNum(pPart0) >= Aig_ManNodeNum(pPart1) ) + { + printf( "Warning: The design after synthesis is smaller!\n" ); + printf( "This warning may indicate that the order of designs is changed.\n" ); + printf( "The solver expects the original disign as first argument and\n" ); + printf( "the modified design as the second argument in Ssw_SecSpecial().\n" ); + } + // create two-level miter + pMiterCec = Saig_ManCreateMiterTwo( pPart0, pPart1, nFrames ); + if ( fVerbose ) + { + Aig_ManPrintStats( pMiterCec ); +// Aig_ManDumpBlif( pMiterCec, "miter01.blif", NULL, NULL ); +// printf( "The new miter is written into file \"%s\".\n", "miter01.blif" ); + } + // run CEC on this miter + RetValue = Fra_FraigCec( &pMiterCec, 100000, fVerbose ); + // transfer model if given +// if ( pNtk2 == NULL ) +// pNtk1->pModel = pMiterCec->pData, pMiterCec->pData = NULL; + Aig_ManStop( pMiterCec ); + // report the miter + if ( RetValue == 1 ) + { + printf( "Networks are equivalent. " ); +PRT( "Time", clock() - clkTotal ); + } + else if ( RetValue == 0 ) + { + printf( "Networks are NOT EQUIVALENT. " ); +PRT( "Time", clock() - clkTotal ); + } + else + { + printf( "Networks are UNDECIDED. " ); +PRT( "Time", clock() - clkTotal ); + } + fflush( stdout ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Reduces SEC to CEC for the special case of seq synthesis.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SecSpecialMiter( Aig_Man_t * pMiter, int fVerbose ) +{ + Aig_Man_t * pPart0, * pPart1; + int RetValue; + if ( fVerbose ) + Aig_ManPrintStats( pMiter ); + // demiter the miter + if ( !Saig_ManDemiterSimple( pMiter, &pPart0, &pPart1 ) ) + { + printf( "Demitering has failed.\n" ); + return -1; + } + if ( fVerbose ) + { + Aig_ManPrintStats( pPart0 ); + Aig_ManPrintStats( pPart1 ); +// 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" ); + } + RetValue = Ssw_SecSpecial( pPart0, pPart1, fVerbose ); + Aig_ManStop( pPart0 ); + Aig_ManStop( pPart1 ); + return RetValue; +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/aig/saig/saigSynch.c b/src/aig/saig/saigSynch.c index 9dbbb420b..eb0fefc9f 100644 --- a/src/aig/saig/saigSynch.c +++ b/src/aig/saig/saigSynch.c @@ -451,6 +451,40 @@ Vec_Str_t * Saig_SynchSequence( Aig_Man_t * pAig, int nWords ) return vSequence; } +/**Function************************************************************* + + Synopsis [Duplicates the AIG to have constant-0 initial state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManDupInitZero( Aig_Man_t * p ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj; + int i; + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Aig_UtilStrsav( p->pName ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Saig_ManForEachPi( p, pObj, i ) + pObj->pData = Aig_ObjCreatePi( pNew ); + Saig_ManForEachLo( p, pObj, i ) + pObj->pData = Aig_NotCond( Aig_ObjCreatePi( pNew ), pObj->fMarkA ); + Aig_ManForEachNode( p, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + Saig_ManForEachPo( p, pObj, i ) + pObj->pData = Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); + Saig_ManForEachLi( p, pObj, i ) + pObj->pData = Aig_ObjCreatePo( pNew, Aig_NotCond( Aig_ObjChild0Copy(pObj), pObj->fMarkA ) ); + Aig_ManSetRegNum( pNew, Saig_ManRegNum(p) ); + assert( Aig_ManNodeNum(pNew) == Aig_ManNodeNum(p) ); + return pNew; +} + /**Function************************************************************* Synopsis [Determines synchronizing sequence using ternary simulation.] diff --git a/src/aig/ssw/ssw.h b/src/aig/ssw/ssw.h index 766407d48..e6e3a1b47 100644 --- a/src/aig/ssw/ssw.h +++ b/src/aig/ssw/ssw.h @@ -55,6 +55,7 @@ struct Ssw_Pars_t_ int fSemiFormal; // enable semiformal filtering int fUniqueness; // enable uniqueness constraints int fVerbose; // verbose stats + int fFlopVerbose; // verbose printout of redundant flops // optimized latch correspondence int fLatchCorrOpt; // perform register correspondence (optimized) int nSatVarMax; // max number of SAT vars before recycling SAT solver (optimized latch corr only) @@ -92,6 +93,8 @@ extern Aig_Man_t * Ssw_SignalCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pP extern Aig_Man_t * Ssw_LatchCorrespondence( Aig_Man_t * pAig, Ssw_Pars_t * pPars ); /*=== sswLoc.c ==========================================================*/ extern int Saig_ManLocalization( Aig_Man_t * p, int nFramesMax, int nConfMax, int fVerbose ); +/*=== sswMiter.c ===================================================*/ +extern int Ssw_SecSpecialMiter( Aig_Man_t * pMiter, int fVerbose ); /*=== sswPart.c ==========================================================*/ extern Aig_Man_t * Ssw_SignalCorrespondencePart( Aig_Man_t * pAig, Ssw_Pars_t * pPars ); /*=== sswPairs.c ===================================================*/ diff --git a/src/aig/ssw/sswPart.c b/src/aig/ssw/sswPart.c index 7eb6b8fef..983a20220 100644 --- a/src/aig/ssw/sswPart.c +++ b/src/aig/ssw/sswPart.c @@ -97,12 +97,14 @@ Aig_Man_t * Ssw_SignalCorrespondencePart( Aig_Man_t * pAig, Ssw_Pars_t * pPars ) if ( pAig->vOnehots ) pTemp->vOnehots = Aig_ManRegProjectOnehots( pAig, pTemp, pAig->vOnehots, fVerbose ); // run SSW - 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 ); + 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 ); free( pMapBack ); } diff --git a/src/aig/ssw_old/module.make b/src/aig/ssw_old/module.make new file mode 100644 index 000000000..625d72d1b --- /dev/null +++ b/src/aig/ssw_old/module.make @@ -0,0 +1,14 @@ +SRC += src/aig/ssw/sswAig.c \ + src/aig/ssw/sswBmc.c \ + src/aig/ssw/sswClass.c \ + src/aig/ssw/sswCnf.c \ + src/aig/ssw/sswCore.c \ + src/aig/ssw/sswLcorr.c \ + src/aig/ssw/sswMan.c \ + src/aig/ssw/sswPart.c \ + src/aig/ssw/sswPairs.c \ + src/aig/ssw/sswSat.c \ + src/aig/ssw/sswSim.c \ + src/aig/ssw/sswSimSat.c \ + src/aig/ssw/sswSweep.c \ + src/aig/ssw/sswUnique.c diff --git a/src/aig/ssw_old/ssw.h b/src/aig/ssw_old/ssw.h new file mode 100644 index 000000000..766407d48 --- /dev/null +++ b/src/aig/ssw_old/ssw.h @@ -0,0 +1,117 @@ +/**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 __SSW_H__ +#define __SSW_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// 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 nConstrs; // treat the last nConstrs POs as seq constraints + int nMaxLevs; // the max number of levels of nodes to consider + int nBTLimit; // conflict limit at a node + int nMinDomSize; // min clock domain considered for optimization + int fPolarFlip; // uses polarity adjustment + int fSkipCheck; // do not run equivalence check for unaffected cones + int fLatchCorr; // perform register correspondence + int fSemiFormal; // enable semiformal filtering + int fUniqueness; // enable uniqueness constraints + int fVerbose; // verbose stats + // 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) + // internal parameters + int nIters; // the number of iterations performed +}; + +// sequential counter-example +typedef struct Ssw_Cex_t_ Ssw_Cex_t; +struct Ssw_Cex_t_ +{ + int iPo; // the zero-based number of PO, for which verification failed + int iFrame; // the zero-based number of the time-frame, for which verificaiton failed + int nRegs; // the number of registers in the miter + int nPis; // the number of primary inputs in the miter + int nBits; // the number of words of bit data used + unsigned pData[0]; // the cex bit data (the number of bits: nRegs + (iFrame+1) * nPis) +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== sswAbs.c ==========================================================*/ +extern Aig_Man_t * Saig_ManProofAbstraction( Aig_Man_t * p, int nFrames, int nConfMax, int fVerbose ); +/*=== 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 ); +/*=== sswLoc.c ==========================================================*/ +extern int Saig_ManLocalization( Aig_Man_t * p, int nFramesMax, int nConfMax, int fVerbose ); +/*=== sswPart.c ==========================================================*/ +extern Aig_Man_t * Ssw_SignalCorrespondencePart( Aig_Man_t * pAig, Ssw_Pars_t * pPars ); +/*=== sswPairs.c ===================================================*/ +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 ); +/*=== sswSim.c ===================================================*/ +extern Ssw_Cex_t * Ssw_SmlAllocCounterExample( int nRegs, int nRealPis, int nFrames ); +extern void Ssw_SmlFreeCounterExample( Ssw_Cex_t * pCex ); +extern int Ssw_SmlRunCounterExample( Aig_Man_t * pAig, Ssw_Cex_t * p ); +extern int Ssw_SmlFindOutputCounterExample( Aig_Man_t * pAig, Ssw_Cex_t * p ); +extern Ssw_Cex_t * Ssw_SmlDupCounterExample( Ssw_Cex_t * p, int nRegsNew ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/aig/ssw_old/sswAig.c b/src/aig/ssw_old/sswAig.c new file mode 100644 index 000000000..7b6d1bb0a --- /dev/null +++ b/src/aig/ssw_old/sswAig.c @@ -0,0 +1,205 @@ +/**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" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**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; + 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 + 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 ) + Ssw_ObjSetFrame( p, pObj, f, Aig_ObjCreatePi(pFrames) ); + // 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 latch input to the latch outputs + Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) + Ssw_ObjSetFrame( p, pObjLo, f+1, Ssw_ObjChild0Fra(p, pObjLi,f) ); + } + // 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 ) ); + for ( f = 0; f <= p->pPars->nFramesK; f++ ) + Saig_ManForEachLo( p->pAig, pObj, i ) + Aig_ObjCreatePo( pFrames, Ssw_ObjFrame( p, pObj, f ) ); + + // 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 ); + // 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 /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ssw_old/sswBmc.c b/src/aig/ssw_old/sswBmc.c new file mode 100644 index 000000000..e2d474406 --- /dev/null +++ b/src/aig/ssw_old/sswBmc.c @@ -0,0 +1,315 @@ +/**CFile**************************************************************** + + FileName [sswBmc.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Inductive prover with constraints.] + + Synopsis [Bounded model checker for equivalence clases.] + + 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" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Ssw_Bmc_t_ Ssw_Bmc_t; // BMC manager + +struct Ssw_Bmc_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_Bmc_t * Ssw_BmcManStart( Ssw_Man_t * pMan, int nConfMax, int fVerbose ) +{ + Ssw_Bmc_t * p; + Aig_Obj_t * pObj; + int i; + // create interpolation manager + p = ALLOC( Ssw_Bmc_t, 1 ); + memset( p, 0, sizeof(Ssw_Bmc_t) ); + p->nConfMaxStart = nConfMax; + p->nConfMax = nConfMax; + p->nFramesSweep = AIG_MAX( (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), Aig_BitWordNum(p->nPatternsAlloc) ); + Vec_PtrCleanSimInfo( p->vPatterns, 0, Aig_BitWordNum(p->nPatternsAlloc) ); + p->vHistory = Vec_IntAlloc( 100 ); + Vec_IntPush( p->vHistory, 0 ); + // update arrays of the manager + free( p->pMan->pNodeToFrames ); + Vec_IntFree( p->pMan->vSatVars ); + p->pMan->pNodeToFrames = 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_BmcManStop( Ssw_Bmc_t * p ) +{ + Vec_PtrFree( p->vTargets ); + Vec_PtrFree( p->vPatterns ); + Vec_IntFree( p->vHistory ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_BmcCheckTargets( Ssw_Bmc_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Vec_PtrForEachEntry( p->vTargets, pObj, i ) + if ( !Ssw_ObjIsConst1Cand(p->pMan->pAig, pObj) ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManFilterBmcSavePattern( Ssw_Bmc_t * p ) +{ + unsigned * pInfo; + Aig_Obj_t * pObj; + int i; + if ( p->nPatterns >= p->nPatternsAlloc ) + return; + Saig_ManForEachLo( p->pMan->pAig, pObj, i ) + { + pInfo = Vec_PtrEntry( p->vPatterns, i ); + if ( Aig_InfoHasBit( p->pMan->pPatWords, Saig_ManPiNum(p->pMan->pAig) + i ) ) + Aig_InfoSetBit( pInfo, p->nPatterns ); + } + p->nPatterns++; +} + +/**Function************************************************************* + + Synopsis [Performs fraiging for the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ManFilterBmc( Ssw_Bmc_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 = Vec_PtrEntry( pBmc->vPatterns, i ); + pObjNew = Aig_NotCond( Aig_ManConst1(p->pFrames), !Aig_InfoHasBit(pInfo, iPat) ); + Ssw_ObjSetFrame( p, pObj, 0, pObjNew ); + } + + // sweep internal nodes + Ssw_ManStartSolver( p ); + 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 ) ) + { + Ssw_ManFilterBmcSavePattern( pBmc ); + if ( fFirst == 0 ) + { + fFirst = 1; + pBmc->nConfMax *= 10; + } + } + if ( f > 0 && p->pSat->stats.conflicts >= pBmc->nConfMax ) + { + RetValue = -1; + break; + } + } + // quit if this is the last timeframe + if ( p->pSat->stats.conflicts >= pBmc->nConfMax ) + { + RetValue += f + 1; + break; + } + if ( fCheckTargets && Ssw_BmcCheckTargets( 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, 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_FilterUsingBmc( Ssw_Man_t * pMan, int fCheckTargets, int nConfMax, int fVerbose ) +{ + Ssw_Bmc_t * p; + int RetValue, Frames, Iter, clk = clock(); + p = Ssw_BmcManStart( pMan, nConfMax, fVerbose ); + if ( fCheckTargets && Ssw_BmcCheckTargets( p ) ) + { + assert( 0 ); + Ssw_BmcManStop( p ); + return 1; + } + if ( fVerbose ) + { + printf( "AIG : Const = %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(); + Frames = Ssw_ManFilterBmc( p, Iter, fCheckTargets ); + if ( fVerbose ) + { + printf( "%3d : Const = %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->pSat->stats.conflicts, p->nPatterns, + p->pMan->nSatFailsReal? "f" : " " ); + PRT( "T", clock() - clk ); + } + Ssw_ManCleanup( p->pMan ); + if ( fCheckTargets && Ssw_BmcCheckTargets( p ) ) + { + printf( "Target is hit!!!\n" ); + RetValue = 1; + } + if ( p->nPatterns >= p->nPatternsAlloc ) + break; + } + Ssw_BmcManStop( p ); + + pMan->nStrangers = 0; + pMan->nSatCalls = 0; + pMan->nSatProof = 0; + pMan->nSatFailsReal = 0; + pMan->nSatFailsTotal = 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 /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ssw_old/sswClass.c b/src/aig/ssw_old/sswClass.c new file mode 100644 index 000000000..cfbb138c7 --- /dev/null +++ b/src/aig/ssw_old/sswClass.c @@ -0,0 +1,941 @@ +/**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" + +/* + 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 + // 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 = ALLOC( Ssw_Cla_t, 1 ); + memset( p, 0, sizeof(Ssw_Cla_t) ); + p->pAig = pAig; + p->pId2Class = CALLOC( Aig_Obj_t **, Aig_ManObjNumMax(pAig) ); + p->pClassSizes = CALLOC( int, Aig_ManObjNumMax(pAig) ); + p->vClassOld = Vec_PtrAlloc( 100 ); + p->vClassNew = Vec_PtrAlloc( 100 ); + p->vRefined = Vec_PtrAlloc( 1000 ); + assert( 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 ); + FREE( p->pId2Class ); + FREE( p->pClassSizes ); + FREE( p->pMemClasses ); + 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) ", pObj->Id, pObj->Level, Aig_SupportSize(p->pAig,pObj) ); + 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( "Equivalence 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) ", pObj->Id, pObj->Level, Aig_SupportSize(p->pAig,pObj) ); + 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 [Creates initial simulation classes.] + + Description [Assumes that simulation info is assigned.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ssw_Cla_t * Ssw_ClassesPrepare( Aig_Man_t * pAig, int fLatchCorr, int nMaxLevs, int fVerbose ) +{ + Ssw_Cla_t * p; + Ssw_Sml_t * pSml; + Aig_Obj_t ** ppTable, ** ppNexts, ** ppClassNew; + Aig_Obj_t * pObj, * pTemp, * pRepr; + int i, k, nTableSize, nNodes, iEntry, nEntries, nEntries2; + int clk; + + // start the classes + p = Ssw_ClassesStart( pAig ); + + // perform sequential simulation +clk = clock(); + pSml = Ssw_SmlSimulateSeq( pAig, 0, 32, 4 ); +if ( fVerbose ) +{ +PRT( "Simulation of 32 frames with 4 words", clock() - clk ); +} + + // set comparison procedures +clk = clock(); + Ssw_ClassesSetData( p, pSml, Ssw_SmlObjHashWord, Ssw_SmlObjIsConstWord, Ssw_SmlObjsAreEqualWord ); + + // allocate the hash table hashing simulation info into nodes + nTableSize = Aig_PrimeCudd( Aig_ManObjNumMax(p->pAig)/4 ); + ppTable = CALLOC( Aig_Obj_t *, nTableSize ); + ppNexts = 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 ( !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; + } + // 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; + } + // 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++; + } + } + + // allocate room for classes + p->pMemClasses = 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 = 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; + } + assert( nEntries == nEntries2 ); + free( ppTable ); + free( ppNexts ); + + // now it is time to refine the classes + Ssw_ClassesRefine( p, 1 ); + Ssw_ClassesCheck( p ); + Ssw_SmlStop( pSml ); +// Ssw_ClassesPrint( p, 0 ); +if ( fVerbose ) +{ +PRT( "Collecting candidate equival classes", clock() - clk ); +} + 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 = 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_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 = 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 = 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 [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 = 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( p->vClassOld, pObj, i ) + { + pClassOld[i] = pObj; + Aig_ObjSetRepr( p->pAig, pObj, i? pReprOld : NULL ); + } + // create new class + pClassNew = pClassOld + i; + Vec_PtrForEachEntry( 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 [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( 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 = 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( 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; + p->nCands1 -= Vec_PtrSize(p->vClassNew); + pReprNew = 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( 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 /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ssw_old/sswCnf.c b/src/aig/ssw_old/sswCnf.c new file mode 100644 index 000000000..e4b8f9f67 --- /dev/null +++ b/src/aig/ssw_old/sswCnf.c @@ -0,0 +1,335 @@ +/**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" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Addes clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_AddClausesMux( Ssw_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 = 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->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 Ssw_AddClausesSuper( Ssw_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 = ALLOC( int, nLits ); + // suppose AND-gate is A & B = C + // add !A => !C or A + !C + Vec_PtrForEachEntry( 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->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( vSuper, pFanin, i ) + { + pLits[i] = toLitCond(Ssw_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(Ssw_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 ); + 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; + } + // 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_Man_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; + if ( p->pPars->fLatchCorrOpt ) + { + Vec_PtrPush( p->vUsedNodes, pObj ); + 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_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 ( Ssw_ObjSatNum(p,pObj) ) + return; + // start the frontier + vFrontier = Vec_PtrAlloc( 100 ); + Ssw_ObjAddToFrontier( p, pObj, vFrontier ); + // explore nodes in the frontier + Vec_PtrForEachEntry( 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( p->vFanins, pFanin, k ) + Ssw_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier ); + Ssw_AddClausesMux( p, pNode ); + } + else + { + Ssw_CollectSuper( pNode, fUseMuxes, p->vFanins ); + Vec_PtrForEachEntry( 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 ); +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ssw_old/sswCore.c b/src/aig/ssw_old/sswCore.c new file mode 100644 index 000000000..5b33d96c2 --- /dev/null +++ b/src/aig/ssw_old/sswCore.c @@ -0,0 +1,293 @@ +/**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" + +//////////////////////////////////////////////////////////////////////// +/// 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 = 0; // additional frames to simulate + p->nConstrs = 0; // treat the last nConstrs POs as seq constraints + p->nBTLimit = 1000; // conflict limit at a node + p->nMinDomSize = 100; // min clock domain considered for optimization + p->fPolarFlip = 0; // uses polarity adjustment + p->fSkipCheck = 0; // do not run equivalence check for unaffected cones + p->fLatchCorr = 0; // performs register correspondence + p->fSemiFormal = 0; // enable semiformal filtering + p->fUniqueness = 0; // enable uniqueness constraints + p->fVerbose = 0; // verbose stats + // 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 + // 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 [Performs computation of signal correspondence with constraints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Ssw_SignalCorrespondenceRefine( Ssw_Man_t * p ) +{ + int nSatProof, nSatCallsSat, nRecycles, nSatFailsReal; + Aig_Man_t * pAigNew; + int RetValue, nIter; + 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 ) + { + Ssw_ManSweepBmc( p ); + 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_FilterUsingBmc( p, 0, 2000, p->pPars->fVerbose ); +// Ssw_FilterUsingBmc( p, 1, 100000, p->pPars->fVerbose ); + pSRed = Ssw_SpeculativeReduction( p ); + Aig_ManDumpBlif( pSRed, "srm.blif", NULL, NULL ); + Aig_ManStop( pSRed ); + } + // refine classes using induction + nSatProof = nSatCallsSat = nRecycles = nSatFailsReal = 0; + for ( nIter = 0; ; nIter++ ) + { +clk = clock(); + if ( p->pPars->fLatchCorrOpt ) + { + RetValue = Ssw_ManSweepLatch( p ); + if ( p->pPars->fVerbose ) + { + printf( "%3d : Const = %6d. Cl = %6d. Pr = %5d. Cex = %5d. Rcl = %3d. F = %3d. ", + nIter, Ssw_ClassesCand1Num(p->ppClasses), Ssw_ClassesClassNum(p->ppClasses), + p->nSatProof-nSatProof, p->nSatCallsSat-nSatCallsSat, + p->nRecycles-nRecycles, p->nSatFailsReal-nSatFailsReal ); + PRT( "T", clock() - clk ); + nSatProof = p->nSatProof; + nSatCallsSat = p->nSatCallsSat; + nRecycles = p->nRecycles; + nSatFailsReal = p->nSatFailsReal; + } + } + else + { +// if ( nIter == 6 ) +// p->pPars->fUniqueness = 0; + + RetValue = Ssw_ManSweep( p ); + if ( p->pPars->fVerbose ) + { + printf( "%3d : Const = %6d. Cl = %6d. LR = %6d. NR = %6d. U = %3d. F = %2d. ", + nIter, Ssw_ClassesCand1Num(p->ppClasses), Ssw_ClassesClassNum(p->ppClasses), + p->nConstrReduced, Aig_ManNodeNum(p->pFrames), p->nUniques, p->nSatFailsReal ); + if ( p->pPars->fSkipCheck ) + printf( "Use = %5d. Skip = %5d. ", + p->nRefUse, p->nRefSkip ); + PRT( "T", clock() - clk ); + } + } + Ssw_ManCleanup( p ); + if ( !RetValue ) + break; +/* + { + static int Flag = 0; + if ( Flag++ == 4 && nIter == 4 ) + { + Aig_Man_t * pSRed; + pSRed = Ssw_SpeculativeReduction( p ); + Aig_ManDumpBlif( pSRed, "srm.blif", NULL, NULL ); + Aig_ManStop( pSRed ); + } + } +*/ + + } + p->pPars->nIters = nIter + 1; +p->timeTotal = clock() - clkTotal; + pAigNew = Aig_ManDupRepr( p->pAig, 0 ); + Aig_ManSeqCleanup( pAigNew ); + // get the final stats + p->nLitsEnd = Ssw_ClassesLitNum( p->ppClasses ); + p->nNodesEnd = Aig_ManNodeNum(pAigNew); + p->nRegsEnd = Aig_ManRegNum(pAigNew); + 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; + } + else + { + assert( pPars->nFramesK > 0 ); + if ( pPars->nFramesK > 1 ) + pPars->fSkipCheck = 0; + // perform partitioning + if ( (pPars->nPartSize > 0 && pPars->nPartSize < Aig_ManRegNum(pAig)) + || (pAig->vClockDoms && Vec_VecSize(pAig->vClockDoms) > 0) ) + return Ssw_SignalCorrespondencePart( pAig, pPars ); + } + // start the induction manager + p = Ssw_ManCreate( pAig, pPars ); + // compute candidate equivalence classes +// p->pPars->nConstrs = 1; + if ( p->pPars->nConstrs == 0 ) + { + // perform one round of seq simulation and generate candidate equivalence classes + p->ppClasses = Ssw_ClassesPrepare( pAig, pPars->fLatchCorr, pPars->nMaxLevs, pPars->fVerbose ); +// p->ppClasses = Ssw_ClassesPrepareTargets( pAig ); +// p->pSml = Ssw_SmlStart( pAig, 0, p->nFrames + p->pPars->nFramesAddSim, 1 ); + p->pSml = Ssw_SmlStart( pAig, 0, 1, 1 ); + Ssw_ClassesSetData( p->ppClasses, p->pSml, Ssw_SmlObjHashWord, Ssw_SmlObjIsConstWord, Ssw_SmlObjsAreEqualWord ); + } + else + { + // 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 ); + } + // perform refinement of classes + pAigNew = Ssw_SignalCorrespondenceRefine( p ); + // 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 ) +{ + Ssw_Pars_t Pars; + if ( pPars == NULL ) + Ssw_ManSetDefaultParamsLcorr( pPars = &Pars ); + return Ssw_SignalCorrespondence( pAig, pPars ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ssw_old/sswInt.h b/src/aig/ssw_old/sswInt.h new file mode 100644 index 000000000..d7bf46a8c --- /dev/null +++ b/src/aig/ssw_old/sswInt.h @@ -0,0 +1,232 @@ +/**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 __SSW_INT_H__ +#define __SSW_INT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "saig.h" +#include "satSolver.h" +#include "ssw.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Ssw_Man_t_ Ssw_Man_t; // signal correspondence manager +typedef struct Ssw_Cla_t_ Ssw_Cla_t; // equivalence classe manager +typedef struct Ssw_Sml_t_ Ssw_Sml_t; // sequential simulation 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 + int nRefUse; // the number of equivalences used + int nRefSkip; // the number of equivalences skipped + // SAT solving + 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 + int nSatVarsTotal; // the total number of SAT vars created + Vec_Ptr_t * vFanins; // fanins of the CNF node + // SAT solving (latch corr only) + Vec_Ptr_t * vUsedNodes; // the nodes with SAT variables + Vec_Ptr_t * vUsedPis; // the PIs with SAT variables + 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 nConeMax; // the maximum cone size + // uniqueness + Vec_Ptr_t * vCommon; // the set of common variables in the logic cones + int iOutputLit; // the output literal of the uniqueness constaint + int nUniques; // the number of uniqueness constaints used + // sequential simulator + Ssw_Sml_t * pSml; + // counter example storage + int nPatWords; // the number of words in the counter example + unsigned * pPatWords; // the counter example + unsigned * pPatWords2; // 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 nSatFailsTotal; // 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; + // 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 +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Ssw_ObjSatNum( Ssw_Man_t * p, Aig_Obj_t * pObj ) { return Vec_IntEntry( p->vSatVars, pObj->Id ); } +static inline void Ssw_ObjSetSatNum( Ssw_Man_t * p, Aig_Obj_t * pObj, int Num ) { Vec_IntWriteEntryFill( 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; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== sswAig.c ===================================================*/ +extern Aig_Man_t * Ssw_FramesWithClasses( Ssw_Man_t * p ); +extern Aig_Man_t * Ssw_SpeculativeReduction( Ssw_Man_t * p ); +/*=== sswBmc.c ===================================================*/ +extern int Ssw_FilterUsingBmc( Ssw_Man_t * pMan, int fCheckTargets, int nConfMax, int fVerbose ); +/*=== 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 fLatchCorr, int nMaxLevs, int fVerbose ); +extern Ssw_Cla_t * Ssw_ClassesPrepareSimple( Aig_Man_t * pAig, int fLatchCorr, int nMaxLevs ); +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 int Ssw_ClassesRefine( Ssw_Cla_t * p, 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 ); +/*=== sswCnf.c ===================================================*/ +extern void Ssw_CnfNodeAddToSolver( Ssw_Man_t * p, Aig_Obj_t * pObj ); +/*=== sswCore.c ===================================================*/ +extern Aig_Man_t * Ssw_SignalCorrespondenceRefine( 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 ); +extern void Ssw_ManStartSolver( 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 ); +/*=== 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 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 unsigned Ssw_SmlObjGetWord( Ssw_Sml_t * p, Aig_Obj_t * pObj, int iWord, 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 Ssw_Sml_t * Ssw_SmlSimulateSeq( Aig_Man_t * pAig, int nPref, int nFrames, int nWords ); +/*=== 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 ); +extern void Ssw_ManResimulateWord2( 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 int Ssw_ManSweepNode( Ssw_Man_t * p, Aig_Obj_t * pObj, int f, int fBmc ); +extern int Ssw_ManSweepBmc( Ssw_Man_t * p ); +extern int Ssw_ManSweep( Ssw_Man_t * p ); +/*=== sswUnique.c ===================================================*/ +extern int Ssw_ManUniqueOne( Ssw_Man_t * p, Aig_Obj_t * pRepr, Aig_Obj_t * pObj ); +extern int Ssw_ManUniqueAddConstraint( Ssw_Man_t * p, Vec_Ptr_t * vCommon, int f1, int f2 ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/aig/ssw_old/sswLcorr.c b/src/aig/ssw_old/sswLcorr.c new file mode 100644 index 000000000..cde9b0c98 --- /dev/null +++ b/src/aig/ssw_old/sswLcorr.c @@ -0,0 +1,364 @@ +/**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" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Recycles the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManSatSolverRecycle( Ssw_Man_t * p ) +{ + int Lit; + if ( p->pSat ) + { + Aig_Obj_t * pObj; + int i; + Vec_PtrForEachEntry( p->vUsedNodes, pObj, i ) + Ssw_ObjSetSatNum( p, pObj, 0 ); + Vec_PtrClear( p->vUsedNodes ); + Vec_PtrClear( p->vUsedPis ); +// 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 ); + Ssw_ObjSetSatNum( p, Aig_ManConst1(p->pFrames), p->nSatVars++ ); + + p->nRecycles++; + p->nRecycleCalls = 0; +} + + +/**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 = 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( p->vUsedPis, pObj, i ) + { + nVarNum = Ssw_ObjSatNum( p, pObj ); + assert( nVarNum > 0 ); + Value = sat_solver_var_value( p->pSat, nVarNum ); + if ( Value == 0 ) + continue; + pInfo = Vec_PtrEntry( p->vSimInfo, Aig_ObjPioNum(pObj) ); + Aig_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( 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->nSatVars > p->pPars->nSatVarMax && + p->nRecycleCalls > p->pPars->nRecycleCalls ) + Ssw_ManSatSolverRecycle( p ); + } + // resimulate + if ( p->nPatterns > 0 ) + Ssw_ManSweepResimulate( p ); + // cleanup + Vec_PtrFree( vClass ); + p->nSatFailsTotal += p->nSatFailsReal; +// if ( p->pPars->fVerbose ) +// Bar_ProgressStop( pProgress ); + + // cleanup +// Ssw_ClassesCheck( p->ppClasses ); + return p->fRefined; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ssw_old/sswMan.c b/src/aig/ssw_old/sswMan.c new file mode 100644 index 000000000..84b041b45 --- /dev/null +++ b/src/aig/ssw_old/sswMan.c @@ -0,0 +1,237 @@ +/**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" + +//////////////////////////////////////////////////////////////////////// +/// 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 = 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 = CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) * p->nFrames ); + // SAT solving + p->vSatVars = Vec_IntStart( Aig_ManObjNumMax(p->pAig) * (p->nFrames+1) ); + p->vFanins = Vec_PtrAlloc( 100 ); + // SAT solving (latch corr only) + p->vUsedNodes = Vec_PtrAlloc( 1000 ); + p->vUsedPis = Vec_PtrAlloc( 1000 ); + p->vCommon = Vec_PtrAlloc( 100 ); + p->iOutputLit = -1; + // allocate storage for sim pattern + p->nPatWords = Aig_BitWordNum( Saig_ManPiNum(pAig) * p->nFrames + Saig_ManRegNum(pAig) ); + p->pPatWords = ALLOC( unsigned, p->nPatWords ); + p->pPatWords2 = ALLOC( unsigned, p->nPatWords ); + 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, p->pPars->nConstrs, 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), + p->nSatVarsTotal/p->pPars->nIters ); + printf( "SAT calls : Proof = %d. Cex = %d. Fail = %d. Equivs = %d. Str = %d.\n", + p->nSatProof, p->nSatCallsSat, p->nSatFailsTotal, Ssw_ManCountEquivs(p), p->nStrangers ); + printf( "SAT solver: Vars = %d. Max cone = %d. Recycles = %d. Rounds = %d.\n", + p->nSatVars, p->nConeMax, p->nRecycles, 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; + PRTP( "BMC ", p->timeBmc, p->timeTotal ); + PRTP( "Spec reduce", p->timeReduce, p->timeTotal ); + PRTP( "Mark cones ", p->timeMarkCones, p->timeTotal ); + PRTP( "Sim SAT ", p->timeSimSat, p->timeTotal ); + PRTP( "SAT solving", p->timeSat, p->timeTotal ); + PRTP( " unsat ", p->timeSatUnsat, p->timeTotal ); + PRTP( " sat ", p->timeSatSat, p->timeTotal ); + PRTP( " undecided", p->timeSatUndec, p->timeTotal ); + PRTP( "Other ", p->timeOther, p->timeTotal ); + PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); +} + +/**Function************************************************************* + + Synopsis [Frees the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManCleanup( Ssw_Man_t * p ) +{ + if ( 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->pSat ) + { + int i; +// printf( "Vars = %d. Clauses = %d. Learnts = %d.\n", p->pSat->size, p->pSat->clauses.size, p->pSat->learnts.size ); + p->nSatVarsTotal += p->pSat->size; + sat_solver_delete( p->pSat ); + p->pSat = NULL; +// memset( p->pSatVars, 0, sizeof(int) * Aig_ManObjNumMax(p->pAig) * (p->nFrames+1) ); + for ( i = 0; i < Vec_IntSize(p->vSatVars); i++ ) + p->vSatVars->pArray[i] = 0; + } + 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 ) +{ + Aig_ManCleanMarkA( p->pAig ); + Aig_ManCleanMarkB( p->pAig ); + if ( p->pPars->fVerbose ) + Ssw_ManPrintStats( p ); + if ( p->ppClasses ) + Ssw_ClassesStop( p->ppClasses ); + if ( p->pSml ) + Ssw_SmlStop( p->pSml ); + Vec_PtrFree( p->vFanins ); + Vec_PtrFree( p->vUsedNodes ); + Vec_PtrFree( p->vUsedPis ); + Vec_IntFree( p->vSatVars ); + Vec_PtrFree( p->vCommon ); + FREE( p->pNodeToFrames ); + FREE( p->pPatWords ); + FREE( p->pPatWords2 ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Starts the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManStartSolver( Ssw_Man_t * p ) +{ + int Lit; + assert( p->pSat == NULL ); + 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 ( p->pPars->fPolarFlip ) + Lit = lit_neg( Lit ); + sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); + Ssw_ObjSetSatNum( p, Aig_ManConst1(p->pAig), p->nSatVars++ ); + + Vec_PtrClear( p->vUsedNodes ); + Vec_PtrClear( p->vUsedPis ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ssw_old/sswPairs.c b/src/aig/ssw_old/sswPairs.c new file mode 100644 index 000000000..c77ad30da --- /dev/null +++ b/src/aig/ssw_old/sswPairs.c @@ -0,0 +1,470 @@ +/**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" + +//////////////////////////////////////////////////////////////////////// +/// 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(pObj1->pData); + pObj2m = Aig_Regular(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 = CALLOC( Vec_Int_t *, nObjNumMax ); + pReprs = 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; + } + } + } + } + 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] ); + 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 ); + // 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, Ssw_SmlObjHashWord, Ssw_SmlObjIsConstWord, 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(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) ); + 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) ); + 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 ); + 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) ); + 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) ); + PRT( "Time", clock() - clk ); + // cleanup + Aig_ManStop( pAigRes ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ssw_old/sswPart.c b/src/aig/ssw_old/sswPart.c new file mode 100644 index 000000000..7eb6b8fef --- /dev/null +++ b/src/aig/ssw_old/sswPart.c @@ -0,0 +1,129 @@ +/**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" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs partitioned sequential SAT sweepingG.] + + 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(); + + // 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_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( 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( 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 + 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 ); + 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 ) + { + PRT( "Total time", clock() - clk ); + } + return pNew; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ssw_old/sswSat.c b/src/aig/ssw_old/sswSat.c new file mode 100644 index 000000000..85d3b8c13 --- /dev/null +++ b/src/aig/ssw_old/sswSat.c @@ -0,0 +1,264 @@ +/**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" + +//////////////////////////////////////////////////////////////////////// +/// 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++; + + // sanity checks + assert( !Aig_IsComplement(pOld) ); + assert( !Aig_IsComplement(pNew) ); + assert( pOld != pNew ); + + if ( p->pSat == NULL ) + Ssw_ManStartSolver( p ); + + // if the nodes do not have SAT variables, allocate them + Ssw_CnfNodeAddToSolver( p, pOld ); + Ssw_CnfNodeAddToSolver( p, pNew ); + + if ( p->pSat->qtail != p->pSat->qhead ) + { + RetValue = sat_solver_simplify(p->pSat); + assert( RetValue != 0 ); + } + + // solve under assumptions + // A = 1; B = 0 OR A = 1; B = 1 + nLits = 2; + pLits[0] = toLitCond( Ssw_ObjSatNum(p,pOld), 0 ); + pLits[1] = toLitCond( Ssw_ObjSatNum(p,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 ); + +clk = clock(); + RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + nLits, + (sint64)nBTLimit, (sint64)0, (sint64)0, (sint64)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->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->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,pOld), 1 ); + pLits[1] = toLitCond( Ssw_ObjSatNum(p,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->pSat->qtail != p->pSat->qhead ) + { + RetValue = sat_solver_simplify(p->pSat); + assert( RetValue != 0 ); + } +*/ +clk = clock(); + RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + nLits, + (sint64)nBTLimit, (sint64)0, (sint64)0, (sint64)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->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; +} + +/**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) ); + + // 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); + } + + // start the solver + if ( p->pSat == NULL ) + Ssw_ManStartSolver( p ); + + // if the nodes do not have SAT variables, allocate them + Ssw_CnfNodeAddToSolver( p, pOld ); + Ssw_CnfNodeAddToSolver( p, 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 constaint A = 1 ----> A + pLits[0] = toLitCond( Ssw_ObjSatNum(p,pNew), fComplNew ); + if ( p->pPars->fPolarFlip ) + { + if ( pNew->fPhase ) pLits[0] = lit_neg( pLits[0] ); + } + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 1 ); + assert( RetValue ); + } + else + { + // add constaint A = B ----> (A v !B)(!A v B) + + // (A v !B) + pLits[0] = toLitCond( Ssw_ObjSatNum(p,pOld), 0 ); + pLits[1] = toLitCond( Ssw_ObjSatNum(p,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->pSat, pLits, pLits + 2 ); + assert( RetValue ); + + // (!A v B) + pLits[0] = toLitCond( Ssw_ObjSatNum(p,pOld), 1 ); + pLits[1] = toLitCond( Ssw_ObjSatNum(p,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->pSat, pLits, pLits + 2 ); + assert( RetValue ); + } + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ssw_old/sswSim.c b/src/aig/ssw_old/sswSim.c new file mode 100644 index 000000000..3fdb5cbc5 --- /dev/null +++ b/src/aig/ssw_old/sswSim.c @@ -0,0 +1,1334 @@ +/**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" + +//////////////////////////////////////////////////////////////////////// +/// 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 [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 [Counts the number of one's in the patten of the output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SmlNodeCountOnes( Ssw_Sml_t * p, Aig_Obj_t * pObj ) +{ + unsigned * pSims; + int i, Counter = 0; + pSims = Ssw_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 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 ) + Aig_InfoXorBit( p->pPatWords, nTruePis * p->nFrames + k++ ); +} + +/**Function************************************************************* + + Synopsis [Copy pattern from the solver into the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlSavePattern( Ssw_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); + Aig_ManForEachPi( p->pFrames, pObj, i ) + if ( p->pSat->model.ptr[Ssw_ObjSatNum(p, pObj)] == l_True ) + Aig_InfoSetBit( p->pPatWords, i ); +/* + if ( p->vCex ) + { + Vec_IntClear( p->vCex ); + for ( i = 0; i < Saig_ManPiNum(p->pAig); i++ ) + Vec_IntPush( p->vCex, Aig_InfoHasBit( p->pPatWords, i ) ); + for ( i = Saig_ManPiNum(p->pFrames); i < Aig_ManPiNum(p->pFrames); i++ ) + Vec_IntPush( p->vCex, Aig_InfoHasBit( p->pPatWords, i ) ); + } +*/ + +/* + printf( "Pattern: " ); + Aig_ManForEachPi( p->pFrames, pObj, i ) + printf( "%d", Aig_InfoHasBit( p->pPatWords, i ) ); + printf( "\n" ); +*/ +} + + + +/**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 = ALLOC( int, Aig_ManPiNum(p->pAig)+1 ); + Aig_ManForEachPi( p->pAig, pObjPi, i ) + { + pModel[i] = Aig_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; + assert( Aig_ObjIsPi(pObj) ); + pSims = Ssw_ObjSim( p, pObj->Id ); + for ( i = 0; i < p->nWordsTotal; i++ ) + pSims[i] = Ssw_ObjRandomSim(); +} + +/**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( 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( 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 [] + +***********************************************************************/ +unsigned Ssw_SmlObjGetWord( Ssw_Sml_t * p, Aig_Obj_t * pObj, int iWord, int iFrame ) +{ + unsigned * pSims; +// assert( Aig_ObjIsPi(pObj) ); + pSims = Ssw_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame; + return pSims[iWord]; +} + +/**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( Aig_ObjIsPi(pObj) ); + pSims = Ssw_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame; + pSims[iWord] = Word; +} + +/**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 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, Aig_InfoHasBit(pPat, i), 0 ); + // flip one bit + Limit = AIG_MIN( Aig_ManPiNum(p->pAig), p->nWordsTotal * 32 - 1 ); + for ( i = 0; i < Limit; i++ ) + Aig_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, Aig_InfoHasBit(pPat, nTruePis * f + i), f ); + // copy the latch info + k = 0; + Saig_ManForEachLo( p->pAig, pObj, i ) + Ssw_SmlObjAssignConst( p, pObj, Aig_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 = AIG_MIN( nTruePis, p->nWordsFrame * 32 - 1 ); + for ( i = 0; i < Limit; i++ ) + Aig_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, Aig_InfoHasBit(pPat, i), 0 ); +/* + // set distance one PIs for the first frame + Limit = AIG_MIN( Saig_ManPiNum(p->pAig), p->nWordsFrame * 32 - 1 ); + for ( i = 0; i < Limit; i++ ) + Aig_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( !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( !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( !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( !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 [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 ( !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 ); + // quit if this is the last timeframe + if ( f == p->nFrames - 1 ) + break; + // copy simulation info into outputs + Saig_ManForEachLi( p->pAig, pObj, i ) + Ssw_SmlNodeCopyFanin( p, pObj, f ); + // 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 [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 *)malloc( 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 [Deallocates simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlStop( Ssw_Sml_t * p ) +{ + 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 [Allocates a counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ssw_Cex_t * Ssw_SmlAllocCounterExample( int nRegs, int nRealPis, int nFrames ) +{ + Ssw_Cex_t * pCex; + int nWords = Aig_BitWordNum( nRegs + nRealPis * nFrames ); + pCex = (Ssw_Cex_t *)malloc( sizeof(Ssw_Cex_t) + sizeof(unsigned) * nWords ); + memset( pCex, 0, sizeof(Ssw_Cex_t) + sizeof(unsigned) * nWords ); + pCex->nRegs = nRegs; + pCex->nPis = nRealPis; + pCex->nBits = nRegs + nRealPis * nFrames; + return pCex; +} + +/**Function************************************************************* + + Synopsis [Frees the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlFreeCounterExample( Ssw_Cex_t * pCex ) +{ + free( pCex ); +} + +/**Function************************************************************* + + Synopsis [Resimulates the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SmlRunCounterExample( Aig_Man_t * pAig, Ssw_Cex_t * p ) +{ + Ssw_Sml_t * pSml; + Aig_Obj_t * pObj; + int RetValue, i, k, iBit; + assert( Aig_ManRegNum(pAig) > 0 ); + assert( Aig_ManRegNum(pAig) < Aig_ManPiNum(pAig) ); + // start a new sequential simulator + pSml = Ssw_SmlStart( pAig, 0, p->iFrame+1, 1 ); + // assign simulation info for the registers + iBit = 0; + Saig_ManForEachLo( pAig, pObj, i ) + Ssw_SmlObjAssignConst( pSml, pObj, Aig_InfoHasBit(p->pData, iBit++), 0 ); + // assign simulation info for the primary inputs + for ( i = 0; i <= p->iFrame; i++ ) + Saig_ManForEachPi( pAig, pObj, k ) + Ssw_SmlObjAssignConst( pSml, pObj, Aig_InfoHasBit(p->pData, iBit++), i ); + assert( iBit == p->nBits ); + // run random simulation + Ssw_SmlSimulateOne( pSml ); + // check if the given output has failed + RetValue = !Ssw_SmlNodeIsZero( pSml, Aig_ManPo(pAig, p->iPo) ); + Ssw_SmlStop( pSml ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Resimulates the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SmlFindOutputCounterExample( Aig_Man_t * pAig, Ssw_Cex_t * p ) +{ + Ssw_Sml_t * pSml; + Aig_Obj_t * pObj; + int i, k, iBit, iOut; + assert( Aig_ManRegNum(pAig) > 0 ); + assert( Aig_ManRegNum(pAig) < Aig_ManPiNum(pAig) ); + // start a new sequential simulator + pSml = Ssw_SmlStart( pAig, 0, p->iFrame+1, 1 ); + // assign simulation info for the registers + iBit = 0; + Saig_ManForEachLo( pAig, pObj, i ) + Ssw_SmlObjAssignConst( pSml, pObj, Aig_InfoHasBit(p->pData, iBit++), 0 ); + // assign simulation info for the primary inputs + for ( i = 0; i <= p->iFrame; i++ ) + Saig_ManForEachPi( pAig, pObj, k ) + Ssw_SmlObjAssignConst( pSml, pObj, Aig_InfoHasBit(p->pData, iBit++), i ); + assert( iBit == p->nBits ); + // run random simulation + Ssw_SmlSimulateOne( pSml ); + // check if the given output has failed + iOut = -1; + Saig_ManForEachPo( pAig, pObj, k ) + if ( !Ssw_SmlNodeIsZero( pSml, Aig_ManPo(pAig, k) ) ) + { + iOut = k; + break; + } + Ssw_SmlStop( pSml ); + return iOut; +} + +/**Function************************************************************* + + Synopsis [Creates sequential counter-example from the simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ssw_Cex_t * Ssw_SmlGetCounterExample( Ssw_Sml_t * p ) +{ + Ssw_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 = Ssw_SmlAllocCounterExample( 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 ( Aig_InfoHasBit( pSims, iBit ) ) + Aig_InfoSetBit( pCex->pData, k ); + } + for ( i = 0; i <= iFrame; i++ ) + { + Saig_ManForEachPi( p->pAig, pObj, k ) + { + pSims = Ssw_ObjSim( p, pObj->Id ); + if ( Aig_InfoHasBit( pSims, 32 * p->nWordsFrame * i + iBit ) ) + Aig_InfoSetBit( pCex->pData, pCex->nRegs + pCex->nPis * i + k ); + } + } + // verify the counter example + if ( !Ssw_SmlRunCounterExample( p->pAig, pCex ) ) + { + printf( "Ssw_SmlGetCounterExample(): Counter-example is invalid.\n" ); + Ssw_SmlFreeCounterExample( pCex ); + pCex = NULL; + } + return pCex; +} + +/**Function************************************************************* + + Synopsis [Generates seq counter-example from the combinational one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ssw_Cex_t * Ssw_SmlCopyCounterExample( Aig_Man_t * pAig, Aig_Man_t * pFrames, int * pModel ) +{ + Ssw_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 = Ssw_SmlAllocCounterExample( 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] ) + Aig_InfoSetBit( pCex->pData, pCex->nRegs + i ); + if ( pCex->nRegs + i == pCex->nBits - 1 ) + break; + } + + // verify the counter example + if ( !Ssw_SmlRunCounterExample( pAig, pCex ) ) + { + printf( "Ssw_SmlGetCounterExample(): Counter-example is invalid.\n" ); + Ssw_SmlFreeCounterExample( pCex ); + pCex = NULL; + } + return pCex; + +} + +/**Function************************************************************* + + Synopsis [Make the trivial counter-example for the trivially asserted output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ssw_Cex_t * Ssw_SmlTrivCounterExample( Aig_Man_t * pAig, int iFrameOut ) +{ + Ssw_Cex_t * pCex; + int nTruePis, nTruePos, iPo, iFrame; + assert( Aig_ManRegNum(pAig) > 0 ); + nTruePis = Aig_ManPiNum(pAig)-Aig_ManRegNum(pAig); + nTruePos = Aig_ManPoNum(pAig)-Aig_ManRegNum(pAig); + iPo = iFrameOut % nTruePos; + iFrame = iFrameOut / nTruePos; + // allocate the counter example + pCex = Ssw_SmlAllocCounterExample( Aig_ManRegNum(pAig), nTruePis, iFrame + 1 ); + pCex->iPo = iPo; + pCex->iFrame = iFrame; + return pCex; +} + +/**Function************************************************************* + + Synopsis [Make the trivial counter-example for the trivially asserted output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ssw_Cex_t * Ssw_SmlDupCounterExample( Ssw_Cex_t * p, int nRegsNew ) +{ + Ssw_Cex_t * pCex; + int i; + pCex = Ssw_SmlAllocCounterExample( nRegsNew, p->nPis, p->iFrame+1 ); + pCex->iPo = p->iPo; + pCex->iFrame = p->iFrame; + for ( i = p->nRegs; i < p->nBits; i++ ) + if ( Aig_InfoHasBit(p->pData, i) ) + Aig_InfoSetBit( pCex->pData, pCex->nRegs + i - p->nRegs ); + return pCex; +} + +/**Function************************************************************* + + Synopsis [Resimulates the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SmlWriteCounterExample( FILE * pFile, Aig_Man_t * pAig, Ssw_Cex_t * p ) +{ + Ssw_Sml_t * pSml; + Aig_Obj_t * pObj; + int RetValue, i, k, iBit; + unsigned * pSims; + assert( Aig_ManRegNum(pAig) > 0 ); + assert( Aig_ManRegNum(pAig) < Aig_ManPiNum(pAig) ); + // start a new sequential simulator + pSml = Ssw_SmlStart( pAig, 0, p->iFrame+1, 1 ); + // assign simulation info for the registers + iBit = 0; + Saig_ManForEachLo( pAig, pObj, i ) +// Ssw_SmlObjAssignConst( pSml, pObj, Aig_InfoHasBit(p->pData, iBit++), 0 ); + Ssw_SmlObjAssignConst( pSml, pObj, 0, 0 ); + // assign simulation info for the primary inputs + iBit = p->nRegs; + for ( i = 0; i <= p->iFrame; i++ ) + Saig_ManForEachPi( pAig, pObj, k ) + Ssw_SmlObjAssignConst( pSml, pObj, Aig_InfoHasBit(p->pData, iBit++), i ); + assert( iBit == p->nBits ); + // run random simulation + Ssw_SmlSimulateOne( pSml ); + // check if the given output has failed + RetValue = !Ssw_SmlNodeIsZero( pSml, Aig_ManPo(pAig, p->iPo) ); + + // write the output file + for ( i = 0; i <= p->iFrame; i++ ) + { +/* + Saig_ManForEachLo( pAig, pObj, k ) + { + pSims = Ssw_ObjSim(pSml, pObj->Id); + fprintf( pFile, "%d", (int)(pSims[i] != 0) ); + } + fprintf( pFile, " " ); +*/ + Saig_ManForEachPi( pAig, pObj, k ) + { + pSims = Ssw_ObjSim(pSml, pObj->Id); + fprintf( pFile, "%d", (int)(pSims[i] != 0) ); + } +/* + fprintf( pFile, " " ); + Saig_ManForEachPo( pAig, pObj, k ) + { + pSims = Ssw_ObjSim(pSml, pObj->Id); + fprintf( pFile, "%d", (int)(pSims[i] != 0) ); + } + fprintf( pFile, " " ); + Saig_ManForEachLi( pAig, pObj, k ) + { + pSims = Ssw_ObjSim(pSml, pObj->Id); + fprintf( pFile, "%d", (int)(pSims[i] != 0) ); + } +*/ + fprintf( pFile, "\n" ); + } + + Ssw_SmlStop( pSml ); + return RetValue; +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ssw_old/sswSimSat.c b/src/aig/ssw_old/sswSimSat.c new file mode 100644 index 000000000..cbb6d0c1f --- /dev/null +++ b/src/aig/ssw_old/sswSimSat.c @@ -0,0 +1,199 @@ +/**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" + +//////////////////////////////////////////////////////////////////////// +/// 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 = Aig_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) ); + // 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 [Verifies the result of simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManResimulateWordVerify( Ssw_Man_t * p, int f ) +{ + Aig_Obj_t * pObj, * pObjFraig; + unsigned uWord; + int Value1, Value2; + int i, nVarNum, Counter = 0; + Aig_ManForEachObj( p->pAig, pObj, i ) + { + pObjFraig = Ssw_ObjFrame( p, pObj, f ); + if ( pObjFraig == NULL ) + continue; + nVarNum = Ssw_ObjSatNum( p, Aig_Regular(pObjFraig) ); + if ( nVarNum == 0 ) + continue; + Value1 = Ssw_ManGetSatVarValue( p, pObj, f ); + uWord = Ssw_SmlObjGetWord( p->pSml, pObj, 0, 0 ); + Value2 = ((uWord != 0) ^ pObj->fPhase); + Counter += (Value1 != Value2); + if ( Value1 != Value2 ) + { +/* + int Value1f = Ssw_ManGetSatVarValue( p, Aig_ObjFanin0(pObj), f ); + int Value2f = Ssw_ManGetSatVarValue( p, Aig_ObjFanin1(pObj), f ); +*/ + int x = 0; + int Value3 = Ssw_ManGetSatVarValue( p, pObj, f ); + } + } + if ( Counter ) + printf( "Counter = %d.\n", Counter ); +} + +/**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 ); + Ssw_ManResimulateWordVerify( p, f ); + + // 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; +} + +/**Function************************************************************* + + Synopsis [Handle the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManResimulateWord2( 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->pPatWords2 ); + // simulate internal nodes + Ssw_SmlSimulateOne( p->pSml ); + Ssw_ManResimulateWordVerify( p, f ); + + // 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 /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ssw_old/sswSweep.c b/src/aig/ssw_old/sswSweep.c new file mode 100644 index 000000000..b9d4ad63d --- /dev/null +++ b/src/aig/ssw_old/sswSweep.c @@ -0,0 +1,473 @@ +/**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 "bar.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Mark nodes affected by sweep in the previous iteration.] + + Description [Assumes that affected nodes are in p->ppClasses->vRefined.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_ManSweepMarkRefinement( Ssw_Man_t * p ) +{ + Vec_Ptr_t * vRefined, * vSupp; + Aig_Obj_t * pObj, * pObjLo, * pObjLi; + int i, k; + vRefined = Ssw_ClassesGetRefined( p->ppClasses ); + if ( Vec_PtrSize(vRefined) == 0 ) + { + Aig_ManForEachObj( p->pAig, pObj, i ) + pObj->fMarkA = 1; + return; + } + // mark the nodes to be refined + Aig_ManCleanMarkA( p->pAig ); + Vec_PtrForEachEntry( vRefined, pObj, i ) + { + if ( Aig_ObjIsPi(pObj) ) + { + pObj->fMarkA = 1; + continue; + } + assert( Aig_ObjIsNode(pObj) ); + vSupp = Aig_Support( p->pAig, pObj ); + Vec_PtrForEachEntry( vSupp, pObjLo, k ) + pObjLo->fMarkA = 1; + Vec_PtrFree( vSupp ); + } + // mark refinement + Aig_ManForEachNode( p->pAig, pObj, i ) + pObj->fMarkA = Aig_ObjFanin0(pObj)->fMarkA | Aig_ObjFanin1(pObj)->fMarkA; + Saig_ManForEachLi( p->pAig, pObj, i ) + pObj->fMarkA |= Aig_ObjFanin0(pObj)->fMarkA; + Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) + pObjLo->fMarkA |= pObjLi->fMarkA; +} + +/**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 ) +{ + Aig_Obj_t * pObjFraig; + int nVarNum, Value; +// assert( Aig_ObjIsPi(pObj) ); + pObjFraig = Ssw_ObjFrame( p, pObj, f ); + nVarNum = Ssw_ObjSatNum( p, Aig_Regular(pObjFraig) ); + assert( nVarNum > 0 ); + if ( nVarNum == 0 ) + printf( "Variable is not assigned.\n" ); + Value = (!nVarNum)? 0 : (Aig_IsComplement(pObjFraig) ^ sat_solver_var_value( p->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 [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 ) ) + Aig_InfoSetBit( p->pPatWords, i ); +} + +/**Function************************************************************* + + Synopsis [Copy pattern from the solver into the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_SmlSavePatternAig2( Ssw_Man_t * p, int f ) +{ + Aig_Obj_t * pObj; + int i; + memset( p->pPatWords2, 0, sizeof(unsigned) * p->nPatWords ); + Aig_ManForEachPi( p->pAig, pObj, i ) + if ( Ssw_ManGetSatVarValue( p, pObj, f ) ) + Aig_InfoSetBit( p->pPatWords2, i ); +} + +/**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) ) ) + Aig_InfoSetBit( p->pPatWords, i ); +} + +/**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 ) +{ + 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 ); + if ( (pObj->fPhase == pObjRepr->fPhase) != (Aig_ObjPhaseReal(pObjFraig) == Aig_ObjPhaseReal(pObjReprFraig)) ) + { + p->nStrangers++; + Ssw_SmlSavePatternAigPhase( p, f ); + } + else + { + // if the fraiged nodes are the same, return + if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) ) + return 0; + // count the number of skipped calls + if ( !pObj->fMarkA && !pObjRepr->fMarkA ) + p->nRefSkip++; + else + p->nRefUse++; + // call equivalence checking + if ( p->pPars->fSkipCheck && !fBmc && !pObj->fMarkA && !pObjRepr->fMarkA ) + RetValue = 1; + else 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; + } + // check if skipping calls works correctly + if ( p->pPars->fSkipCheck && !fBmc && !pObj->fMarkA && !pObjRepr->fMarkA ) + { + assert( 0 ); + printf( "\nSsw_ManSweepNode(): Error!\n" ); + } + // disproved the equivalence + Ssw_SmlSavePatternAig( p, f ); + } + if ( !fBmc && p->pPars->fUniqueness && p->pPars->nFramesK > 1 && + Ssw_ManUniqueOne( p, pObjRepr, pObj ) && p->iOutputLit == -1 ) + { + if ( Ssw_ManUniqueAddConstraint( p, p->vCommon, 0, 1 ) ) + { + int RetValue2 = Ssw_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) ); + p->iOutputLit = -1; + + { + int Flag = 0; + if ( Flag ) + { + Aig_Obj_t * pFan0 = Aig_ObjFanin0(pObj); + Aig_Obj_t * pFan1 = Aig_ObjFanin1(pObj); + Aig_Obj_t * pFan00 = Aig_ObjFanin0(pFan0); + Aig_Obj_t * pFan01 = Aig_ObjFanin1(pFan0); + Aig_Obj_t * pFan10 = Aig_ObjFanin0(pFan1); + Aig_Obj_t * pFan11 = Aig_ObjFanin1(pFan1); + } + } + + if ( RetValue2 == 0 ) + { + int x = Ssw_ManUniqueOne( p, pObjRepr, pObj ); +// Ssw_SmlSavePatternAig2( p, f ); +// Ssw_ManResimulateWord2( p, pObj, pObjRepr, f ); + Ssw_SmlSavePatternAig( p, f ); + Ssw_ManResimulateWord( p, pObj, pObjRepr, f ); + if ( Aig_ObjRepr( p->pAig, pObj ) == pObjRepr ) + printf( "Ssw_ManSweepNode(): Refinement did not happen!!!!!!!!!!!!!!!!!!!!.\n" ); + return 1; + } + return 0; + + +/* + int RetValue; + assert( p->iOutputLit > -1 ); + RetValue = Ssw_ManSweepNode( p, pObj, f, 0 ); + p->iOutputLit = -1; + return RetValue; +*/ + } + } + if ( p->pPars->nConstrs == 0 ) + 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(): Refinement did not happen.\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 ); + Ssw_ManStartSolver( p ); + 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); + Ssw_ObjSetFrame( p, pObj, f, pObjNew ); + Ssw_CnfNodeAddToSolver( p, Aig_Regular(pObjNew) ); + } + // 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 ); + } + // quit if this is the last timeframe + if ( f == p->pPars->nFramesK - 1 ) + 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, 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_ManSweep( Ssw_Man_t * p ) +{ + Bar_Progress_t * pProgress = NULL; + Aig_Obj_t * pObj, * pObj2, * pObjNew; + int nConstrPairs, clk, i, f; + int v; + + // perform speculative reduction +clk = clock(); + // create timeframes + p->pFrames = Ssw_FramesWithClasses( p ); + // add constraints + Ssw_ManStartSolver( p ); +// nConstrPairs = Aig_ManPoNum(p->pFrames)-Aig_ManRegNum(p->pAig); + nConstrPairs = Aig_ManPoNum(p->pFrames)-p->nFrames*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, Aig_ObjFanin0(pObj) ); + } +*/ +p->timeReduce += clock() - clk; + + // mark nodes that do not have to be refined +clk = clock(); + if ( p->pPars->fSkipCheck ) + Ssw_ManSweepMarkRefinement( p ); +p->timeMarkCones += clock() - clk; + +//Ssw_ManUnique( p ); + + // 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) ); +//// + // bring up the previous frames +// if ( p->pPars->fUniqueness ) + for ( v = 0; v <= f; v++ ) +// Saig_ManForEachLo( p->pAig, pObj, i ) + Aig_ManForEachPi( p->pAig, pObj, i ) + { +/* + if ( i == 53 && v == 1 ) + { + int x = 0; + } +*/ + Ssw_CnfNodeAddToSolver( p, Aig_Regular(Ssw_ObjFrame(p, pObj, v)) ); + } +//// + sat_solver_simplify( p->pSat ); + // make sure LOs are assigned + Saig_ManForEachLo( p->pAig, pObj, i ) + assert( Ssw_ObjFrame( p, pObj, f ) != NULL ); + // sweep internal nodes + p->fRefined = 0; + p->nSatFailsReal = 0; + p->nRefUse = p->nRefSkip = 0; + p->nUniques = 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_ManSweepNode( p, pObj, f, 0 ); + else if ( Aig_ObjIsNode(pObj) ) + { + pObj->fMarkA = Aig_ObjFanin0(pObj)->fMarkA | Aig_ObjFanin1(pObj)->fMarkA; + 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 ); + } + } + p->nSatFailsTotal += p->nSatFailsReal; + if ( p->pPars->fVerbose ) + Bar_ProgressStop( pProgress ); + + // cleanup +// Ssw_ClassesCheck( p->ppClasses ); + return p->fRefined; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ssw_old/sswUnique.c b/src/aig/ssw_old/sswUnique.c new file mode 100644 index 000000000..2beeed090 --- /dev/null +++ b/src/aig/ssw_old/sswUnique.c @@ -0,0 +1,290 @@ +/**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" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the result of merging the two vectors.] + + Description [Assumes that the vectors are sorted in the increasing order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_PtrTwoMerge( Vec_Ptr_t * vArr1, Vec_Ptr_t * vArr2, Vec_Ptr_t * vArr ) +{ + Aig_Obj_t ** pBeg = (Aig_Obj_t **)vArr->pArray; + Aig_Obj_t ** pBeg1 = (Aig_Obj_t **)vArr1->pArray; + Aig_Obj_t ** pBeg2 = (Aig_Obj_t **)vArr2->pArray; + Aig_Obj_t ** pEnd1 = (Aig_Obj_t **)vArr1->pArray + vArr1->nSize; + Aig_Obj_t ** pEnd2 = (Aig_Obj_t **)vArr2->pArray + vArr2->nSize; + Vec_PtrGrow( vArr, Vec_PtrSize(vArr1) + Vec_PtrSize(vArr2) ); + pBeg = (Aig_Obj_t **)vArr->pArray; + while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) + { + if ( (*pBeg1)->Id == (*pBeg2)->Id ) + *pBeg++ = *pBeg1++, pBeg2++; + else if ( (*pBeg1)->Id < (*pBeg2)->Id ) + *pBeg++ = *pBeg1++; + else + *pBeg++ = *pBeg2++; + } + while ( pBeg1 < pEnd1 ) + *pBeg++ = *pBeg1++; + while ( pBeg2 < pEnd2 ) + *pBeg++ = *pBeg2++; + vArr->nSize = pBeg - (Aig_Obj_t **)vArr->pArray; + assert( vArr->nSize <= vArr->nCap ); + assert( vArr->nSize >= vArr1->nSize ); + assert( vArr->nSize >= vArr2->nSize ); +} + +/**Function************************************************************* + + Synopsis [Returns the result of merging the two vectors.] + + Description [Assumes that the vectors are sorted in the increasing order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_PtrTwoCommon( Vec_Ptr_t * vArr1, Vec_Ptr_t * vArr2, Vec_Ptr_t * vArr ) +{ + Aig_Obj_t ** pBeg = (Aig_Obj_t **)vArr->pArray; + Aig_Obj_t ** pBeg1 = (Aig_Obj_t **)vArr1->pArray; + Aig_Obj_t ** pBeg2 = (Aig_Obj_t **)vArr2->pArray; + Aig_Obj_t ** pEnd1 = (Aig_Obj_t **)vArr1->pArray + vArr1->nSize; + Aig_Obj_t ** pEnd2 = (Aig_Obj_t **)vArr2->pArray + vArr2->nSize; + Vec_PtrGrow( vArr, AIG_MIN( Vec_PtrSize(vArr1), Vec_PtrSize(vArr2) ) ); + pBeg = (Aig_Obj_t **)vArr->pArray; + while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) + { + if ( (*pBeg1)->Id == (*pBeg2)->Id ) + *pBeg++ = *pBeg1++, pBeg2++; + else if ( (*pBeg1)->Id < (*pBeg2)->Id ) +// *pBeg++ = *pBeg1++; + pBeg1++; + else +// *pBeg++ = *pBeg2++; + pBeg2++; + } +// while ( pBeg1 < pEnd1 ) +// *pBeg++ = *pBeg1++; +// while ( pBeg2 < pEnd2 ) +// *pBeg++ = *pBeg2++; + vArr->nSize = pBeg - (Aig_Obj_t **)vArr->pArray; + assert( vArr->nSize <= vArr->nCap ); + assert( vArr->nSize <= vArr1->nSize ); + assert( vArr->nSize <= vArr2->nSize ); +} + +/**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 = 1; + Aig_Obj_t * ppObjs[2], * pTemp; + Vec_Ptr_t * vSupp, * vSupp2; + int i, k, Value0, Value1, RetValue; + assert( p->pPars->nFramesK > 1 ); + + vSupp = Vec_PtrAlloc( 100 ); + vSupp2 = Vec_PtrAlloc( 100 ); + Vec_PtrClear( p->vCommon ); + + // compute the first support in terms of LOs + ppObjs[0] = pRepr; + ppObjs[1] = pObj; + Aig_SupportNodes( p->pAig, ppObjs, 2, vSupp ); + // modify support to be in terms of LIs + k = 0; + Vec_PtrForEachEntry( vSupp, pTemp, i ) + if ( Saig_ObjIsLo(p->pAig, pTemp) ) + Vec_PtrWriteEntry( vSupp, k++, Saig_ObjLoToLi(p->pAig, pTemp) ); + Vec_PtrShrink( vSupp, k ); + // compute the support of support + Aig_SupportNodes( p->pAig, (Aig_Obj_t **)Vec_PtrArray(vSupp), Vec_PtrSize(vSupp), vSupp2 ); + // return support to LO + Vec_PtrForEachEntry( vSupp, pTemp, i ) + Vec_PtrWriteEntry( vSupp, i, Saig_ObjLiToLo(p->pAig, pTemp) ); + // find the number of common vars + Vec_PtrSort( vSupp, Aig_ObjCompareIdIncrease ); + Vec_PtrSort( vSupp2, Aig_ObjCompareIdIncrease ); + Vec_PtrTwoCommon( vSupp, vSupp2, p->vCommon ); +// Vec_PtrTwoMerge( vSupp, vSupp2, p->vCommon ); + +/* + { + Vec_Ptr_t * vNew = Vec_PtrDup(vSupp); + Vec_PtrUniqify( vNew, Aig_ObjCompareIdIncrease ); + if ( Vec_PtrSize(vNew) != Vec_PtrSize(vSupp) ) + printf( "Not unique!\n" ); + Vec_PtrFree( vNew ); + Vec_PtrForEachEntry( vSupp, pTemp, i ) + printf( "%d ", pTemp->Id ); + printf( "\n" ); + } + { + Vec_Ptr_t * vNew = Vec_PtrDup(vSupp2); + Vec_PtrUniqify( vNew, Aig_ObjCompareIdIncrease ); + if ( Vec_PtrSize(vNew) != Vec_PtrSize(vSupp2) ) + printf( "Not unique!\n" ); + Vec_PtrFree( vNew ); + Vec_PtrForEachEntry( vSupp2, pTemp, i ) + printf( "%d ", pTemp->Id ); + printf( "\n" ); + } + { + Vec_Ptr_t * vNew = Vec_PtrDup(p->vCommon); + Vec_PtrUniqify( vNew, Aig_ObjCompareIdIncrease ); + if ( Vec_PtrSize(vNew) != Vec_PtrSize(p->vCommon) ) + printf( "Not unique!\n" ); + Vec_PtrFree( vNew ); + Vec_PtrForEachEntry( p->vCommon, pTemp, i ) + printf( "%d ", pTemp->Id ); + printf( "\n" ); + } +*/ + + if ( fVerbose ) + printf( "Node = %5d : One = %3d. Two = %3d. Common = %3d. ", + Aig_ObjId(pObj), Vec_PtrSize(vSupp), Vec_PtrSize(vSupp2), Vec_PtrSize(p->vCommon) ); + +// Vec_PtrClear( vSupp ); +// Vec_PtrForEachEntry( vSupp2, pTemp, i ) +// Vec_PtrPush( vSupp, pTemp ); + + // check the current values + RetValue = 1; +// Vec_PtrForEachEntry( p->vCommon, pTemp, i ) + Vec_PtrForEachEntry( vSupp, 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 ( Vec_PtrSize(p->vCommon) == 0 ) + RetValue = 0; + + Vec_PtrForEachEntry( vSupp, pTemp, i ) + printf( " %d", pTemp->Id ); + + if ( fVerbose ) + printf( "\n" ); + + + Vec_PtrClear( p->vCommon ); + Vec_PtrForEachEntry( vSupp, pTemp, i ) + Vec_PtrPush( p->vCommon, pTemp ); + + Vec_PtrFree( vSupp ); + Vec_PtrFree( vSupp2 ); + return RetValue; +} + +/**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( 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; + } +*/ + p->nUniques++; + // create CNF +// { +// int Num1 = p->nSatVars; + Ssw_CnfNodeAddToSolver( p, Aig_Regular(pTotal) ); +// printf( "Created variable %d while vars are %d. (diff = %d)\n", +// Ssw_ObjSatNum( p, Aig_Regular(pTotal) ), p->nSatVars, p->nSatVars - Num1 ); +// } + // add output constraint + pLits[0] = toLitCond( Ssw_ObjSatNum(p,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 /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 4f46f3a20..50fb11ac4 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -254,6 +254,7 @@ static int Abc_CommandAbc8Zero ( Abc_Frame_t * pAbc, int argc, char ** arg static int Abc_CommandAbc8Cec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc8DSec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbcTestNew ( Abc_Frame_t * pAbc, int argc, char ** argv ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -518,6 +519,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC8", "*cec", Abc_CommandAbc8Cec, 0 ); Cmd_CommandAdd( pAbc, "ABC8", "*dsec", Abc_CommandAbc8DSec, 0 ); + Cmd_CommandAdd( pAbc, "Various", "testnew", Abc_CommandAbcTestNew, 0 ); // Cmd_CommandAdd( pAbc, "Verification", "trace_start", Abc_CommandTraceStart, 0 ); // Cmd_CommandAdd( pAbc, "Verification", "trace_check", Abc_CommandTraceCheck, 0 ); @@ -4919,22 +4921,24 @@ int Abc_CommandDemiter( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pOut, * pErr; Abc_Ntk_t * pNtk;//, * pNtkRes; - int fComb; + int fSeq; int c; extern int Abc_NtkDemiter( Abc_Ntk_t * pNtk ); + extern int Abc_NtkDarDemiter( Abc_Ntk_t * pNtk ); pNtk = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); pErr = Abc_FrameReadErr(pAbc); // set defaults + fSeq = 1; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "sh" ) ) != EOF ) { switch ( c ) { - case 'c': - fComb ^= 1; + case 's': + fSeq ^= 1; break; default: goto usage; @@ -4947,12 +4951,6 @@ int Abc_CommandDemiter( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - if ( Abc_NtkPoNum(pNtk) != 1 ) - { - fprintf( pErr, "The network is not a miter.\n" ); - return 1; - } - if ( !Abc_NodeIsExorType(Abc_ObjFanin0(Abc_NtkPo(pNtk,0))) ) { fprintf( pErr, "The miter's PO is not an EXOR.\n" ); @@ -4960,19 +4958,35 @@ int Abc_CommandDemiter( Abc_Frame_t * pAbc, int argc, char ** argv ) } // get the new network - if ( !Abc_NtkDemiter( pNtk ) ) + if ( fSeq ) { - fprintf( pErr, "Demitering has failed.\n" ); - return 1; + if ( !Abc_NtkDarDemiter( pNtk ) ) + { + fprintf( pErr, "Demitering has failed.\n" ); + return 1; + } + } + else + { + if ( Abc_NtkPoNum(pNtk) != 1 ) + { + fprintf( pErr, "The network is not a single-output miter.\n" ); + return 1; + } + if ( !Abc_NtkDemiter( pNtk ) ) + { + fprintf( pErr, "Demitering has failed.\n" ); + return 1; + } } // replace the current network // Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: - fprintf( pErr, "usage: demiter [-h]\n" ); + fprintf( pErr, "usage: demiter [-sh]\n" ); fprintf( pErr, "\t removes topmost EXOR from the miter to create two POs\n" ); -// fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" ); + fprintf( pErr, "\t-s : applied multi-output algorithm [default = %s]\n", fSeq? "yes": "no" ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; } @@ -7720,7 +7734,7 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) // extern void Aig_ProcedureTest(); extern void Abc_NtkDarTest( Abc_Ntk_t * pNtk ); extern Abc_Ntk_t * Abc_NtkDarTestNtk( Abc_Ntk_t * pNtk ); - + extern int Ssw_SecSpecialMiter( Aig_Man_t * pMiter, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); pOut = Abc_FrameReadOut(pAbc); @@ -7922,6 +7936,7 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); */ +/* pNtkRes = Abc_NtkDarTestNtk( pNtk ); if ( pNtkRes == NULL ) { @@ -7930,6 +7945,9 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); +*/ + + Abc_NtkDarTest( pNtk ); return 0; usage: @@ -13541,7 +13559,7 @@ int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults Ssw_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "PQFCLNSplsfuvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "PQFCLNSplsfuvwh" ) ) != EOF ) { switch ( c ) { @@ -13640,6 +13658,9 @@ int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'v': pPars->fVerbose ^= 1; break; + case 'w': + pPars->fFlopVerbose ^= 1; + break; case 'h': goto usage; default: @@ -13689,7 +13710,7 @@ int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - fprintf( pErr, "usage: scorr [-PQFCLNS ] [-plsfuvh]\n" ); + fprintf( pErr, "usage: scorr [-PQFCLNS ] [-plsfuvwh]\n" ); fprintf( pErr, "\t performs sequential sweep using K-step induction\n" ); fprintf( pErr, "\t-P num : max partition size (0 = no partitioning) [default = %d]\n", pPars->nPartSize ); fprintf( pErr, "\t-Q num : partition overlap (0 = no overlap) [default = %d]\n", pPars->nOverSize ); @@ -13704,6 +13725,7 @@ usage: fprintf( pErr, "\t-f : toggle filtering using interative BMC [default = %s]\n", pPars->fSemiFormal? "yes": "no" ); fprintf( pErr, "\t-u : toggle using uniqueness constraints [default = %s]\n", pPars->fUniqueness? "yes": "no" ); fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-w : toggle printout of flop equivalences [default = %s]\n", pPars->fFlopVerbose? "yes": "no" ); fprintf( pErr, "\t-h : print the command usage\n"); return 1; } @@ -19634,6 +19656,64 @@ usage: } + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbcTestNew( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern int Abc_NtkTestProcedure( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 ); + + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( stdout, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash( pNtk) ) + { + fprintf( stdout, "The current network is not an AIG. Cannot continue.\n" ); + return 1; + } + +// Abc_NtkTestProcedure( pNtk, NULL ); + + return 0; + +usage: + fprintf( stdout, "usage: testnew [-h]\n" ); + fprintf( stdout, "\t new testing procedure\n" ); + fprintf( stdout, "\t-h : print the command usage\n"); + return 1; +} + + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/base/abci/abc.zip b/src/base/abci/abc.zip new file mode 100644 index 0000000000000000000000000000000000000000..34df9a6336e41f9f5c3abdbec2ad56543b628eb8 GIT binary patch literal 62408 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

Z}+g&#PgLa@OBwZ%@_6g{feV8e%ZY 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 literal 0 HcmV?d00001 diff --git a/src/base/abci/abcDar.c b/src/base/abci/abcDar.c index 98228c564..c64fb0f50 100644 --- a/src/base/abci/abcDar.c +++ b/src/base/abci/abcDar.c @@ -1238,6 +1238,96 @@ PRT( "Initial fraiging time", clock() - clk ); return pNtkAig; } +/**Function************************************************************* + + Synopsis [Print Latch Equivalence Classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintLatchEquivClasses( Abc_Ntk_t * pNtk, Aig_Man_t * pAig ) +{ + bool header_dumped = false; + int num_orig_latches = Abc_NtkLatchNum(pNtk); + char **pNames = ALLOC( char *, num_orig_latches ); + bool *p_irrelevant = ALLOC( bool, num_orig_latches ); + char * pFlopName, * pReprName; + Aig_Obj_t * pFlop, * pRepr; + Abc_Obj_t * pNtkFlop; + int repr_idx; + int i; + + Abc_NtkForEachLatch( pNtk, pNtkFlop, i ) + { + char *temp_name = Abc_ObjName( Abc_ObjFanout0(pNtkFlop) ); + pNames[i] = ALLOC( char , strlen(temp_name)+1); + strcpy(pNames[i], temp_name); + } + i = 0; + + Aig_ManSetPioNumbers( pAig ); + Saig_ManForEachLo( pAig, pFlop, i ) + { + p_irrelevant[i] = false; + + pFlopName = pNames[i]; + + pRepr = Aig_ObjRepr(pAig, pFlop); + + if ( pRepr == NULL ) + { + // printf("Nothing equivalent to flop %s\n", pFlopName); + p_irrelevant[i] = true; + continue; + } + + if (!header_dumped) + { + printf("Here are the flop equivalences:\n"); + header_dumped = true; + } + + // pRepr is representative of the equivalence class, to which pFlop belongs + if ( Aig_ObjIsConst1(pRepr) ) + { + printf( "Original flop %s is proved equivalent to constant.\n", pFlopName ); + // printf( "Original flop # %d is proved equivalent to constant.\n", i ); + continue; + } + + assert( Saig_ObjIsLo( pAig, pRepr ) ); + repr_idx = Aig_ObjPioNum(pRepr) - Saig_ManPiNum(pAig); + pReprName = pNames[repr_idx]; + printf( "Original flop %s is proved equivalent to flop %s.\n", pFlopName, pReprName ); + // printf( "Original flop # %d is proved equivalent to flop # %d.\n", i, repr_idx ); + } + + header_dumped = false; + for (i=0; ifFlopVerbose ) + Abc_NtkPrintLatchEquivClasses(pNtk, pTemp); + + Aig_ManStop( pTemp ); if ( pMan == NULL ) return NULL; @@ -1463,6 +1557,47 @@ PRT( "Time", clock() - clk ); return 1; } +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDarDemiter( Abc_Ntk_t * pNtk ) +{ + Aig_Man_t * pMan, * pPart0, * pPart1, * pMiter; + // derive the AIG manager + pMan = Abc_NtkToDar( pNtk, 0, 1 ); + if ( pMan == NULL ) + { + printf( "Converting network into AIG has failed.\n" ); + return 0; + } + if ( !Saig_ManDemiterSimple( pMan, &pPart0, &pPart1 ) ) + { + printf( "Demitering has failed.\n" ); + return 0; + } + 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" ); + // create two-level miter + pMiter = Saig_ManCreateMiterTwo( pPart0, pPart1, 2 ); + Aig_ManDumpBlif( pMiter, "miter01.blif", NULL, NULL ); + Aig_ManStop( pMiter ); + printf( "The new miter is written into file \"%s\".\n", "miter01.blif" ); + + Aig_ManStop( pPart0 ); + Aig_ManStop( pPart1 ); + Aig_ManStop( pMan ); + return 1; +} + /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] @@ -2457,9 +2592,9 @@ void Abc_NtkDarReach( Abc_Ntk_t * pNtk, int nBddMax, int nIterMax, int fPartitio ***********************************************************************/ void Abc_NtkDarTest( Abc_Ntk_t * pNtk ) { - extern Aig_Man_t * Ssw_SignalCorrespondeceTestPairs( Aig_Man_t * pAig ); +// extern Aig_Man_t * Ssw_SignalCorrespondeceTestPairs( Aig_Man_t * pAig ); - Aig_Man_t * pMan, * pTemp; + Aig_Man_t * pMan;//, * pTemp; assert( Abc_NtkIsStrash(pNtk) ); pMan = Abc_NtkToDar( pNtk, 0, 1 ); if ( pMan == NULL ) @@ -2472,9 +2607,13 @@ Aig_ManStop( pMan ); pMan = Saig_ManReadBlif( "_temp_.blif" ); Aig_ManPrintStats( pMan ); */ +/* Aig_ManSetRegNum( pMan, pMan->nRegs ); pTemp = Ssw_SignalCorrespondeceTestPairs( pMan ); Aig_ManStop( pTemp ); +*/ + Ssw_SecSpecialMiter( pMan, 0 ); + Aig_ManStop( pMan ); } diff --git a/src/base/cmd/cmd.c b/src/base/cmd/cmd.c index 75aa00646..4e0a4c95c 100644 --- a/src/base/cmd/cmd.c +++ b/src/base/cmd/cmd.c @@ -50,6 +50,7 @@ static int CmdCommandEmpty ( Abc_Frame_t * pAbc, int argc, char ** argv static int CmdCommandLs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandScrGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); #endif +static int CmdCommandVersion ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandSis ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandMvsis ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int CmdCommandCapo ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -68,7 +69,7 @@ static int CmdCommandCapo ( Abc_Frame_t * pAbc, int argc, char ** argv ******************************************************************************/ void Cmd_Init( Abc_Frame_t * pAbc ) -{ +{ pAbc->tCommands = st_init_table(strcmp, st_strhash); pAbc->tAliases = st_init_table(strcmp, st_strhash); pAbc->tFlags = st_init_table(strcmp, st_strhash); @@ -91,6 +92,7 @@ void Cmd_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Basic", "ls", CmdCommandLs, 0 ); Cmd_CommandAdd( pAbc, "Basic", "scrgen", CmdCommandScrGen, 0 ); #endif + Cmd_CommandAdd( pAbc, "Basic", "version", CmdCommandVersion, 0); Cmd_CommandAdd( pAbc, "Various", "sis", CmdCommandSis, 1); Cmd_CommandAdd( pAbc, "Various", "mvsis", CmdCommandMvsis, 1); @@ -1910,6 +1912,22 @@ usage: return 1; // error exit } +/**Function******************************************************************** + + Synopsis [Print the version string.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandVersion( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + printf("%s\n", Abc_UtilsGetVersion(pAbc)); + return 0; +} //////////////////////////////////////////////////////////////////////// diff --git a/src/base/cmd/cmd.h b/src/base/cmd/cmd.h index 030b77e8d..9d0b87033 100644 --- a/src/base/cmd/cmd.h +++ b/src/base/cmd/cmd.h @@ -40,6 +40,17 @@ extern "C" { typedef struct MvCommand Abc_Command; // one command typedef struct MvAlias Abc_Alias; // one alias +#ifdef WIN32 +#define DLLEXPORT __declspec(dllexport) +#define DLLIMPORT __declspec(dllimport) +#else /* defined(WIN32) */ +#define DLLIMPORT +#endif /* defined(WIN32) */ + +#ifndef ABC_DLL +#define ABC_DLL DLLIMPORT +#endif + //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -53,7 +64,7 @@ extern void Cmd_Init(); extern void Cmd_End(); /*=== cmdApi.c ========================================================*/ extern void Cmd_CommandAdd( Abc_Frame_t * pAbc, char * sGroup, char * sName, void * pFunc, int fChanges ); -extern int Cmd_CommandExecute( Abc_Frame_t * pAbc, char * sCommand ); +extern ABC_DLL int Cmd_CommandExecute( Abc_Frame_t * pAbc, char * sCommand ); /*=== cmdFlag.c ========================================================*/ extern char * Cmd_FlagReadByName( Abc_Frame_t * pAbc, char * flag ); extern void Cmd_FlagDeleteByName( Abc_Frame_t * pAbc, char * key ); diff --git a/src/base/io/io.c b/src/base/io/io.c index 6d7948abf..6f326a27c 100644 --- a/src/base/io/io.c +++ b/src/base/io/io.c @@ -1710,30 +1710,7 @@ int IoCommandWriteCounter( Abc_Frame_t * pAbc, int argc, char **argv ) } // write the counter-example into the file - if ( pNtk->pModel ) - { - Abc_Obj_t * pObj; - FILE * pFile = fopen( pFileName, "w" ); - int i; - if ( pFile == NULL ) - { - fprintf( stdout, "IoCommandWriteCounter(): Cannot open the output file \"%s\".\n", pFileName ); - return 1; - } - if ( fNames ) - { - Abc_NtkForEachPi( pNtk, pObj, i ) - fprintf( pFile, "%s=%c ", Abc_ObjName(pObj), '0'+(pNtk->pModel[i]==1) ); - } - else - { - Abc_NtkForEachPi( pNtk, pObj, i ) - fprintf( pFile, "%c", '0'+(pNtk->pModel[i]==1) ); - } - fprintf( pFile, "\n" ); - fclose( pFile ); - } - else + if ( pNtk->pSeqModel ) { Fra_Cex_t * pCex = pNtk->pSeqModel; Abc_Obj_t * pObj; @@ -1771,6 +1748,29 @@ int IoCommandWriteCounter( Abc_Frame_t * pAbc, int argc, char **argv ) fprintf( pFile, "\n" ); fclose( pFile ); } + else + { + Abc_Obj_t * pObj; + FILE * pFile = fopen( pFileName, "w" ); + int i; + if ( pFile == NULL ) + { + fprintf( stdout, "IoCommandWriteCounter(): Cannot open the output file \"%s\".\n", pFileName ); + return 1; + } + if ( fNames ) + { + Abc_NtkForEachPi( pNtk, pObj, i ) + fprintf( pFile, "%s=%c ", Abc_ObjName(pObj), '0'+(pNtk->pModel[i]==1) ); + } + else + { + Abc_NtkForEachPi( pNtk, pObj, i ) + fprintf( pFile, "%c", '0'+(pNtk->pModel[i]==1) ); + } + fprintf( pFile, "\n" ); + fclose( pFile ); + } return 0; diff --git a/src/base/main/mainUtils.c b/src/base/main/mainUtils.c index d69055a48..464694908 100644 --- a/src/base/main/mainUtils.c +++ b/src/base/main/mainUtils.c @@ -200,14 +200,26 @@ void Abc_UtilsSource( Abc_Frame_t * pAbc ) if ( sPath1 && sPath2 ) { /* ~/.rc == .rc : Source the file only once */ - (void) Cmd_CommandExecute(pAbc, "source -s ~/.abc.rc"); + char *tmp_cmd = ALLOC(char, strlen(sPath1)+12); + (void) sprintf(tmp_cmd, "source -s %s", sPath1); + // (void) Cmd_CommandExecute(pAbc, "source -s ~/.abc.rc"); + (void) Cmd_CommandExecute(pAbc, tmp_cmd); + FREE(tmp_cmd); } else { if (sPath1) { - (void) Cmd_CommandExecute(pAbc, "source -s ~/.abc.rc"); + char *tmp_cmd = ALLOC(char, strlen(sPath1)+12); + (void) sprintf(tmp_cmd, "source -s %s", sPath1); + // (void) Cmd_CommandExecute(pAbc, "source -s ~/.abc.rc"); + (void) Cmd_CommandExecute(pAbc, tmp_cmd); + FREE(tmp_cmd); } if (sPath2) { - (void) Cmd_CommandExecute(pAbc, "source -s .abc.rc"); + char *tmp_cmd = ALLOC(char, strlen(sPath2)+12); + (void) sprintf(tmp_cmd, "source -s %s", sPath2); + // (void) Cmd_CommandExecute(pAbc, "source -s .abc.rc"); + (void) Cmd_CommandExecute(pAbc, tmp_cmd); + FREE(tmp_cmd); } } if ( sPath1 ) FREE(sPath1); diff --git a/src/misc/extra/extra.h b/src/misc/extra/extra.h index d63ed5d3c..beb5a4d04 100644 --- a/src/misc/extra/extra.h +++ b/src/misc/extra/extra.h @@ -76,6 +76,18 @@ extern "C" { /* Macro declarations */ /*---------------------------------------------------------------------------*/ +#ifdef WIN32 +#define DLLEXPORT __declspec(dllexport) +#define DLLIMPORT __declspec(dllimport) +#else /* defined(WIN32) */ +#define DLLIMPORT +#endif /* defined(WIN32) */ + +#ifndef ABC_DLL +#define ABC_DLL DLLIMPORT +#endif + + typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned int uint32; @@ -633,19 +645,19 @@ extern unsigned Extra_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux #endif -extern long Extra_CpuTime(); -extern double Extra_CpuTimeDouble(); -extern int Extra_GetSoftDataLimit(); -extern void Extra_UtilGetoptReset(); -extern int Extra_UtilGetopt( int argc, char *argv[], char *optstring ); -extern char * Extra_UtilPrintTime( long t ); -extern char * Extra_UtilStrsav( char *s ); -extern char * Extra_UtilTildeExpand( char *fname ); -extern char * Extra_UtilFileSearch( char *file, char *path, char *mode ); -extern void (*Extra_UtilMMoutOfMemory)(); +extern long Extra_CpuTime(); +extern double Extra_CpuTimeDouble(); +extern int Extra_GetSoftDataLimit(); +extern ABC_DLL void Extra_UtilGetoptReset(); +extern int Extra_UtilGetopt( int argc, char *argv[], char *optstring ); +extern char * Extra_UtilPrintTime( long t ); +extern char * Extra_UtilStrsav( char *s ); +extern char * Extra_UtilTildeExpand( char *fname ); +extern char * Extra_UtilFileSearch( char *file, char *path, char *mode ); +extern void (*Extra_UtilMMoutOfMemory)(); -extern char * globalUtilOptarg; -extern int globalUtilOptind; +extern char * globalUtilOptarg; +extern int globalUtilOptind; /**AutomaticEnd***************************************************************/ diff --git a/src/sat/bsat/satChecker.c b/src/sat/bsat/satChecker.c new file mode 100644 index 000000000..1488fe2ff --- /dev/null +++ b/src/sat/bsat/satChecker.c @@ -0,0 +1,187 @@ +/**CFile**************************************************************** + + FileName [satChecker.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [SAT sat_solver.] + + Synopsis [Resolution proof checker.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: satChecker.c,v 1.4 2005/09/16 22:55:03 casem Exp $] + +***********************************************************************/ + +#include +#include +#include +#include +#include +#include "vec.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sat_PrintClause( Vec_Vec_t * vClauses, int Clause ) +{ + Vec_Int_t * vClause; + int i, Entry; + printf( "Clause %d: {", Clause ); + vClause = Vec_VecEntry( vClauses, Clause ); + Vec_IntForEachEntry( vClause, Entry, i ) + printf( " %d", Entry ); + printf( " }\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sat_ProofResolve( Vec_Vec_t * vClauses, int Result, int Clause1, int Clause2 ) +{ + Vec_Int_t * vResult = Vec_VecEntry( vClauses, Result ); + Vec_Int_t * vClause1 = Vec_VecEntry( vClauses, Clause1 ); + Vec_Int_t * vClause2 = Vec_VecEntry( vClauses, Clause2 ); + int Entry1, Entry2, ResVar; + int i, j, Counter = 0; + + Vec_IntForEachEntry( vClause1, Entry1, i ) + Vec_IntForEachEntry( vClause2, Entry2, j ) + if ( Entry1 == -Entry2 ) + { + ResVar = Entry1; + Counter++; + } + if ( Counter != 1 ) + { + printf( "Error: Clause %d = Resolve(%d, %d): The number of pivot vars is %d.\n", + Result, Clause1, Clause2, Counter ); + Sat_PrintClause( vClauses, Clause1 ); + Sat_PrintClause( vClauses, Clause2 ); + return 0; + } + // create new clause + assert( Vec_IntSize(vResult) == 0 ); + Vec_IntForEachEntry( vClause1, Entry1, i ) + if ( Entry1 != ResVar && Entry1 != -ResVar ) + Vec_IntPushUnique( vResult, Entry1 ); + assert( Vec_IntSize(vResult) + 1 == Vec_IntSize(vClause1) ); + Vec_IntForEachEntry( vClause2, Entry2, i ) + if ( Entry2 != ResVar && Entry2 != -ResVar ) + Vec_IntPushUnique( vResult, Entry2 ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sat_ProofChecker( char * pFileName ) +{ + FILE * pFile; + Vec_Vec_t * vClauses; + int c, i, Num, RetValue, Counter, Counter2, Clause1, Clause2; + // open the file + pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + return; + // count the number of clauses + Counter = Counter2 = 0; + while ( (c = fgetc(pFile)) != EOF ) + { + Counter += (c == '\n'); + Counter2 += (c == '*'); + } + vClauses = Vec_VecStart( Counter+1 ); + printf( "The proof contains %d roots and %d resolution steps.\n", Counter-Counter2, Counter2 ); + // read the clauses + rewind( pFile ); + for ( i = 1 ; ; i++ ) + { + RetValue = fscanf( pFile, "%d", &Num ); + if ( RetValue != 1 ) + break; + assert( Num == i ); + while ( (c = fgetc( pFile )) == ' ' ); + if ( c == '*' ) + { + RetValue = fscanf( pFile, "%d %d", &Clause1, &Clause2 ); + assert( RetValue == 2 ); + RetValue = fscanf( pFile, "%d", &Num ); + assert( RetValue == 1 ); + assert( Num == 0 ); + if ( !Sat_ProofResolve( vClauses, i, Clause1, Clause2 ) ) + { + printf( "Error detected in the resolution proof.\n" ); + Vec_VecFree( vClauses ); + fclose( pFile ); + return; + } + } + else + { + ungetc( c, pFile ); + while ( 1 ) + { + RetValue = fscanf( pFile, "%d", &Num ); + assert( RetValue == 1 ); + if ( Num == 0 ) + break; + Vec_VecPush( vClauses, i, (void *)Num ); + } + RetValue = fscanf( pFile, "%d", &Num ); + assert( RetValue == 1 ); + assert( Num == 0 ); + } + } + assert( i-1 == Counter ); + if ( Vec_IntSize( Vec_VecEntry(vClauses, Counter) ) != 0 ) + printf( "The last clause is not empty.\n" ); + else + printf( "The empty clause is derived.\n" ); + Vec_VecFree( vClauses ); + fclose( pFile ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/sat/bsat/satInterA.c b/src/sat/bsat/satInterA.c index 576289898..5edc5b67a 100644 --- a/src/sat/bsat/satInterA.c +++ b/src/sat/bsat/satInterA.c @@ -701,6 +701,10 @@ p->timeTrace += clock() - clk; // Inta_ManPrintInterOne( p, pFinal ); } Inta_ManProofSet( p, pFinal, p->Counter ); + // make sure the same proof ID is not asssigned to two consecutive clauses + assert( p->pProofNums[pFinal->Id-1] != p->Counter ); +// if ( p->pProofNums[pFinal->Id] == p->pProofNums[pFinal->Id-1] ) +// p->pProofNums[pFinal->Id] = p->pProofNums[pConflict->Id]; return p->Counter; } @@ -748,6 +752,27 @@ int Inta_ManProofRecordOne( Inta_Man_t * p, Sto_Cls_t * pClause ) { assert( 0 ); // cannot prove return 0; + } + + // skip the clause if it is weaker or the same as the conflict clause + if ( pClause->nLits >= pConflict->nLits ) + { + // check if every literal of conflict clause can be found in the given clause + int j; + for ( i = 0; i < (int)pConflict->nLits; i++ ) + { + for ( j = 0; j < (int)pClause->nLits; j++ ) + if ( pConflict->pLits[i] == pClause->pLits[j] ) + break; + if ( j == (int)pClause->nLits ) // literal pConflict->pLits[i] is not found + break; + } + if ( i == (int)pConflict->nLits ) // all lits are found + { + // undo to the root level + Inta_ManCancelUntil( p, p->nRootSize ); + return 1; + } } // construct the proof @@ -973,6 +998,7 @@ void * Inta_ManInterpolate( Inta_Man_t * p, Sto_Man_t * pCnf, void * vVarsAB, in if ( p->fProofWrite ) { fclose( p->pFile ); +// Sat_ProofChecker( "proof.cnf_" ); p->pFile = NULL; } diff --git a/src/sat/bsat/satInterA_mod.c b/src/sat/bsat/satInterA_mod.c new file mode 100644 index 000000000..faf396a6c --- /dev/null +++ b/src/sat/bsat/satInterA_mod.c @@ -0,0 +1,1104 @@ +/**CFile**************************************************************** + + FileName [satInter.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [SAT sat_solver.] + + Synopsis [Interpolation package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: satInter.c,v 1.4 2005/09/16 22:55:03 casem Exp $] + +***********************************************************************/ + +#include +#include +#include +#include +#include +#include "satStore.h" +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// variable assignments +static const lit LIT_UNDEF = 0xffffffff; + +// interpolation manager +struct Inta_Man_t_ +{ + // clauses of the problems + Sto_Man_t * pCnf; // the set of CNF clauses for A and B + Vec_Int_t * vVarsAB; // the array of global variables + // various parameters + int fVerbose; // verbosiness flag + int fProofVerif; // verifies the proof + int fProofWrite; // writes the proof file + int nVarsAlloc; // the allocated size of var arrays + int nClosAlloc; // the allocated size of clause arrays + // internal BCP + int nRootSize; // the number of root level assignments + int nTrailSize; // the number of assignments made + lit * pTrail; // chronological order of assignments (size nVars) + lit * pAssigns; // assignments by variable (size nVars) + char * pSeens; // temporary mark (size nVars) + Sto_Cls_t ** pReasons; // reasons for each assignment (size nVars) + Sto_Cls_t ** pWatches; // watched clauses for each literal (size 2*nVars) + // interpolation data + Aig_Man_t * pAig; // the AIG manager for recording the interpolant + int * pVarTypes; // variable type (size nVars) [1=A, 0=B, <0=AB] + Aig_Obj_t ** pInters; // storage for interpolants as truth tables (size nClauses) + int nIntersAlloc; // the allocated size of truth table array + // proof recording + int Counter; // counter of resolved clauses + int * pProofNums; // the proof numbers for each clause (size nClauses) + FILE * pFile; // the file for proof recording + // internal verification + lit * pResLits; // the literals of the resolvent + int nResLits; // the number of literals of the resolvent + int nResLitsAlloc;// the number of literals of the resolvent + // runtime stats + int timeBcp; // the runtime for BCP + int timeTrace; // the runtime of trace construction + int timeTotal; // the total runtime of interpolation +}; + +// procedure to get hold of the clauses' truth table +static inline Aig_Obj_t ** Inta_ManAigRead( Inta_Man_t * pMan, Sto_Cls_t * pCls ) { return pMan->pInters + pCls->Id; } +static inline void Inta_ManAigClear( Inta_Man_t * pMan, Aig_Obj_t ** p ) { *p = Aig_ManConst0(pMan->pAig); } +static inline void Inta_ManAigFill( Inta_Man_t * pMan, Aig_Obj_t ** p ) { *p = Aig_ManConst1(pMan->pAig); } +static inline void Inta_ManAigCopy( Inta_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q ) { *p = *q; } +static inline void Inta_ManAigAnd( Inta_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q ) { *p = Aig_And(pMan->pAig, *p, *q); } +static inline void Inta_ManAigOr( Inta_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q ) { *p = Aig_Or(pMan->pAig, *p, *q); } +static inline void Inta_ManAigOrNot( Inta_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q ) { *p = Aig_Or(pMan->pAig, *p, Aig_Not(*q)); } +static inline void Inta_ManAigOrVar( Inta_Man_t * pMan, Aig_Obj_t ** p, int v ) { *p = Aig_Or(pMan->pAig, *p, Aig_IthVar(pMan->pAig, v)); } +static inline void Inta_ManAigOrNotVar( Inta_Man_t * pMan, Aig_Obj_t ** p, int v ) { *p = Aig_Or(pMan->pAig, *p, Aig_Not(Aig_IthVar(pMan->pAig, v))); } + +// reading/writing the proof for a clause +static inline int Inta_ManProofGet( Inta_Man_t * p, Sto_Cls_t * pCls ) { return p->pProofNums[pCls->Id]; } +static inline void Inta_ManProofSet( Inta_Man_t * p, Sto_Cls_t * pCls, int n ) { + p->pProofNums[pCls->Id] = n; + if ( pCls->Id == 5552 || pCls->Id == 5553 ) + { + int x = 0; + } +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocate proof manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Inta_Man_t * Inta_ManAlloc() +{ + Inta_Man_t * p; + // allocate the manager + p = (Inta_Man_t *)malloc( sizeof(Inta_Man_t) ); + memset( p, 0, sizeof(Inta_Man_t) ); + // verification + p->nResLitsAlloc = (1<<16); + p->pResLits = malloc( sizeof(lit) * p->nResLitsAlloc ); + // parameters + p->fProofWrite = 1; + p->fProofVerif = 1; + + return p; +} + +/**Function************************************************************* + + Synopsis [Count common variables in the clauses of A and B.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Inta_ManGlobalVars( Inta_Man_t * p ) +{ + Sto_Cls_t * pClause; + int LargeNum = -100000000; + int Var, nVarsAB, v; + + // mark the variable encountered in the clauses of A + Sto_ManForEachClauseRoot( p->pCnf, pClause ) + { + if ( !pClause->fA ) + break; + for ( v = 0; v < (int)pClause->nLits; v++ ) + p->pVarTypes[lit_var(pClause->pLits[v])] = 1; + } + + // check variables that appear in clauses of B + nVarsAB = 0; + Sto_ManForEachClauseRoot( p->pCnf, pClause ) + { + if ( pClause->fA ) + continue; + for ( v = 0; v < (int)pClause->nLits; v++ ) + { + Var = lit_var(pClause->pLits[v]); + if ( p->pVarTypes[Var] == 1 ) // var of A + { + // change it into a global variable + nVarsAB++; + p->pVarTypes[Var] = LargeNum; + } + } + } + assert( nVarsAB <= Vec_IntSize(p->vVarsAB) ); + + // order global variables + nVarsAB = 0; + Vec_IntForEachEntry( p->vVarsAB, Var, v ) + p->pVarTypes[Var] = -(1+nVarsAB++); + + // check that there is no extra global variables + for ( v = 0; v < p->pCnf->nVars; v++ ) + assert( p->pVarTypes[v] != LargeNum ); + return nVarsAB; +} + +/**Function************************************************************* + + Synopsis [Resize proof manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inta_ManResize( Inta_Man_t * p ) +{ + // check if resizing is needed + if ( p->nVarsAlloc < p->pCnf->nVars ) + { + // find the new size + if ( p->nVarsAlloc == 0 ) + p->nVarsAlloc = 1; + while ( p->nVarsAlloc < p->pCnf->nVars ) + p->nVarsAlloc *= 2; + // resize the arrays + p->pTrail = (lit *) realloc( p->pTrail, sizeof(lit) * p->nVarsAlloc ); + p->pAssigns = (lit *) realloc( p->pAssigns, sizeof(lit) * p->nVarsAlloc ); + p->pSeens = (char *) realloc( p->pSeens, sizeof(char) * p->nVarsAlloc ); + p->pVarTypes = (int *) realloc( p->pVarTypes, sizeof(int) * p->nVarsAlloc ); + p->pReasons = (Sto_Cls_t **)realloc( p->pReasons, sizeof(Sto_Cls_t *) * p->nVarsAlloc ); + p->pWatches = (Sto_Cls_t **)realloc( p->pWatches, sizeof(Sto_Cls_t *) * p->nVarsAlloc*2 ); + } + + // clean the free space + memset( p->pAssigns , 0xff, sizeof(lit) * p->pCnf->nVars ); + memset( p->pSeens , 0, sizeof(char) * p->pCnf->nVars ); + memset( p->pVarTypes, 0, sizeof(int) * p->pCnf->nVars ); + memset( p->pReasons , 0, sizeof(Sto_Cls_t *) * p->pCnf->nVars ); + memset( p->pWatches , 0, sizeof(Sto_Cls_t *) * p->pCnf->nVars*2 ); + + // compute the number of common variables + Inta_ManGlobalVars( p ); + + // check if resizing of clauses is needed + if ( p->nClosAlloc < p->pCnf->nClauses ) + { + // find the new size + if ( p->nClosAlloc == 0 ) + p->nClosAlloc = 1; + while ( p->nClosAlloc < p->pCnf->nClauses ) + p->nClosAlloc *= 2; + // resize the arrays + p->pProofNums = (int *) realloc( p->pProofNums, sizeof(int) * p->nClosAlloc ); + } + memset( p->pProofNums, 0, sizeof(int) * p->pCnf->nClauses ); + + // check if resizing of truth tables is needed + if ( p->nIntersAlloc < p->pCnf->nClauses ) + { + p->nIntersAlloc = p->pCnf->nClauses; + p->pInters = (Aig_Obj_t **) realloc( p->pInters, sizeof(Aig_Obj_t *) * p->nIntersAlloc ); + } + memset( p->pInters, 0, sizeof(Aig_Obj_t *) * p->pCnf->nClauses ); +} + +/**Function************************************************************* + + Synopsis [Deallocate proof manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inta_ManFree( Inta_Man_t * p ) +{ +/* + printf( "Runtime stats:\n" ); +PRT( "BCP ", p->timeBcp ); +PRT( "Trace ", p->timeTrace ); +PRT( "TOTAL ", p->timeTotal ); +*/ + free( p->pInters ); + free( p->pProofNums ); + free( p->pTrail ); + free( p->pAssigns ); + free( p->pSeens ); + free( p->pVarTypes ); + free( p->pReasons ); + free( p->pWatches ); + free( p->pResLits ); + free( p ); +} + + + + +/**Function************************************************************* + + Synopsis [Prints the clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inta_ManPrintClause( Inta_Man_t * p, Sto_Cls_t * pClause ) +{ + int i; + printf( "Clause ID = %d. Proof = %d. {", pClause->Id, Inta_ManProofGet(p, pClause) ); + for ( i = 0; i < (int)pClause->nLits; i++ ) + printf( " %d", pClause->pLits[i] ); + printf( " }\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints the resolvent.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inta_ManPrintResolvent( lit * pResLits, int nResLits ) +{ + int i; + printf( "Resolvent: {" ); + for ( i = 0; i < nResLits; i++ ) + // Yu Hu + // printf( " %d", pResLits[i] ); + printf( " %d", lit_print(pResLits[i]) ); + printf( " }\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints the interpolant for one clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inta_ManPrintInterOne( Inta_Man_t * p, Sto_Cls_t * pClause ) +{ + printf( "Clause %2d : ", pClause->Id ); +// Extra_PrintBinary___( stdout, Inta_ManAigRead(p, pClause), (1 << p->nVarsAB) ); + printf( "\n" ); +} + + + +/**Function************************************************************* + + Synopsis [Adds one clause to the watcher list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Inta_ManWatchClause( Inta_Man_t * p, Sto_Cls_t * pClause, lit Lit ) +{ + assert( lit_check(Lit, p->pCnf->nVars) ); + if ( pClause->pLits[0] == Lit ) + pClause->pNext0 = p->pWatches[lit_neg(Lit)]; + else + { + assert( pClause->pLits[1] == Lit ); + pClause->pNext1 = p->pWatches[lit_neg(Lit)]; + } + p->pWatches[lit_neg(Lit)] = pClause; +} + + +/**Function************************************************************* + + Synopsis [Records implication.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Inta_ManEnqueue( Inta_Man_t * p, lit Lit, Sto_Cls_t * pReason ) +{ + int Var = lit_var(Lit); + if ( p->pAssigns[Var] != LIT_UNDEF ) + return p->pAssigns[Var] == Lit; + p->pAssigns[Var] = Lit; + p->pReasons[Var] = pReason; + p->pTrail[p->nTrailSize++] = Lit; +//printf( "assigning var %d value %d\n", Var, !lit_sign(Lit) ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Records implication.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Inta_ManCancelUntil( Inta_Man_t * p, int Level ) +{ + lit Lit; + int i, Var; + for ( i = p->nTrailSize - 1; i >= Level; i-- ) + { + Lit = p->pTrail[i]; + Var = lit_var( Lit ); + p->pReasons[Var] = NULL; + p->pAssigns[Var] = LIT_UNDEF; +//printf( "cancelling var %d\n", Var ); + } + p->nTrailSize = Level; +} + +/**Function************************************************************* + + Synopsis [Propagate one assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Sto_Cls_t * Inta_ManPropagateOne( Inta_Man_t * p, lit Lit ) +{ + Sto_Cls_t ** ppPrev, * pCur, * pTemp; + lit LitF = lit_neg(Lit); + int i; + // iterate through the literals + ppPrev = p->pWatches + Lit; + for ( pCur = p->pWatches[Lit]; pCur; pCur = *ppPrev ) + { + // make sure the false literal is in the second literal of the clause + if ( pCur->pLits[0] == LitF ) + { + pCur->pLits[0] = pCur->pLits[1]; + pCur->pLits[1] = LitF; + pTemp = pCur->pNext0; + pCur->pNext0 = pCur->pNext1; + pCur->pNext1 = pTemp; + } + assert( pCur->pLits[1] == LitF ); + + // if the first literal is true, the clause is satisfied + if ( pCur->pLits[0] == p->pAssigns[lit_var(pCur->pLits[0])] ) + { + ppPrev = &pCur->pNext1; + continue; + } + + // look for a new literal to watch + for ( i = 2; i < (int)pCur->nLits; i++ ) + { + // skip the case when the literal is false + if ( lit_neg(pCur->pLits[i]) == p->pAssigns[lit_var(pCur->pLits[i])] ) + continue; + // the literal is either true or unassigned - watch it + pCur->pLits[1] = pCur->pLits[i]; + pCur->pLits[i] = LitF; + // remove this clause from the watch list of Lit + *ppPrev = pCur->pNext1; + // add this clause to the watch list of pCur->pLits[i] (now it is pCur->pLits[1]) + Inta_ManWatchClause( p, pCur, pCur->pLits[1] ); + break; + } + if ( i < (int)pCur->nLits ) // found new watch + continue; + + // clause is unit - enqueue new implication + if ( Inta_ManEnqueue(p, pCur->pLits[0], pCur) ) + { + ppPrev = &pCur->pNext1; + continue; + } + + // conflict detected - return the conflict clause + return pCur; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Propagate the current assignments.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Sto_Cls_t * Inta_ManPropagate( Inta_Man_t * p, int Start ) +{ + Sto_Cls_t * pClause; + int i; + int clk = clock(); + for ( i = Start; i < p->nTrailSize; i++ ) + { + pClause = Inta_ManPropagateOne( p, p->pTrail[i] ); + if ( pClause ) + { +p->timeBcp += clock() - clk; + return pClause; + } + } +p->timeBcp += clock() - clk; + return NULL; +} + + +/**Function************************************************************* + + Synopsis [Writes one root clause into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inta_ManProofWriteOne( Inta_Man_t * p, Sto_Cls_t * pClause ) +{ + Inta_ManProofSet( p, pClause, ++p->Counter ); + + if ( p->fProofWrite ) + { + int v; + fprintf( p->pFile, "%d", Inta_ManProofGet(p, pClause) ); + for ( v = 0; v < (int)pClause->nLits; v++ ) + fprintf( p->pFile, " %d", lit_print(pClause->pLits[v]) ); + fprintf( p->pFile, " 0 0\n" ); + } +} + +// Yu Hu +void Inta_ManPrintClauseEx( lit * pResLits, int nResLits ) +{ + int i; + printf( " {" ); + for ( i = 0; i < nResLits; i++ ) + printf( " %d", lit_print(pResLits[i]) ); + printf( " }\n" ); +} + + +/**Function************************************************************* + + Synopsis [Traces the proof for one clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Inta_ManProofTraceOne( Inta_Man_t * p, Sto_Cls_t * pConflict, Sto_Cls_t * pFinal ) +{ + Sto_Cls_t * pReason; + int i, v, Var, PrevId; + int fPrint = 1; // Yu Hu + int clk = clock(); + + // collect resolvent literals + if ( p->fProofVerif ) + { + assert( (int)pConflict->nLits <= p->nResLitsAlloc ); + memcpy( p->pResLits, pConflict->pLits, sizeof(lit) * pConflict->nLits ); + p->nResLits = pConflict->nLits; + } + + // mark all the variables in the conflict as seen + for ( v = 0; v < (int)pConflict->nLits; v++ ) + p->pSeens[lit_var(pConflict->pLits[v])] = 1; + + // start the anticedents +// pFinal->pAntis = Vec_PtrAlloc( 32 ); +// Vec_PtrPush( pFinal->pAntis, pConflict ); + + if ( p->pCnf->nClausesA ) + Inta_ManAigCopy( p, Inta_ManAigRead(p, pFinal), Inta_ManAigRead(p, pConflict) ); + + // follow the trail backwards + PrevId = Inta_ManProofGet(p, pConflict); + for ( i = p->nTrailSize - 1; i >= 0; i-- ) + { + // skip literals that are not involved + Var = lit_var(p->pTrail[i]); + if ( !p->pSeens[Var] ) + continue; + p->pSeens[Var] = 0; + + // skip literals of the resulting clause + pReason = p->pReasons[Var]; + if ( pReason == NULL ) + continue; + assert( p->pTrail[i] == pReason->pLits[0] ); + + // add the variables to seen + for ( v = 1; v < (int)pReason->nLits; v++ ) + p->pSeens[lit_var(pReason->pLits[v])] = 1; + + // record the reason clause + assert( Inta_ManProofGet(p, pReason) > 0 ); + p->Counter++; + if ( p->fProofWrite && p->Counter >= 8370 && p->Counter <= 8380 ) { + fprintf( p->pFile, "%d * %d %d 0\n", p->Counter, PrevId, Inta_ManProofGet(p, pReason) ); + // Yu Hu + printf( "%d * %d %d 0\n", p->Counter, PrevId, Inta_ManProofGet(p, pReason) ); + + if ( p->Counter == 8371 ) + { + int s = 0; + } + } + PrevId = p->Counter; + + if ( p->pCnf->nClausesA ) + { + if ( p->pVarTypes[Var] == 1 ) // var of A + Inta_ManAigOr( p, Inta_ManAigRead(p, pFinal), Inta_ManAigRead(p, pReason) ); + else + Inta_ManAigAnd( p, Inta_ManAigRead(p, pFinal), Inta_ManAigRead(p, pReason) ); + } + + // resolve the temporary resolvent with the reason clause + if ( p->fProofVerif ) + { + int v1, v2; + + // Yu Hu + // if ( fPrint ) + // Inta_ManPrintResolvent( p->pResLits, p->nResLits ); + if ( fPrint && p->Counter >= 8370 && p->Counter <= 8380 ) { + printf("pivot = %d,\n", lit_print(p->pTrail[i])); + Inta_ManPrintClauseEx( p->pResLits, p->nResLits); + } + + // check that the var is present in the resolvent + for ( v1 = 0; v1 < p->nResLits; v1++ ) + if ( lit_var(p->pResLits[v1]) == Var ) + break; + if ( v1 == p->nResLits ) + printf( "Recording clause %d: Cannot find variable %d in the temporary resolvent.\n", pFinal->Id, Var ); + if ( p->pResLits[v1] != lit_neg(pReason->pLits[0]) ) + printf( "Recording clause %d: The resolved variable %d is in the wrong polarity.\n", pFinal->Id, Var ); + // remove this variable from the resolvent + assert( lit_var(p->pResLits[v1]) == Var ); + p->nResLits--; + for ( ; v1 < p->nResLits; v1++ ) + p->pResLits[v1] = p->pResLits[v1+1]; + // add variables of the reason clause + for ( v2 = 1; v2 < (int)pReason->nLits; v2++ ) + { + for ( v1 = 0; v1 < p->nResLits; v1++ ) + if ( lit_var(p->pResLits[v1]) == lit_var(pReason->pLits[v2]) ) + break; + // if it is a new variable, add it to the resolvent + if ( v1 == p->nResLits ) + { + if ( p->nResLits == p->nResLitsAlloc ) + printf( "Recording clause %d: Ran out of space for intermediate resolvent.\n", pFinal->Id ); + p->pResLits[ p->nResLits++ ] = pReason->pLits[v2]; + continue; + } + // if the variable is the same, the literal should be the same too + if ( p->pResLits[v1] == pReason->pLits[v2] ) + continue; + // the literal is different + printf( "Recording clause %d: Trying to resolve the clause with more than one opposite literal.\n", pFinal->Id ); + } + + // Yu Hu + if ( fPrint && p->Counter >= 8370 && p->Counter <= 8380 ) { + Inta_ManPrintClauseEx( pReason->pLits, pReason->nLits); + Inta_ManPrintResolvent( p->pResLits, p->nResLits); + } + + } +// Vec_PtrPush( pFinal->pAntis, pReason ); + } + + // unmark all seen variables +// for ( i = p->nTrailSize - 1; i >= 0; i-- ) +// p->pSeens[lit_var(p->pTrail[i])] = 0; + // check that the literals are unmarked +// for ( i = p->nTrailSize - 1; i >= 0; i-- ) +// assert( p->pSeens[lit_var(p->pTrail[i])] == 0 ); + + // use the resulting clause to check the correctness of resolution + if ( p->fProofVerif ) + { + int v1, v2; + + // Yu Hu +// if ( fPrint ) +// Inta_ManPrintResolvent( p->pResLits, p->nResLits ); + + for ( v1 = 0; v1 < p->nResLits; v1++ ) + { + for ( v2 = 0; v2 < (int)pFinal->nLits; v2++ ) + if ( pFinal->pLits[v2] == p->pResLits[v1] ) + break; + if ( v2 < (int)pFinal->nLits ) + continue; + break; + } + if ( v1 < p->nResLits ) + { + printf( "Recording clause %d: The final resolvent is wrong.\n", pFinal->Id ); + Inta_ManPrintClause( p, pConflict ); + Inta_ManPrintResolvent( p->pResLits, p->nResLits ); + Inta_ManPrintClause( p, pFinal ); + } + + // if there are literals in the clause that are not in the resolvent + // it means that the derived resolvent is stronger than the clause + // we can replace the clause with the resolvent by removing these literals + if ( p->nResLits != (int)pFinal->nLits ) + { + for ( v1 = 0; v1 < (int)pFinal->nLits; v1++ ) + { + for ( v2 = 0; v2 < p->nResLits; v2++ ) + if ( pFinal->pLits[v1] == p->pResLits[v2] ) + break; + if ( v2 < p->nResLits ) + continue; + // remove literal v1 from the final clause + pFinal->nLits--; + for ( v2 = v1; v2 < (int)pFinal->nLits; v2++ ) + pFinal->pLits[v2] = pFinal->pLits[v2+1]; + v1--; + } + assert( p->nResLits == (int)pFinal->nLits ); + } + } +p->timeTrace += clock() - clk; + + // return the proof pointer + if ( p->pCnf->nClausesA ) + { +// Inta_ManPrintInterOne( p, pFinal ); + } + Inta_ManProofSet( p, pFinal, p->Counter ); + if ( pFinal->Id == 5552 || pFinal->Id == 5553 ) + { + int x = 0; + } + + if ( p->pProofNums[pFinal->Id] == p->pProofNums[pFinal->Id-1] ) + p->pProofNums[pFinal->Id] = p->pProofNums[pConflict->Id]; + + return p->Counter; +} + +/**Function************************************************************* + + Synopsis [Records the proof for one clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Inta_ManProofRecordOne( Inta_Man_t * p, Sto_Cls_t * pClause ) +{ + Sto_Cls_t * pConflict; + int i; + + // empty clause never ends up there + assert( pClause->nLits > 0 ); + if ( pClause->nLits == 0 ) + printf( "Error: Empty clause is attempted.\n" ); + + assert( !pClause->fRoot ); + assert( p->nTrailSize == p->nRootSize ); + + // if any of the clause literals are already assumed + // it means that the clause is redundant and can be skipped + for ( i = 0; i < (int)pClause->nLits; i++ ) + if ( p->pAssigns[lit_var(pClause->pLits[i])] == pClause->pLits[i] ) + return 1; + + // add assumptions to the trail + for ( i = 0; i < (int)pClause->nLits; i++ ) + if ( !Inta_ManEnqueue( p, lit_neg(pClause->pLits[i]), NULL ) ) + { + assert( 0 ); // impossible + return 0; + } + + // propagate the assumptions + pConflict = Inta_ManPropagate( p, p->nRootSize ); + if ( pConflict == NULL ) + { + assert( 0 ); // cannot prove + return 0; + } + + // construct the proof + Inta_ManProofTraceOne( p, pConflict, pClause ); + + // undo to the root level + Inta_ManCancelUntil( p, p->nRootSize ); + + // add large clauses to the watched lists + if ( pClause->nLits > 1 ) + { + Inta_ManWatchClause( p, pClause, pClause->pLits[0] ); + Inta_ManWatchClause( p, pClause, pClause->pLits[1] ); + return 1; + } + assert( pClause->nLits == 1 ); + + // if the clause proved is unit, add it and propagate + if ( !Inta_ManEnqueue( p, pClause->pLits[0], pClause ) ) + { + assert( 0 ); // impossible + return 0; + } + + // propagate the assumption + pConflict = Inta_ManPropagate( p, p->nRootSize ); + if ( pConflict ) + { + // construct the proof + Inta_ManProofTraceOne( p, pConflict, p->pCnf->pEmpty ); +// if ( p->fVerbose ) +// printf( "Found last conflict after adding unit clause number %d!\n", pClause->Id ); + return 0; + } + + // update the root level + p->nRootSize = p->nTrailSize; + return 1; +} + +/**Function************************************************************* + + Synopsis [Propagate the root clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Inta_ManProcessRoots( Inta_Man_t * p ) +{ + Sto_Cls_t * pClause; + int Counter; + + // make sure the root clauses are preceeding the learnt clauses + Counter = 0; + Sto_ManForEachClause( p->pCnf, pClause ) + { + assert( (int)pClause->fA == (Counter < (int)p->pCnf->nClausesA) ); + assert( (int)pClause->fRoot == (Counter < (int)p->pCnf->nRoots) ); + Counter++; + } + assert( p->pCnf->nClauses == Counter ); + + // make sure the last clause if empty + assert( p->pCnf->pTail->nLits == 0 ); + + // go through the root unit clauses + p->nTrailSize = 0; + Sto_ManForEachClauseRoot( p->pCnf, pClause ) + { + // create watcher lists for the root clauses + if ( pClause->nLits > 1 ) + { + Inta_ManWatchClause( p, pClause, pClause->pLits[0] ); + Inta_ManWatchClause( p, pClause, pClause->pLits[1] ); + } + // empty clause and large clauses + if ( pClause->nLits != 1 ) + continue; + // unit clause + assert( lit_check(pClause->pLits[0], p->pCnf->nVars) ); + if ( !Inta_ManEnqueue( p, pClause->pLits[0], pClause ) ) + { + // detected root level conflict +// printf( "Error in Inta_ManProcessRoots(): Detected a root-level conflict too early!\n" ); +// assert( 0 ); + // detected root level conflict + Inta_ManProofTraceOne( p, pClause, p->pCnf->pEmpty ); + if ( p->fVerbose ) + printf( "Found root level conflict!\n" ); + return 0; + } + } + + // propagate the root unit clauses + pClause = Inta_ManPropagate( p, 0 ); + if ( pClause ) + { + // detected root level conflict + Inta_ManProofTraceOne( p, pClause, p->pCnf->pEmpty ); + if ( p->fVerbose ) + printf( "Found root level conflict!\n" ); + return 0; + } + + // set the root level + p->nRootSize = p->nTrailSize; + return 1; +} + +/**Function************************************************************* + + Synopsis [Records the proof.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inta_ManPrepareInter( Inta_Man_t * p ) +{ + Sto_Cls_t * pClause; + int Var, VarAB, v; + + // set interpolants for root clauses + Sto_ManForEachClauseRoot( p->pCnf, pClause ) + { + if ( !pClause->fA ) // clause of B + { + Inta_ManAigFill( p, Inta_ManAigRead(p, pClause) ); +// Inta_ManPrintInterOne( p, pClause ); + continue; + } + // clause of A + Inta_ManAigClear( p, Inta_ManAigRead(p, pClause) ); + for ( v = 0; v < (int)pClause->nLits; v++ ) + { + Var = lit_var(pClause->pLits[v]); + if ( p->pVarTypes[Var] < 0 ) // global var + { + VarAB = -p->pVarTypes[Var]-1; + assert( VarAB >= 0 && VarAB < Vec_IntSize(p->vVarsAB) ); + if ( lit_sign(pClause->pLits[v]) ) // negative var + Inta_ManAigOrNotVar( p, Inta_ManAigRead(p, pClause), VarAB ); + else + Inta_ManAigOrVar( p, Inta_ManAigRead(p, pClause), VarAB ); + } + } +// Inta_ManPrintInterOne( p, pClause ); + } +} + +/**Function************************************************************* + + Synopsis [Computes interpolant for the given CNF.] + + Description [Takes the interpolation manager, the CNF deriving by the SAT + solver, which includes ClausesA, ClausesB, and learned clauses. Additional + arguments are the vector of variables common to AB and the verbosiness flag. + Returns the AIG manager with a single output, containing the interpolant.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Inta_ManInterpolate( Inta_Man_t * p, Sto_Man_t * pCnf, void * vVarsAB, int fVerbose ) +{ + Aig_Man_t * pRes; + Aig_Obj_t * pObj; + Sto_Cls_t * pClause; + int RetValue = 1; + int clkTotal = clock(); + + // check that the CNF makes sense + assert( pCnf->nVars > 0 && pCnf->nClauses > 0 ); + p->pCnf = pCnf; + p->fVerbose = fVerbose; + p->vVarsAB = vVarsAB; + p->pAig = pRes = Aig_ManStart( 10000 ); + Aig_IthVar( p->pAig, Vec_IntSize(p->vVarsAB) - 1 ); + + // adjust the manager + Inta_ManResize( p ); + + // prepare the interpolant computation + Inta_ManPrepareInter( p ); + + // construct proof for each clause + // start the proof + if ( p->fProofWrite ) + { + p->pFile = fopen( "proof.cnf_", "w" ); + p->Counter = 0; + } + + // write the root clauses + Sto_ManForEachClauseRoot( p->pCnf, pClause ) + Inta_ManProofWriteOne( p, pClause ); + + // propagate root level assignments + if ( Inta_ManProcessRoots( p ) ) + { + // if there is no conflict, consider learned clauses + Sto_ManForEachClause( p->pCnf, pClause ) + { + if ( pClause->Id == 5552 ) + { + int s = 0; + } + if ( pClause->fRoot ) + continue; + if ( !Inta_ManProofRecordOne( p, pClause ) ) + { + RetValue = 0; + break; + } + } + } + + // stop the proof + if ( p->fProofWrite ) + { + fclose( p->pFile ); + p->pFile = NULL; + } + + if ( fVerbose ) + { +// PRT( "Interpo", clock() - clkTotal ); + printf( "Vars = %d. Roots = %d. Learned = %d. Resol steps = %d. Ave = %.2f. Mem = %.2f Mb\n", + p->pCnf->nVars, p->pCnf->nRoots, p->pCnf->nClauses-p->pCnf->nRoots, p->Counter, + 1.0*(p->Counter-p->pCnf->nRoots)/(p->pCnf->nClauses-p->pCnf->nRoots), + 1.0*Sto_ManMemoryReport(p->pCnf)/(1<<20) ); +p->timeTotal += clock() - clkTotal; + } + + pObj = *Inta_ManAigRead( p, p->pCnf->pTail ); + Aig_ObjCreatePo( pRes, pObj ); + Aig_ManCleanup( pRes ); + + p->pAig = NULL; + return pRes; + +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Inta_ManDeriveClauses( Inta_Man_t * pMan, Sto_Man_t * pCnf, int fClausesA ) +{ + Aig_Man_t * p; + Aig_Obj_t * pMiter, * pSum, * pLit; + Sto_Cls_t * pClause; + int Var, VarAB, v; + p = Aig_ManStart( 10000 ); + pMiter = Aig_ManConst1(p); + Sto_ManForEachClauseRoot( pCnf, pClause ) + { + if ( fClausesA ^ pClause->fA ) // clause of B + continue; + // clause of A + pSum = Aig_ManConst0(p); + for ( v = 0; v < (int)pClause->nLits; v++ ) + { + Var = lit_var(pClause->pLits[v]); + if ( pMan->pVarTypes[Var] < 0 ) // global var + { + VarAB = -pMan->pVarTypes[Var]-1; + assert( VarAB >= 0 && VarAB < Vec_IntSize(pMan->vVarsAB) ); + pLit = Aig_NotCond( Aig_IthVar(p, VarAB), lit_sign(pClause->pLits[v]) ); + } + else + pLit = Aig_NotCond( Aig_IthVar(p, Vec_IntSize(pMan->vVarsAB)+1+Var), lit_sign(pClause->pLits[v]) ); + pSum = Aig_Or( p, pSum, pLit ); + } + pMiter = Aig_And( p, pMiter, pSum ); + } + Aig_ObjCreatePo( p, pMiter ); + return p; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/sat/bsat/satInterA_old.c b/src/sat/bsat/satInterA_old.c new file mode 100644 index 000000000..576289898 --- /dev/null +++ b/src/sat/bsat/satInterA_old.c @@ -0,0 +1,1047 @@ +/**CFile**************************************************************** + + FileName [satInter.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [SAT sat_solver.] + + Synopsis [Interpolation package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: satInter.c,v 1.4 2005/09/16 22:55:03 casem Exp $] + +***********************************************************************/ + +#include +#include +#include +#include +#include +#include "satStore.h" +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// variable assignments +static const lit LIT_UNDEF = 0xffffffff; + +// interpolation manager +struct Inta_Man_t_ +{ + // clauses of the problems + Sto_Man_t * pCnf; // the set of CNF clauses for A and B + Vec_Int_t * vVarsAB; // the array of global variables + // various parameters + int fVerbose; // verbosiness flag + int fProofVerif; // verifies the proof + int fProofWrite; // writes the proof file + int nVarsAlloc; // the allocated size of var arrays + int nClosAlloc; // the allocated size of clause arrays + // internal BCP + int nRootSize; // the number of root level assignments + int nTrailSize; // the number of assignments made + lit * pTrail; // chronological order of assignments (size nVars) + lit * pAssigns; // assignments by variable (size nVars) + char * pSeens; // temporary mark (size nVars) + Sto_Cls_t ** pReasons; // reasons for each assignment (size nVars) + Sto_Cls_t ** pWatches; // watched clauses for each literal (size 2*nVars) + // interpolation data + Aig_Man_t * pAig; // the AIG manager for recording the interpolant + int * pVarTypes; // variable type (size nVars) [1=A, 0=B, <0=AB] + Aig_Obj_t ** pInters; // storage for interpolants as truth tables (size nClauses) + int nIntersAlloc; // the allocated size of truth table array + // proof recording + int Counter; // counter of resolved clauses + int * pProofNums; // the proof numbers for each clause (size nClauses) + FILE * pFile; // the file for proof recording + // internal verification + lit * pResLits; // the literals of the resolvent + int nResLits; // the number of literals of the resolvent + int nResLitsAlloc;// the number of literals of the resolvent + // runtime stats + int timeBcp; // the runtime for BCP + int timeTrace; // the runtime of trace construction + int timeTotal; // the total runtime of interpolation +}; + +// procedure to get hold of the clauses' truth table +static inline Aig_Obj_t ** Inta_ManAigRead( Inta_Man_t * pMan, Sto_Cls_t * pCls ) { return pMan->pInters + pCls->Id; } +static inline void Inta_ManAigClear( Inta_Man_t * pMan, Aig_Obj_t ** p ) { *p = Aig_ManConst0(pMan->pAig); } +static inline void Inta_ManAigFill( Inta_Man_t * pMan, Aig_Obj_t ** p ) { *p = Aig_ManConst1(pMan->pAig); } +static inline void Inta_ManAigCopy( Inta_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q ) { *p = *q; } +static inline void Inta_ManAigAnd( Inta_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q ) { *p = Aig_And(pMan->pAig, *p, *q); } +static inline void Inta_ManAigOr( Inta_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q ) { *p = Aig_Or(pMan->pAig, *p, *q); } +static inline void Inta_ManAigOrNot( Inta_Man_t * pMan, Aig_Obj_t ** p, Aig_Obj_t ** q ) { *p = Aig_Or(pMan->pAig, *p, Aig_Not(*q)); } +static inline void Inta_ManAigOrVar( Inta_Man_t * pMan, Aig_Obj_t ** p, int v ) { *p = Aig_Or(pMan->pAig, *p, Aig_IthVar(pMan->pAig, v)); } +static inline void Inta_ManAigOrNotVar( Inta_Man_t * pMan, Aig_Obj_t ** p, int v ) { *p = Aig_Or(pMan->pAig, *p, Aig_Not(Aig_IthVar(pMan->pAig, v))); } + +// reading/writing the proof for a clause +static inline int Inta_ManProofGet( Inta_Man_t * p, Sto_Cls_t * pCls ) { return p->pProofNums[pCls->Id]; } +static inline void Inta_ManProofSet( Inta_Man_t * p, Sto_Cls_t * pCls, int n ) { p->pProofNums[pCls->Id] = n; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocate proof manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Inta_Man_t * Inta_ManAlloc() +{ + Inta_Man_t * p; + // allocate the manager + p = (Inta_Man_t *)malloc( sizeof(Inta_Man_t) ); + memset( p, 0, sizeof(Inta_Man_t) ); + // verification + p->nResLitsAlloc = (1<<16); + p->pResLits = malloc( sizeof(lit) * p->nResLitsAlloc ); + // parameters + p->fProofWrite = 0; + p->fProofVerif = 1; + return p; +} + +/**Function************************************************************* + + Synopsis [Count common variables in the clauses of A and B.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Inta_ManGlobalVars( Inta_Man_t * p ) +{ + Sto_Cls_t * pClause; + int LargeNum = -100000000; + int Var, nVarsAB, v; + + // mark the variable encountered in the clauses of A + Sto_ManForEachClauseRoot( p->pCnf, pClause ) + { + if ( !pClause->fA ) + break; + for ( v = 0; v < (int)pClause->nLits; v++ ) + p->pVarTypes[lit_var(pClause->pLits[v])] = 1; + } + + // check variables that appear in clauses of B + nVarsAB = 0; + Sto_ManForEachClauseRoot( p->pCnf, pClause ) + { + if ( pClause->fA ) + continue; + for ( v = 0; v < (int)pClause->nLits; v++ ) + { + Var = lit_var(pClause->pLits[v]); + if ( p->pVarTypes[Var] == 1 ) // var of A + { + // change it into a global variable + nVarsAB++; + p->pVarTypes[Var] = LargeNum; + } + } + } + assert( nVarsAB <= Vec_IntSize(p->vVarsAB) ); + + // order global variables + nVarsAB = 0; + Vec_IntForEachEntry( p->vVarsAB, Var, v ) + p->pVarTypes[Var] = -(1+nVarsAB++); + + // check that there is no extra global variables + for ( v = 0; v < p->pCnf->nVars; v++ ) + assert( p->pVarTypes[v] != LargeNum ); + return nVarsAB; +} + +/**Function************************************************************* + + Synopsis [Resize proof manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inta_ManResize( Inta_Man_t * p ) +{ + // check if resizing is needed + if ( p->nVarsAlloc < p->pCnf->nVars ) + { + // find the new size + if ( p->nVarsAlloc == 0 ) + p->nVarsAlloc = 1; + while ( p->nVarsAlloc < p->pCnf->nVars ) + p->nVarsAlloc *= 2; + // resize the arrays + p->pTrail = (lit *) realloc( p->pTrail, sizeof(lit) * p->nVarsAlloc ); + p->pAssigns = (lit *) realloc( p->pAssigns, sizeof(lit) * p->nVarsAlloc ); + p->pSeens = (char *) realloc( p->pSeens, sizeof(char) * p->nVarsAlloc ); + p->pVarTypes = (int *) realloc( p->pVarTypes, sizeof(int) * p->nVarsAlloc ); + p->pReasons = (Sto_Cls_t **)realloc( p->pReasons, sizeof(Sto_Cls_t *) * p->nVarsAlloc ); + p->pWatches = (Sto_Cls_t **)realloc( p->pWatches, sizeof(Sto_Cls_t *) * p->nVarsAlloc*2 ); + } + + // clean the free space + memset( p->pAssigns , 0xff, sizeof(lit) * p->pCnf->nVars ); + memset( p->pSeens , 0, sizeof(char) * p->pCnf->nVars ); + memset( p->pVarTypes, 0, sizeof(int) * p->pCnf->nVars ); + memset( p->pReasons , 0, sizeof(Sto_Cls_t *) * p->pCnf->nVars ); + memset( p->pWatches , 0, sizeof(Sto_Cls_t *) * p->pCnf->nVars*2 ); + + // compute the number of common variables + Inta_ManGlobalVars( p ); + + // check if resizing of clauses is needed + if ( p->nClosAlloc < p->pCnf->nClauses ) + { + // find the new size + if ( p->nClosAlloc == 0 ) + p->nClosAlloc = 1; + while ( p->nClosAlloc < p->pCnf->nClauses ) + p->nClosAlloc *= 2; + // resize the arrays + p->pProofNums = (int *) realloc( p->pProofNums, sizeof(int) * p->nClosAlloc ); + } + memset( p->pProofNums, 0, sizeof(int) * p->pCnf->nClauses ); + + // check if resizing of truth tables is needed + if ( p->nIntersAlloc < p->pCnf->nClauses ) + { + p->nIntersAlloc = p->pCnf->nClauses; + p->pInters = (Aig_Obj_t **) realloc( p->pInters, sizeof(Aig_Obj_t *) * p->nIntersAlloc ); + } + memset( p->pInters, 0, sizeof(Aig_Obj_t *) * p->pCnf->nClauses ); +} + +/**Function************************************************************* + + Synopsis [Deallocate proof manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inta_ManFree( Inta_Man_t * p ) +{ +/* + printf( "Runtime stats:\n" ); +PRT( "BCP ", p->timeBcp ); +PRT( "Trace ", p->timeTrace ); +PRT( "TOTAL ", p->timeTotal ); +*/ + free( p->pInters ); + free( p->pProofNums ); + free( p->pTrail ); + free( p->pAssigns ); + free( p->pSeens ); + free( p->pVarTypes ); + free( p->pReasons ); + free( p->pWatches ); + free( p->pResLits ); + free( p ); +} + + + + +/**Function************************************************************* + + Synopsis [Prints the clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inta_ManPrintClause( Inta_Man_t * p, Sto_Cls_t * pClause ) +{ + int i; + printf( "Clause ID = %d. Proof = %d. {", pClause->Id, Inta_ManProofGet(p, pClause) ); + for ( i = 0; i < (int)pClause->nLits; i++ ) + printf( " %d", pClause->pLits[i] ); + printf( " }\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints the resolvent.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inta_ManPrintResolvent( lit * pResLits, int nResLits ) +{ + int i; + printf( "Resolvent: {" ); + for ( i = 0; i < nResLits; i++ ) + printf( " %d", pResLits[i] ); + printf( " }\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints the interpolant for one clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inta_ManPrintInterOne( Inta_Man_t * p, Sto_Cls_t * pClause ) +{ + printf( "Clause %2d : ", pClause->Id ); +// Extra_PrintBinary___( stdout, Inta_ManAigRead(p, pClause), (1 << p->nVarsAB) ); + printf( "\n" ); +} + + + +/**Function************************************************************* + + Synopsis [Adds one clause to the watcher list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Inta_ManWatchClause( Inta_Man_t * p, Sto_Cls_t * pClause, lit Lit ) +{ + assert( lit_check(Lit, p->pCnf->nVars) ); + if ( pClause->pLits[0] == Lit ) + pClause->pNext0 = p->pWatches[lit_neg(Lit)]; + else + { + assert( pClause->pLits[1] == Lit ); + pClause->pNext1 = p->pWatches[lit_neg(Lit)]; + } + p->pWatches[lit_neg(Lit)] = pClause; +} + + +/**Function************************************************************* + + Synopsis [Records implication.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Inta_ManEnqueue( Inta_Man_t * p, lit Lit, Sto_Cls_t * pReason ) +{ + int Var = lit_var(Lit); + if ( p->pAssigns[Var] != LIT_UNDEF ) + return p->pAssigns[Var] == Lit; + p->pAssigns[Var] = Lit; + p->pReasons[Var] = pReason; + p->pTrail[p->nTrailSize++] = Lit; +//printf( "assigning var %d value %d\n", Var, !lit_sign(Lit) ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Records implication.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Inta_ManCancelUntil( Inta_Man_t * p, int Level ) +{ + lit Lit; + int i, Var; + for ( i = p->nTrailSize - 1; i >= Level; i-- ) + { + Lit = p->pTrail[i]; + Var = lit_var( Lit ); + p->pReasons[Var] = NULL; + p->pAssigns[Var] = LIT_UNDEF; +//printf( "cancelling var %d\n", Var ); + } + p->nTrailSize = Level; +} + +/**Function************************************************************* + + Synopsis [Propagate one assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Sto_Cls_t * Inta_ManPropagateOne( Inta_Man_t * p, lit Lit ) +{ + Sto_Cls_t ** ppPrev, * pCur, * pTemp; + lit LitF = lit_neg(Lit); + int i; + // iterate through the literals + ppPrev = p->pWatches + Lit; + for ( pCur = p->pWatches[Lit]; pCur; pCur = *ppPrev ) + { + // make sure the false literal is in the second literal of the clause + if ( pCur->pLits[0] == LitF ) + { + pCur->pLits[0] = pCur->pLits[1]; + pCur->pLits[1] = LitF; + pTemp = pCur->pNext0; + pCur->pNext0 = pCur->pNext1; + pCur->pNext1 = pTemp; + } + assert( pCur->pLits[1] == LitF ); + + // if the first literal is true, the clause is satisfied + if ( pCur->pLits[0] == p->pAssigns[lit_var(pCur->pLits[0])] ) + { + ppPrev = &pCur->pNext1; + continue; + } + + // look for a new literal to watch + for ( i = 2; i < (int)pCur->nLits; i++ ) + { + // skip the case when the literal is false + if ( lit_neg(pCur->pLits[i]) == p->pAssigns[lit_var(pCur->pLits[i])] ) + continue; + // the literal is either true or unassigned - watch it + pCur->pLits[1] = pCur->pLits[i]; + pCur->pLits[i] = LitF; + // remove this clause from the watch list of Lit + *ppPrev = pCur->pNext1; + // add this clause to the watch list of pCur->pLits[i] (now it is pCur->pLits[1]) + Inta_ManWatchClause( p, pCur, pCur->pLits[1] ); + break; + } + if ( i < (int)pCur->nLits ) // found new watch + continue; + + // clause is unit - enqueue new implication + if ( Inta_ManEnqueue(p, pCur->pLits[0], pCur) ) + { + ppPrev = &pCur->pNext1; + continue; + } + + // conflict detected - return the conflict clause + return pCur; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Propagate the current assignments.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Sto_Cls_t * Inta_ManPropagate( Inta_Man_t * p, int Start ) +{ + Sto_Cls_t * pClause; + int i; + int clk = clock(); + for ( i = Start; i < p->nTrailSize; i++ ) + { + pClause = Inta_ManPropagateOne( p, p->pTrail[i] ); + if ( pClause ) + { +p->timeBcp += clock() - clk; + return pClause; + } + } +p->timeBcp += clock() - clk; + return NULL; +} + + +/**Function************************************************************* + + Synopsis [Writes one root clause into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inta_ManProofWriteOne( Inta_Man_t * p, Sto_Cls_t * pClause ) +{ + Inta_ManProofSet( p, pClause, ++p->Counter ); + + if ( p->fProofWrite ) + { + int v; + fprintf( p->pFile, "%d", Inta_ManProofGet(p, pClause) ); + for ( v = 0; v < (int)pClause->nLits; v++ ) + fprintf( p->pFile, " %d", lit_print(pClause->pLits[v]) ); + fprintf( p->pFile, " 0 0\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Traces the proof for one clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Inta_ManProofTraceOne( Inta_Man_t * p, Sto_Cls_t * pConflict, Sto_Cls_t * pFinal ) +{ + Sto_Cls_t * pReason; + int i, v, Var, PrevId; + int fPrint = 0; + int clk = clock(); + + // collect resolvent literals + if ( p->fProofVerif ) + { + assert( (int)pConflict->nLits <= p->nResLitsAlloc ); + memcpy( p->pResLits, pConflict->pLits, sizeof(lit) * pConflict->nLits ); + p->nResLits = pConflict->nLits; + } + + // mark all the variables in the conflict as seen + for ( v = 0; v < (int)pConflict->nLits; v++ ) + p->pSeens[lit_var(pConflict->pLits[v])] = 1; + + // start the anticedents +// pFinal->pAntis = Vec_PtrAlloc( 32 ); +// Vec_PtrPush( pFinal->pAntis, pConflict ); + + if ( p->pCnf->nClausesA ) + Inta_ManAigCopy( p, Inta_ManAigRead(p, pFinal), Inta_ManAigRead(p, pConflict) ); + + // follow the trail backwards + PrevId = Inta_ManProofGet(p, pConflict); + for ( i = p->nTrailSize - 1; i >= 0; i-- ) + { + // skip literals that are not involved + Var = lit_var(p->pTrail[i]); + if ( !p->pSeens[Var] ) + continue; + p->pSeens[Var] = 0; + + // skip literals of the resulting clause + pReason = p->pReasons[Var]; + if ( pReason == NULL ) + continue; + assert( p->pTrail[i] == pReason->pLits[0] ); + + // add the variables to seen + for ( v = 1; v < (int)pReason->nLits; v++ ) + p->pSeens[lit_var(pReason->pLits[v])] = 1; + + // record the reason clause + assert( Inta_ManProofGet(p, pReason) > 0 ); + p->Counter++; + if ( p->fProofWrite ) + fprintf( p->pFile, "%d * %d %d 0\n", p->Counter, PrevId, Inta_ManProofGet(p, pReason) ); + PrevId = p->Counter; + + if ( p->pCnf->nClausesA ) + { + if ( p->pVarTypes[Var] == 1 ) // var of A + Inta_ManAigOr( p, Inta_ManAigRead(p, pFinal), Inta_ManAigRead(p, pReason) ); + else + Inta_ManAigAnd( p, Inta_ManAigRead(p, pFinal), Inta_ManAigRead(p, pReason) ); + } + + // resolve the temporary resolvent with the reason clause + if ( p->fProofVerif ) + { + int v1, v2; + if ( fPrint ) + Inta_ManPrintResolvent( p->pResLits, p->nResLits ); + // check that the var is present in the resolvent + for ( v1 = 0; v1 < p->nResLits; v1++ ) + if ( lit_var(p->pResLits[v1]) == Var ) + break; + if ( v1 == p->nResLits ) + printf( "Recording clause %d: Cannot find variable %d in the temporary resolvent.\n", pFinal->Id, Var ); + if ( p->pResLits[v1] != lit_neg(pReason->pLits[0]) ) + printf( "Recording clause %d: The resolved variable %d is in the wrong polarity.\n", pFinal->Id, Var ); + // remove this variable from the resolvent + assert( lit_var(p->pResLits[v1]) == Var ); + p->nResLits--; + for ( ; v1 < p->nResLits; v1++ ) + p->pResLits[v1] = p->pResLits[v1+1]; + // add variables of the reason clause + for ( v2 = 1; v2 < (int)pReason->nLits; v2++ ) + { + for ( v1 = 0; v1 < p->nResLits; v1++ ) + if ( lit_var(p->pResLits[v1]) == lit_var(pReason->pLits[v2]) ) + break; + // if it is a new variable, add it to the resolvent + if ( v1 == p->nResLits ) + { + if ( p->nResLits == p->nResLitsAlloc ) + printf( "Recording clause %d: Ran out of space for intermediate resolvent.\n", pFinal->Id ); + p->pResLits[ p->nResLits++ ] = pReason->pLits[v2]; + continue; + } + // if the variable is the same, the literal should be the same too + if ( p->pResLits[v1] == pReason->pLits[v2] ) + continue; + // the literal is different + printf( "Recording clause %d: Trying to resolve the clause with more than one opposite literal.\n", pFinal->Id ); + } + } +// Vec_PtrPush( pFinal->pAntis, pReason ); + } + + // unmark all seen variables +// for ( i = p->nTrailSize - 1; i >= 0; i-- ) +// p->pSeens[lit_var(p->pTrail[i])] = 0; + // check that the literals are unmarked +// for ( i = p->nTrailSize - 1; i >= 0; i-- ) +// assert( p->pSeens[lit_var(p->pTrail[i])] == 0 ); + + // use the resulting clause to check the correctness of resolution + if ( p->fProofVerif ) + { + int v1, v2; + if ( fPrint ) + Inta_ManPrintResolvent( p->pResLits, p->nResLits ); + for ( v1 = 0; v1 < p->nResLits; v1++ ) + { + for ( v2 = 0; v2 < (int)pFinal->nLits; v2++ ) + if ( pFinal->pLits[v2] == p->pResLits[v1] ) + break; + if ( v2 < (int)pFinal->nLits ) + continue; + break; + } + if ( v1 < p->nResLits ) + { + printf( "Recording clause %d: The final resolvent is wrong.\n", pFinal->Id ); + Inta_ManPrintClause( p, pConflict ); + Inta_ManPrintResolvent( p->pResLits, p->nResLits ); + Inta_ManPrintClause( p, pFinal ); + } + + // if there are literals in the clause that are not in the resolvent + // it means that the derived resolvent is stronger than the clause + // we can replace the clause with the resolvent by removing these literals + if ( p->nResLits != (int)pFinal->nLits ) + { + for ( v1 = 0; v1 < (int)pFinal->nLits; v1++ ) + { + for ( v2 = 0; v2 < p->nResLits; v2++ ) + if ( pFinal->pLits[v1] == p->pResLits[v2] ) + break; + if ( v2 < p->nResLits ) + continue; + // remove literal v1 from the final clause + pFinal->nLits--; + for ( v2 = v1; v2 < (int)pFinal->nLits; v2++ ) + pFinal->pLits[v2] = pFinal->pLits[v2+1]; + v1--; + } + assert( p->nResLits == (int)pFinal->nLits ); + } + } +p->timeTrace += clock() - clk; + + // return the proof pointer + if ( p->pCnf->nClausesA ) + { +// Inta_ManPrintInterOne( p, pFinal ); + } + Inta_ManProofSet( p, pFinal, p->Counter ); + return p->Counter; +} + +/**Function************************************************************* + + Synopsis [Records the proof for one clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Inta_ManProofRecordOne( Inta_Man_t * p, Sto_Cls_t * pClause ) +{ + Sto_Cls_t * pConflict; + int i; + + // empty clause never ends up there + assert( pClause->nLits > 0 ); + if ( pClause->nLits == 0 ) + printf( "Error: Empty clause is attempted.\n" ); + + assert( !pClause->fRoot ); + assert( p->nTrailSize == p->nRootSize ); + + // if any of the clause literals are already assumed + // it means that the clause is redundant and can be skipped + for ( i = 0; i < (int)pClause->nLits; i++ ) + if ( p->pAssigns[lit_var(pClause->pLits[i])] == pClause->pLits[i] ) + return 1; + + // add assumptions to the trail + for ( i = 0; i < (int)pClause->nLits; i++ ) + if ( !Inta_ManEnqueue( p, lit_neg(pClause->pLits[i]), NULL ) ) + { + assert( 0 ); // impossible + return 0; + } + + // propagate the assumptions + pConflict = Inta_ManPropagate( p, p->nRootSize ); + if ( pConflict == NULL ) + { + assert( 0 ); // cannot prove + return 0; + } + + // construct the proof + Inta_ManProofTraceOne( p, pConflict, pClause ); + + // undo to the root level + Inta_ManCancelUntil( p, p->nRootSize ); + + // add large clauses to the watched lists + if ( pClause->nLits > 1 ) + { + Inta_ManWatchClause( p, pClause, pClause->pLits[0] ); + Inta_ManWatchClause( p, pClause, pClause->pLits[1] ); + return 1; + } + assert( pClause->nLits == 1 ); + + // if the clause proved is unit, add it and propagate + if ( !Inta_ManEnqueue( p, pClause->pLits[0], pClause ) ) + { + assert( 0 ); // impossible + return 0; + } + + // propagate the assumption + pConflict = Inta_ManPropagate( p, p->nRootSize ); + if ( pConflict ) + { + // construct the proof + Inta_ManProofTraceOne( p, pConflict, p->pCnf->pEmpty ); +// if ( p->fVerbose ) +// printf( "Found last conflict after adding unit clause number %d!\n", pClause->Id ); + return 0; + } + + // update the root level + p->nRootSize = p->nTrailSize; + return 1; +} + +/**Function************************************************************* + + Synopsis [Propagate the root clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Inta_ManProcessRoots( Inta_Man_t * p ) +{ + Sto_Cls_t * pClause; + int Counter; + + // make sure the root clauses are preceeding the learnt clauses + Counter = 0; + Sto_ManForEachClause( p->pCnf, pClause ) + { + assert( (int)pClause->fA == (Counter < (int)p->pCnf->nClausesA) ); + assert( (int)pClause->fRoot == (Counter < (int)p->pCnf->nRoots) ); + Counter++; + } + assert( p->pCnf->nClauses == Counter ); + + // make sure the last clause if empty + assert( p->pCnf->pTail->nLits == 0 ); + + // go through the root unit clauses + p->nTrailSize = 0; + Sto_ManForEachClauseRoot( p->pCnf, pClause ) + { + // create watcher lists for the root clauses + if ( pClause->nLits > 1 ) + { + Inta_ManWatchClause( p, pClause, pClause->pLits[0] ); + Inta_ManWatchClause( p, pClause, pClause->pLits[1] ); + } + // empty clause and large clauses + if ( pClause->nLits != 1 ) + continue; + // unit clause + assert( lit_check(pClause->pLits[0], p->pCnf->nVars) ); + if ( !Inta_ManEnqueue( p, pClause->pLits[0], pClause ) ) + { + // detected root level conflict +// printf( "Error in Inta_ManProcessRoots(): Detected a root-level conflict too early!\n" ); +// assert( 0 ); + // detected root level conflict + Inta_ManProofTraceOne( p, pClause, p->pCnf->pEmpty ); + if ( p->fVerbose ) + printf( "Found root level conflict!\n" ); + return 0; + } + } + + // propagate the root unit clauses + pClause = Inta_ManPropagate( p, 0 ); + if ( pClause ) + { + // detected root level conflict + Inta_ManProofTraceOne( p, pClause, p->pCnf->pEmpty ); + if ( p->fVerbose ) + printf( "Found root level conflict!\n" ); + return 0; + } + + // set the root level + p->nRootSize = p->nTrailSize; + return 1; +} + +/**Function************************************************************* + + Synopsis [Records the proof.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Inta_ManPrepareInter( Inta_Man_t * p ) +{ + Sto_Cls_t * pClause; + int Var, VarAB, v; + + // set interpolants for root clauses + Sto_ManForEachClauseRoot( p->pCnf, pClause ) + { + if ( !pClause->fA ) // clause of B + { + Inta_ManAigFill( p, Inta_ManAigRead(p, pClause) ); +// Inta_ManPrintInterOne( p, pClause ); + continue; + } + // clause of A + Inta_ManAigClear( p, Inta_ManAigRead(p, pClause) ); + for ( v = 0; v < (int)pClause->nLits; v++ ) + { + Var = lit_var(pClause->pLits[v]); + if ( p->pVarTypes[Var] < 0 ) // global var + { + VarAB = -p->pVarTypes[Var]-1; + assert( VarAB >= 0 && VarAB < Vec_IntSize(p->vVarsAB) ); + if ( lit_sign(pClause->pLits[v]) ) // negative var + Inta_ManAigOrNotVar( p, Inta_ManAigRead(p, pClause), VarAB ); + else + Inta_ManAigOrVar( p, Inta_ManAigRead(p, pClause), VarAB ); + } + } +// Inta_ManPrintInterOne( p, pClause ); + } +} + +/**Function************************************************************* + + Synopsis [Computes interpolant for the given CNF.] + + Description [Takes the interpolation manager, the CNF deriving by the SAT + solver, which includes ClausesA, ClausesB, and learned clauses. Additional + arguments are the vector of variables common to AB and the verbosiness flag. + Returns the AIG manager with a single output, containing the interpolant.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Inta_ManInterpolate( Inta_Man_t * p, Sto_Man_t * pCnf, void * vVarsAB, int fVerbose ) +{ + Aig_Man_t * pRes; + Aig_Obj_t * pObj; + Sto_Cls_t * pClause; + int RetValue = 1; + int clkTotal = clock(); + + // check that the CNF makes sense + assert( pCnf->nVars > 0 && pCnf->nClauses > 0 ); + p->pCnf = pCnf; + p->fVerbose = fVerbose; + p->vVarsAB = vVarsAB; + p->pAig = pRes = Aig_ManStart( 10000 ); + Aig_IthVar( p->pAig, Vec_IntSize(p->vVarsAB) - 1 ); + + // adjust the manager + Inta_ManResize( p ); + + // prepare the interpolant computation + Inta_ManPrepareInter( p ); + + // construct proof for each clause + // start the proof + if ( p->fProofWrite ) + { + p->pFile = fopen( "proof.cnf_", "w" ); + p->Counter = 0; + } + + // write the root clauses + Sto_ManForEachClauseRoot( p->pCnf, pClause ) + Inta_ManProofWriteOne( p, pClause ); + + // propagate root level assignments + if ( Inta_ManProcessRoots( p ) ) + { + // if there is no conflict, consider learned clauses + Sto_ManForEachClause( p->pCnf, pClause ) + { + if ( pClause->fRoot ) + continue; + if ( !Inta_ManProofRecordOne( p, pClause ) ) + { + RetValue = 0; + break; + } + } + } + + // stop the proof + if ( p->fProofWrite ) + { + fclose( p->pFile ); + p->pFile = NULL; + } + + if ( fVerbose ) + { +// PRT( "Interpo", clock() - clkTotal ); + printf( "Vars = %d. Roots = %d. Learned = %d. Resol steps = %d. Ave = %.2f. Mem = %.2f Mb\n", + p->pCnf->nVars, p->pCnf->nRoots, p->pCnf->nClauses-p->pCnf->nRoots, p->Counter, + 1.0*(p->Counter-p->pCnf->nRoots)/(p->pCnf->nClauses-p->pCnf->nRoots), + 1.0*Sto_ManMemoryReport(p->pCnf)/(1<<20) ); +p->timeTotal += clock() - clkTotal; + } + + pObj = *Inta_ManAigRead( p, p->pCnf->pTail ); + Aig_ObjCreatePo( pRes, pObj ); + Aig_ManCleanup( pRes ); + + p->pAig = NULL; + return pRes; + +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Inta_ManDeriveClauses( Inta_Man_t * pMan, Sto_Man_t * pCnf, int fClausesA ) +{ + Aig_Man_t * p; + Aig_Obj_t * pMiter, * pSum, * pLit; + Sto_Cls_t * pClause; + int Var, VarAB, v; + p = Aig_ManStart( 10000 ); + pMiter = Aig_ManConst1(p); + Sto_ManForEachClauseRoot( pCnf, pClause ) + { + if ( fClausesA ^ pClause->fA ) // clause of B + continue; + // clause of A + pSum = Aig_ManConst0(p); + for ( v = 0; v < (int)pClause->nLits; v++ ) + { + Var = lit_var(pClause->pLits[v]); + if ( pMan->pVarTypes[Var] < 0 ) // global var + { + VarAB = -pMan->pVarTypes[Var]-1; + assert( VarAB >= 0 && VarAB < Vec_IntSize(pMan->vVarsAB) ); + pLit = Aig_NotCond( Aig_IthVar(p, VarAB), lit_sign(pClause->pLits[v]) ); + } + else + pLit = Aig_NotCond( Aig_IthVar(p, Vec_IntSize(pMan->vVarsAB)+1+Var), lit_sign(pClause->pLits[v]) ); + pSum = Aig_Or( p, pSum, pLit ); + } + pMiter = Aig_And( p, pMiter, pSum ); + } + Aig_ObjCreatePo( p, pMiter ); + return p; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/sat/bsat/satInterA_yu_hu.c b/src/sat/bsat/satInterA_yu_hu.c index 2005e5587..aa2289f26 100644 --- a/src/sat/bsat/satInterA_yu_hu.c +++ b/src/sat/bsat/satInterA_yu_hu.c @@ -114,6 +114,7 @@ Inta_Man_t * Inta_ManAlloc() // parameters p->fProofWrite = 1; p->fProofVerif = 1; + return p; } @@ -289,16 +290,6 @@ void Inta_ManPrintClause( Inta_Man_t * p, Sto_Cls_t * pClause ) printf( " }\n" ); } -// Yu Hu -void Inta_ManPrintClauseEx( lit * pResLits, int nResLits ) -{ - int i; - printf( " {" ); - for ( i = 0; i < nResLits; i++ ) - printf( " %d", lit_print(pResLits[i]) ); - printf( " }\n" ); -} - /**Function************************************************************* Synopsis [Prints the resolvent.] @@ -315,6 +306,8 @@ void Inta_ManPrintResolvent( lit * pResLits, int nResLits ) int i; printf( "Resolvent: {" ); for ( i = 0; i < nResLits; i++ ) + // Yu Hu + // printf( " %d", pResLits[i] ); printf( " %d", lit_print(pResLits[i]) ); printf( " }\n" ); } @@ -537,6 +530,17 @@ void Inta_ManProofWriteOne( Inta_Man_t * p, Sto_Cls_t * pClause ) } } +// Yu Hu +void Inta_ManPrintClauseEx( lit * pResLits, int nResLits ) +{ + int i; + printf( " {" ); + for ( i = 0; i < nResLits; i++ ) + printf( " %d", lit_print(pResLits[i]) ); + printf( " }\n" ); +} + + /**Function************************************************************* Synopsis [Traces the proof for one clause.] @@ -594,7 +598,6 @@ int Inta_ManProofTraceOne( Inta_Man_t * p, Sto_Cls_t * pConflict, Sto_Cls_t * pF for ( v = 1; v < (int)pReason->nLits; v++ ) p->pSeens[lit_var(pReason->pLits[v])] = 1; - // record the reason clause assert( Inta_ManProofGet(p, pReason) > 0 ); p->Counter++; @@ -617,14 +620,15 @@ int Inta_ManProofTraceOne( Inta_Man_t * p, Sto_Cls_t * pConflict, Sto_Cls_t * pF if ( p->fProofVerif ) { int v1, v2; + // Yu Hu -// if ( fPrint ) -// Inta_ManPrintResolvent( p->pResLits, p->nResLits ); - if ( fPrint ) { - printf("pivot = %d,\n", lit_print(p->pTrail[i])); - Inta_ManPrintClauseEx( p->pResLits, p->nResLits); - } - + // if ( fPrint ) + // Inta_ManPrintResolvent( p->pResLits, p->nResLits ); + if ( fPrint ) { + printf("pivot = %d,\n", lit_print(p->pTrail[i])); + Inta_ManPrintClauseEx( p->pResLits, p->nResLits); + } + // check that the var is present in the resolvent for ( v1 = 0; v1 < p->nResLits; v1++ ) if ( lit_var(p->pResLits[v1]) == Var ) @@ -660,12 +664,12 @@ int Inta_ManProofTraceOne( Inta_Man_t * p, Sto_Cls_t * pConflict, Sto_Cls_t * pF } // Yu Hu - if ( fPrint ) { - Inta_ManPrintClauseEx( pReason->pLits, pReason->nLits); - Inta_ManPrintResolvent( p->pResLits, p->nResLits ); - } - } + if ( fPrint ) { + Inta_ManPrintClauseEx( pReason->pLits, pReason->nLits); + Inta_ManPrintResolvent( p->pResLits, p->nResLits); + } + } // Vec_PtrPush( pFinal->pAntis, pReason ); } @@ -680,10 +684,11 @@ int Inta_ManProofTraceOne( Inta_Man_t * p, Sto_Cls_t * pConflict, Sto_Cls_t * pF if ( p->fProofVerif ) { int v1, v2; - if ( fPrint ){ - // Yu Hu + + // Yu Hu +// if ( fPrint ) // Inta_ManPrintResolvent( p->pResLits, p->nResLits ); - } + for ( v1 = 0; v1 < p->nResLits; v1++ ) { for ( v2 = 0; v2 < (int)pFinal->nLits; v2++ ) @@ -700,6 +705,27 @@ int Inta_ManProofTraceOne( Inta_Man_t * p, Sto_Cls_t * pConflict, Sto_Cls_t * pF Inta_ManPrintResolvent( p->pResLits, p->nResLits ); Inta_ManPrintClause( p, pFinal ); } + + // if there are literals in the clause that are not in the resolvent + // it means that the derived resolvent is stronger than the clause + // we can replace the clause with the resolvent by removing these literals + if ( p->nResLits != (int)pFinal->nLits ) + { + for ( v1 = 0; v1 < (int)pFinal->nLits; v1++ ) + { + for ( v2 = 0; v2 < p->nResLits; v2++ ) + if ( pFinal->pLits[v1] == p->pResLits[v2] ) + break; + if ( v2 < p->nResLits ) + continue; + // remove literal v1 from the final clause + pFinal->nLits--; + for ( v2 = v1; v2 < (int)pFinal->nLits; v2++ ) + pFinal->pLits[v2] = pFinal->pLits[v2+1]; + v1--; + } + assert( p->nResLits == (int)pFinal->nLits ); + } } p->timeTrace += clock() - clk; @@ -733,9 +759,16 @@ int Inta_ManProofRecordOne( Inta_Man_t * p, Sto_Cls_t * pClause ) if ( pClause->nLits == 0 ) printf( "Error: Empty clause is attempted.\n" ); - // add assumptions to the trail assert( !pClause->fRoot ); assert( p->nTrailSize == p->nRootSize ); + + // if any of the clause literals are already assumed + // it means that the clause is redundant and can be skipped + for ( i = 0; i < (int)pClause->nLits; i++ ) + if ( p->pAssigns[lit_var(pClause->pLits[i])] == pClause->pLits[i] ) + return 1; + + // add assumptions to the trail for ( i = 0; i < (int)pClause->nLits; i++ ) if ( !Inta_ManEnqueue( p, lit_neg(pClause->pLits[i]), NULL ) ) { diff --git a/src/sat/lsat/solver.h b/src/sat/lsat/solver.h new file mode 100644 index 000000000..a15e42d6d --- /dev/null +++ b/src/sat/lsat/solver.h @@ -0,0 +1,124 @@ +/****************************************************************************************[solver.h] +Copyright (c) 2008, Niklas Sorensson + 2008, Koen Claessen + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ + +#ifndef Minisat_solver_h +#define Minisat_solver_h + +// SolverTypes: +// +typedef struct solver_t solver; +typedef int solver_Var; +typedef int solver_Lit; +typedef int solver_lbool; + +// Constants: (can these be made inline-able?) +// + +extern const solver_lbool solver_l_True; +extern const solver_lbool solver_l_False; +extern const solver_lbool solver_l_Undef; + + +solver* solver_new (void); +void solver_delete (solver* s); + +solver_Var solver_newVar (solver *s); +solver_Lit solver_newLit (solver *s); + +solver_Lit solver_mkLit (solver_Var x); +solver_Lit solver_mkLit_args (solver_Var x, int sign); +solver_Lit solver_negate (solver_Lit p); + +solver_Var solver_var (solver_Lit p); +int solver_sign (solver_Lit p); + +int solver_addClause (solver *s, int len, solver_Lit *ps); +void solver_addClause_begin (solver *s); +void solver_addClause_addLit(solver *s, solver_Lit p); +int solver_addClause_commit(solver *s); + +int solver_simplify (solver *s); + +int solver_solve (solver *s, int len, solver_Lit *ps); +void solver_solve_begin (solver *s); +void solver_solve_addLit (solver *s, solver_Lit p); +int solver_solve_commit (solver *s); + +int solver_okay (solver *s); + +void solver_setPolarity (solver *s, solver_Var v, int b); +void solver_setDecisionVar (solver *s, solver_Var v, int b); + +solver_lbool solver_get_l_True (void); +solver_lbool solver_get_l_False (void); +solver_lbool solver_get_l_Undef (void); + +solver_lbool solver_value_Var (solver *s, solver_Var x); +solver_lbool solver_value_Lit (solver *s, solver_Lit p); + +solver_lbool solver_modelValue_Var (solver *s, solver_Var x); +solver_lbool solver_modelValue_Lit (solver *s, solver_Lit p); + +int solver_num_assigns (solver *s); +int solver_num_clauses (solver *s); +int solver_num_learnts (solver *s); +int solver_num_vars (solver *s); +int solver_num_freeVars (solver *s); + +int solver_conflict_len (solver *s); +solver_Lit solver_conflict_nthLit (solver *s, int i); + +// Setters: + +void solver_set_verbosity (solver *s, int v); + +// Getters: + +int solver_num_conflicts (solver *s); + +/* TODO + + // Mode of operation: + // + int verbosity; + double var_decay; + double clause_decay; + double random_var_freq; + double random_seed; + double restart_luby_start; // The factor with which the values of the luby sequence is multiplied to get the restart (default 100) + double restart_luby_inc; // The constant that the luby sequence uses powers of (default 2) + bool expensive_ccmin; // FIXME: describe. + bool rnd_pol; // FIXME: describe. + + int restart_first; // The initial restart limit. (default 100) + double restart_inc; // The factor with which the restart limit is multiplied in each restart. (default 1.5) + double learntsize_factor; // The intitial limit for learnt clauses is a factor of the original clauses. (default 1 / 3) + double learntsize_inc; // The limit for learnt clauses is multiplied with this factor each restart. (default 1.1) + + int learntsize_adjust_start_confl; + double learntsize_adjust_inc; + + // Statistics: (read-only member variable) + // + uint64_t starts, decisions, rnd_decisions, propagations, conflicts; + uint64_t dec_vars, clauses_literals, learnts_literals, max_literals, tot_literals; +*/ + +#endif