From 24f2a120f2203acc8038ccce4e8dd141564a7a04 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Mon, 24 Aug 2015 21:09:50 -0700 Subject: Changes to be able to compile ABC without CUDD. --- src/bdd/bbr/bbr.h | 93 ++ src/bdd/bbr/bbrCex.c | 172 +++ src/bdd/bbr/bbrImage.c | 1327 +++++++++++++++++++++++ src/bdd/bbr/bbrNtbdd.c | 218 ++++ src/bdd/bbr/bbrReach.c | 615 +++++++++++ src/bdd/bbr/bbr_.c | 52 + src/bdd/bbr/module.make | 4 + src/bdd/extrab/extraBdd.h | 317 ++++++ src/bdd/extrab/extraBddAuto.c | 1563 +++++++++++++++++++++++++++ src/bdd/extrab/extraBddCas.c | 1235 +++++++++++++++++++++ src/bdd/extrab/extraBddImage.c | 1162 ++++++++++++++++++++ src/bdd/extrab/extraBddKmap.c | 876 +++++++++++++++ src/bdd/extrab/extraBddMisc.c | 2342 ++++++++++++++++++++++++++++++++++++++++ src/bdd/extrab/extraBddSymm.c | 1474 +++++++++++++++++++++++++ src/bdd/extrab/extraBddTime.c | 660 +++++++++++ src/bdd/extrab/extraBddUnate.c | 646 +++++++++++ src/bdd/extrab/module.make | 8 + src/bdd/llb/llb.c | 52 + src/bdd/llb/llb.h | 96 ++ src/bdd/llb/llb1Cluster.c | 356 ++++++ src/bdd/llb/llb1Constr.c | 313 ++++++ src/bdd/llb/llb1Core.c | 222 ++++ src/bdd/llb/llb1Group.c | 474 ++++++++ src/bdd/llb/llb1Hint.c | 226 ++++ src/bdd/llb/llb1Man.c | 218 ++++ src/bdd/llb/llb1Matrix.c | 430 ++++++++ src/bdd/llb/llb1Pivot.c | 254 +++++ src/bdd/llb/llb1Reach.c | 904 ++++++++++++++++ src/bdd/llb/llb1Sched.c | 257 +++++ src/bdd/llb/llb2Bad.c | 138 +++ src/bdd/llb/llb2Core.c | 777 +++++++++++++ src/bdd/llb/llb2Driver.c | 222 ++++ src/bdd/llb/llb2Dump.c | 104 ++ src/bdd/llb/llb2Flow.c | 1376 +++++++++++++++++++++++ src/bdd/llb/llb2Image.c | 482 +++++++++ src/bdd/llb/llb3Image.c | 1095 +++++++++++++++++++ src/bdd/llb/llb3Nonlin.c | 872 +++++++++++++++ src/bdd/llb/llb4Cex.c | 320 ++++++ src/bdd/llb/llb4Cluster.c | 452 ++++++++ src/bdd/llb/llb4Image.c | 863 +++++++++++++++ src/bdd/llb/llb4Map.c | 123 +++ src/bdd/llb/llb4Nonlin.c | 1185 ++++++++++++++++++++ src/bdd/llb/llb4Sweep.c | 589 ++++++++++ src/bdd/llb/llbInt.h | 212 ++++ src/bdd/llb/module.make | 22 + src/bdd/parse/module.make | 3 - src/bdd/parse/parse.h | 62 -- src/bdd/parse/parseCore.c | 536 --------- src/bdd/parse/parseEqn.c | 358 ------ src/bdd/parse/parseInt.h | 79 -- src/bdd/parse/parseStack.c | 248 ----- src/misc/extra/extraBdd.h | 317 ------ src/misc/extra/extraBddAuto.c | 1563 --------------------------- src/misc/extra/extraBddCas.c | 1235 --------------------- src/misc/extra/extraBddImage.c | 1162 -------------------- src/misc/extra/extraBddKmap.c | 876 --------------- src/misc/extra/extraBddMisc.c | 2342 ---------------------------------------- src/misc/extra/extraBddSymm.c | 1474 ------------------------- src/misc/extra/extraBddTime.c | 660 ----------- src/misc/extra/extraBddUnate.c | 646 ----------- src/misc/parse/module.make | 2 + src/misc/parse/parse.h | 62 ++ src/misc/parse/parseCore.c | 536 +++++++++ src/misc/parse/parseEqn.c | 355 ++++++ src/misc/parse/parseInt.h | 77 ++ src/misc/parse/parseStack.c | 248 +++++ src/proof/bbr/bbr.h | 93 -- src/proof/bbr/bbrCex.c | 172 --- src/proof/bbr/bbrImage.c | 1327 ----------------------- src/proof/bbr/bbrNtbdd.c | 218 ---- src/proof/bbr/bbrReach.c | 615 ----------- src/proof/bbr/bbr_.c | 52 - src/proof/bbr/module.make | 4 - src/proof/llb/llb.c | 52 - src/proof/llb/llb.h | 96 -- src/proof/llb/llb1Cluster.c | 356 ------ src/proof/llb/llb1Constr.c | 313 ------ src/proof/llb/llb1Core.c | 222 ---- src/proof/llb/llb1Group.c | 474 -------- src/proof/llb/llb1Hint.c | 226 ---- src/proof/llb/llb1Man.c | 218 ---- src/proof/llb/llb1Matrix.c | 430 -------- src/proof/llb/llb1Pivot.c | 254 ----- src/proof/llb/llb1Reach.c | 904 ---------------- src/proof/llb/llb1Sched.c | 257 ----- src/proof/llb/llb2Bad.c | 138 --- src/proof/llb/llb2Core.c | 777 ------------- src/proof/llb/llb2Driver.c | 222 ---- src/proof/llb/llb2Dump.c | 104 -- src/proof/llb/llb2Flow.c | 1376 ----------------------- src/proof/llb/llb2Image.c | 482 --------- src/proof/llb/llb3Image.c | 1095 ------------------- src/proof/llb/llb3Nonlin.c | 872 --------------- src/proof/llb/llb4Cex.c | 320 ------ src/proof/llb/llb4Cluster.c | 452 -------- src/proof/llb/llb4Image.c | 863 --------------- src/proof/llb/llb4Map.c | 123 --- src/proof/llb/llb4Nonlin.c | 1185 -------------------- src/proof/llb/llb4Sweep.c | 589 ---------- src/proof/llb/llbInt.h | 212 ---- src/proof/llb/module.make | 22 - 101 files changed, 26678 insertions(+), 26676 deletions(-) create mode 100644 src/bdd/bbr/bbr.h create mode 100644 src/bdd/bbr/bbrCex.c create mode 100644 src/bdd/bbr/bbrImage.c create mode 100644 src/bdd/bbr/bbrNtbdd.c create mode 100644 src/bdd/bbr/bbrReach.c create mode 100644 src/bdd/bbr/bbr_.c create mode 100644 src/bdd/bbr/module.make create mode 100644 src/bdd/extrab/extraBdd.h create mode 100644 src/bdd/extrab/extraBddAuto.c create mode 100644 src/bdd/extrab/extraBddCas.c create mode 100644 src/bdd/extrab/extraBddImage.c create mode 100644 src/bdd/extrab/extraBddKmap.c create mode 100644 src/bdd/extrab/extraBddMisc.c create mode 100644 src/bdd/extrab/extraBddSymm.c create mode 100644 src/bdd/extrab/extraBddTime.c create mode 100644 src/bdd/extrab/extraBddUnate.c create mode 100644 src/bdd/extrab/module.make create mode 100644 src/bdd/llb/llb.c create mode 100644 src/bdd/llb/llb.h create mode 100644 src/bdd/llb/llb1Cluster.c create mode 100644 src/bdd/llb/llb1Constr.c create mode 100644 src/bdd/llb/llb1Core.c create mode 100644 src/bdd/llb/llb1Group.c create mode 100644 src/bdd/llb/llb1Hint.c create mode 100644 src/bdd/llb/llb1Man.c create mode 100644 src/bdd/llb/llb1Matrix.c create mode 100644 src/bdd/llb/llb1Pivot.c create mode 100644 src/bdd/llb/llb1Reach.c create mode 100644 src/bdd/llb/llb1Sched.c create mode 100644 src/bdd/llb/llb2Bad.c create mode 100644 src/bdd/llb/llb2Core.c create mode 100644 src/bdd/llb/llb2Driver.c create mode 100644 src/bdd/llb/llb2Dump.c create mode 100644 src/bdd/llb/llb2Flow.c create mode 100644 src/bdd/llb/llb2Image.c create mode 100644 src/bdd/llb/llb3Image.c create mode 100644 src/bdd/llb/llb3Nonlin.c create mode 100644 src/bdd/llb/llb4Cex.c create mode 100644 src/bdd/llb/llb4Cluster.c create mode 100644 src/bdd/llb/llb4Image.c create mode 100644 src/bdd/llb/llb4Map.c create mode 100644 src/bdd/llb/llb4Nonlin.c create mode 100644 src/bdd/llb/llb4Sweep.c create mode 100644 src/bdd/llb/llbInt.h create mode 100644 src/bdd/llb/module.make delete mode 100644 src/bdd/parse/module.make delete mode 100644 src/bdd/parse/parse.h delete mode 100644 src/bdd/parse/parseCore.c delete mode 100644 src/bdd/parse/parseEqn.c delete mode 100644 src/bdd/parse/parseInt.h delete mode 100644 src/bdd/parse/parseStack.c delete mode 100644 src/misc/extra/extraBdd.h delete mode 100644 src/misc/extra/extraBddAuto.c delete mode 100644 src/misc/extra/extraBddCas.c delete mode 100644 src/misc/extra/extraBddImage.c delete mode 100644 src/misc/extra/extraBddKmap.c delete mode 100644 src/misc/extra/extraBddMisc.c delete mode 100644 src/misc/extra/extraBddSymm.c delete mode 100644 src/misc/extra/extraBddTime.c delete mode 100644 src/misc/extra/extraBddUnate.c create mode 100644 src/misc/parse/module.make create mode 100644 src/misc/parse/parse.h create mode 100644 src/misc/parse/parseCore.c create mode 100644 src/misc/parse/parseEqn.c create mode 100644 src/misc/parse/parseInt.h create mode 100644 src/misc/parse/parseStack.c delete mode 100644 src/proof/bbr/bbr.h delete mode 100644 src/proof/bbr/bbrCex.c delete mode 100644 src/proof/bbr/bbrImage.c delete mode 100644 src/proof/bbr/bbrNtbdd.c delete mode 100644 src/proof/bbr/bbrReach.c delete mode 100644 src/proof/bbr/bbr_.c delete mode 100644 src/proof/bbr/module.make delete mode 100644 src/proof/llb/llb.c delete mode 100644 src/proof/llb/llb.h delete mode 100644 src/proof/llb/llb1Cluster.c delete mode 100644 src/proof/llb/llb1Constr.c delete mode 100644 src/proof/llb/llb1Core.c delete mode 100644 src/proof/llb/llb1Group.c delete mode 100644 src/proof/llb/llb1Hint.c delete mode 100644 src/proof/llb/llb1Man.c delete mode 100644 src/proof/llb/llb1Matrix.c delete mode 100644 src/proof/llb/llb1Pivot.c delete mode 100644 src/proof/llb/llb1Reach.c delete mode 100644 src/proof/llb/llb1Sched.c delete mode 100644 src/proof/llb/llb2Bad.c delete mode 100644 src/proof/llb/llb2Core.c delete mode 100644 src/proof/llb/llb2Driver.c delete mode 100644 src/proof/llb/llb2Dump.c delete mode 100644 src/proof/llb/llb2Flow.c delete mode 100644 src/proof/llb/llb2Image.c delete mode 100644 src/proof/llb/llb3Image.c delete mode 100644 src/proof/llb/llb3Nonlin.c delete mode 100644 src/proof/llb/llb4Cex.c delete mode 100644 src/proof/llb/llb4Cluster.c delete mode 100644 src/proof/llb/llb4Image.c delete mode 100644 src/proof/llb/llb4Map.c delete mode 100644 src/proof/llb/llb4Nonlin.c delete mode 100644 src/proof/llb/llb4Sweep.c delete mode 100644 src/proof/llb/llbInt.h delete mode 100644 src/proof/llb/module.make diff --git a/src/bdd/bbr/bbr.h b/src/bdd/bbr/bbr.h new file mode 100644 index 00000000..1db638e8 --- /dev/null +++ b/src/bdd/bbr/bbr.h @@ -0,0 +1,93 @@ +/**CFile**************************************************************** + + FileName [bbr.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD-based reachability analysis.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: bbr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__bbr__bbr_h +#define ABC__aig__bbr__bbr_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include "aig/aig/aig.h" +#include "aig/saig/saig.h" +#include "bdd/cudd/cuddInt.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline DdNode * Aig_ObjGlobalBdd( Aig_Obj_t * pObj ) { return (DdNode *)pObj->pData; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== bbrImage.c ==========================================================*/ +typedef struct Bbr_ImageTree_t_ Bbr_ImageTree_t; +extern Bbr_ImageTree_t * Bbr_bddImageStart( + DdManager * dd, DdNode * bCare, + int nParts, DdNode ** pbParts, + int nVars, DdNode ** pbVars, int nBddMax, int fVerbose ); +extern DdNode * Bbr_bddImageCompute( Bbr_ImageTree_t * pTree, DdNode * bCare ); +extern void Bbr_bddImageTreeDelete( Bbr_ImageTree_t * pTree ); +extern DdNode * Bbr_bddImageRead( Bbr_ImageTree_t * pTree ); +typedef struct Bbr_ImageTree2_t_ Bbr_ImageTree2_t; +extern Bbr_ImageTree2_t * Bbr_bddImageStart2( + DdManager * dd, DdNode * bCare, + int nParts, DdNode ** pbParts, + int nVars, DdNode ** pbVars, int fVerbose ); +extern DdNode * Bbr_bddImageCompute2( Bbr_ImageTree2_t * pTree, DdNode * bCare ); +extern void Bbr_bddImageTreeDelete2( Bbr_ImageTree2_t * pTree ); +extern DdNode * Bbr_bddImageRead2( Bbr_ImageTree2_t * pTree ); +/*=== bbrNtbdd.c ==========================================================*/ +extern void Aig_ManFreeGlobalBdds( Aig_Man_t * p, DdManager * dd ); +extern int Aig_ManSizeOfGlobalBdds( Aig_Man_t * p ); +extern DdManager * Aig_ManComputeGlobalBdds( Aig_Man_t * p, int nBddSizeMax, int fDropInternal, int fReorder, int fVerbose ); +/*=== bbrReach.c ==========================================================*/ +extern int Aig_ManVerifyUsingBdds( Aig_Man_t * p, Saig_ParBbr_t * pPars ); +extern void Bbr_ManSetDefaultParams( Saig_ParBbr_t * p ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/bdd/bbr/bbrCex.c b/src/bdd/bbr/bbrCex.c new file mode 100644 index 00000000..31a46d61 --- /dev/null +++ b/src/bdd/bbr/bbrCex.c @@ -0,0 +1,172 @@ +/**CFile**************************************************************** + + FileName [bbrCex.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD-based reachability analysis.] + + Synopsis [Procedures to derive a satisfiable counter-example.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: bbrCex.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "bbr.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern DdNode * Bbr_bddComputeRangeCube( DdManager * dd, int iStart, int iStop ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Derives the counter-example using the set of reached states.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Aig_ManVerifyUsingBddsCountExample( Aig_Man_t * p, DdManager * dd, + DdNode ** pbParts, Vec_Ptr_t * vOnionRings, DdNode * bCubeFirst, + int iOutput, int fVerbose, int fSilent ) +{ + Abc_Cex_t * pCex; + Aig_Obj_t * pObj; + Bbr_ImageTree_t * pTree; + DdNode * bCubeNs, * bState, * bImage; + DdNode * bTemp, * bVar, * bRing; + int i, v, RetValue, nPiOffset; + char * pValues; + abctime clk = Abc_Clock(); +//printf( "\nDeriving counter-example.\n" ); + + // allocate room for the counter-example + pCex = Abc_CexAlloc( Saig_ManRegNum(p), Saig_ManPiNum(p), Vec_PtrSize(vOnionRings)+1 ); + pCex->iFrame = Vec_PtrSize(vOnionRings); + pCex->iPo = iOutput; + nPiOffset = Saig_ManRegNum(p) + Saig_ManPiNum(p) * Vec_PtrSize(vOnionRings); + + // create the cube of NS variables + bCubeNs = Bbr_bddComputeRangeCube( dd, Saig_ManCiNum(p), Saig_ManCiNum(p)+Saig_ManRegNum(p) ); Cudd_Ref( bCubeNs ); + pTree = Bbr_bddImageStart( dd, bCubeNs, Saig_ManRegNum(p), pbParts, Saig_ManCiNum(p), dd->vars, 100000000, fVerbose ); + Cudd_RecursiveDeref( dd, bCubeNs ); + if ( pTree == NULL ) + { + if ( !fSilent ) + printf( "BDDs blew up during qualitification scheduling. " ); + return NULL; + } + + // allocate room for the cube + pValues = ABC_ALLOC( char, dd->size ); + + // get the last cube + RetValue = Cudd_bddPickOneCube( dd, bCubeFirst, pValues ); + assert( RetValue ); + + // write PIs of counter-example + Saig_ManForEachPi( p, pObj, i ) + if ( pValues[i] == 1 ) + Abc_InfoSetBit( pCex->pData, nPiOffset + i ); + nPiOffset -= Saig_ManPiNum(p); + + // write state in terms of NS variables + bState = (dd)->one; Cudd_Ref( bState ); + Saig_ManForEachLo( p, pObj, i ) + { + bVar = Cudd_NotCond( dd->vars[Saig_ManCiNum(p)+i], pValues[Saig_ManPiNum(p)+i] != 1 ); + bState = Cudd_bddAnd( dd, bTemp = bState, bVar ); Cudd_Ref( bState ); + Cudd_RecursiveDeref( dd, bTemp ); + } + + // perform backward analysis + Vec_PtrForEachEntryReverse( DdNode *, vOnionRings, bRing, v ) + { + // compute the next states + bImage = Bbr_bddImageCompute( pTree, bState ); + if ( bImage == NULL ) + { + Cudd_RecursiveDeref( dd, bState ); + if ( !fSilent ) + printf( "BDDs blew up during image computation. " ); + Bbr_bddImageTreeDelete( pTree ); + ABC_FREE( pValues ); + return NULL; + } + Cudd_Ref( bImage ); + Cudd_RecursiveDeref( dd, bState ); + + // intersect with the previous set + bImage = Cudd_bddAnd( dd, bTemp = bImage, bRing ); Cudd_Ref( bImage ); + Cudd_RecursiveDeref( dd, bTemp ); + + // find any assignment of the BDD + RetValue = Cudd_bddPickOneCube( dd, bImage, pValues ); + assert( RetValue ); + Cudd_RecursiveDeref( dd, bImage ); + + // write PIs of counter-example + Saig_ManForEachPi( p, pObj, i ) + if ( pValues[i] == 1 ) + Abc_InfoSetBit( pCex->pData, nPiOffset + i ); + nPiOffset -= Saig_ManPiNum(p); + + // check that we get the init state + if ( v == 0 ) + { + Saig_ManForEachLo( p, pObj, i ) + assert( pValues[Saig_ManPiNum(p)+i] == 0 ); + break; + } + + // write state in terms of NS variables + bState = (dd)->one; Cudd_Ref( bState ); + Saig_ManForEachLo( p, pObj, i ) + { + bVar = Cudd_NotCond( dd->vars[Saig_ManCiNum(p)+i], pValues[Saig_ManPiNum(p)+i] != 1 ); + bState = Cudd_bddAnd( dd, bTemp = bState, bVar ); Cudd_Ref( bState ); + Cudd_RecursiveDeref( dd, bTemp ); + } + } + // cleanup + Bbr_bddImageTreeDelete( pTree ); + ABC_FREE( pValues ); + // verify the counter example + if ( Vec_PtrSize(vOnionRings) < 1000 ) + { + RetValue = Saig_ManVerifyCex( p, pCex ); + if ( RetValue == 0 && !fSilent ) + printf( "Aig_ManVerifyUsingBdds(): Counter-example verification has FAILED.\n" ); + } + if ( fVerbose && !fSilent ) + { + ABC_PRT( "Counter-example generation time", Abc_Clock() - clk ); + } + return pCex; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/bbr/bbrImage.c b/src/bdd/bbr/bbrImage.c new file mode 100644 index 00000000..1ff3d0b6 --- /dev/null +++ b/src/bdd/bbr/bbrImage.c @@ -0,0 +1,1327 @@ +/**CFile**************************************************************** + + FileName [bbrImage.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD-based reachability analysis.] + + Synopsis [Performs image computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: bbrImage.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "bbr.h" +#include "bdd/mtr/mtr.h" + +ABC_NAMESPACE_IMPL_START + + +/* + The ideas implemented in this file are inspired by the paper: + Pankaj Chauhan, Edmund Clarke, Somesh Jha, Jim Kukula, Tom Shiple, + Helmut Veith, Dong Wang. Non-linear Quantification Scheduling in + Image Computation. ICCAD, 2001. +*/ + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +typedef struct Bbr_ImageNode_t_ Bbr_ImageNode_t; +typedef struct Bbr_ImagePart_t_ Bbr_ImagePart_t; +typedef struct Bbr_ImageVar_t_ Bbr_ImageVar_t; + +struct Bbr_ImageTree_t_ +{ + Bbr_ImageNode_t * pRoot; // the root of quantification tree + Bbr_ImageNode_t * pCare; // the leaf node with the care set + DdNode * bCareSupp; // the cube to quantify from the care + int fVerbose; // the verbosity flag + int nNodesMax; // the max number of nodes in one iter + int nNodesMaxT; // the overall max number of nodes + int nIter; // the number of iterations with this tree + int nBddMax; // the number of node to stop +}; + +struct Bbr_ImageNode_t_ +{ + DdManager * dd; // the manager + DdNode * bCube; // the cube to quantify + DdNode * bImage; // the partial image + Bbr_ImageNode_t * pNode1; // the first branch + Bbr_ImageNode_t * pNode2; // the second branch + Bbr_ImagePart_t * pPart; // the partition (temporary) +}; + +struct Bbr_ImagePart_t_ +{ + DdNode * bFunc; // the partition + DdNode * bSupp; // the support of this partition + int nNodes; // the number of BDD nodes + short nSupp; // the number of support variables + short iPart; // the number of this partition +}; + +struct Bbr_ImageVar_t_ +{ + int iNum; // the BDD index of this variable + DdNode * bParts; // the partition numbers + int nParts; // the number of partitions +}; + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +#define b0 Cudd_Not((dd)->one) +#define b1 (dd)->one + +#ifndef ABC_PRB +#define ABC_PRB(dd,f) printf("%s = ", #f); Bbr_bddPrint(dd,f); printf("\n") +#endif + +/**AutomaticStart*************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static Bbr_ImagePart_t ** Bbr_CreateParts( DdManager * dd, + int nParts, DdNode ** pbParts, DdNode * bCare ); +static Bbr_ImageVar_t ** Bbr_CreateVars( DdManager * dd, + int nParts, Bbr_ImagePart_t ** pParts, + int nVars, DdNode ** pbVarsNs ); +static Bbr_ImageNode_t ** Bbr_CreateNodes( DdManager * dd, + int nParts, Bbr_ImagePart_t ** pParts, + int nVars, Bbr_ImageVar_t ** pVars ); +static void Bbr_DeleteParts_rec( Bbr_ImageNode_t * pNode ); +static int Bbr_BuildTreeNode( DdManager * dd, + int nNodes, Bbr_ImageNode_t ** pNodes, + int nVars, Bbr_ImageVar_t ** pVars, int * pfStop, int nBddMax ); +static Bbr_ImageNode_t * Bbr_MergeTopNodes( DdManager * dd, + int nNodes, Bbr_ImageNode_t ** pNodes ); +static void Bbr_bddImageTreeDelete_rec( Bbr_ImageNode_t * pNode ); +static int Bbr_bddImageCompute_rec( Bbr_ImageTree_t * pTree, Bbr_ImageNode_t * pNode ); +static int Bbr_FindBestVariable( DdManager * dd, + int nNodes, Bbr_ImageNode_t ** pNodes, + int nVars, Bbr_ImageVar_t ** pVars ); +static void Bbr_FindBestPartitions( DdManager * dd, DdNode * bParts, + int nNodes, Bbr_ImageNode_t ** pNodes, + int * piNode1, int * piNode2 ); +static Bbr_ImageNode_t * Bbr_CombineTwoNodes( DdManager * dd, DdNode * bCube, + Bbr_ImageNode_t * pNode1, Bbr_ImageNode_t * pNode2 ); + +static void Bbr_bddImagePrintLatchDependency( DdManager * dd, DdNode * bCare, + int nParts, DdNode ** pbParts, + int nVars, DdNode ** pbVars ); +static void Bbr_bddImagePrintLatchDependencyOne( DdManager * dd, DdNode * bFunc, + DdNode * bVarsCs, DdNode * bVarsNs, int iPart ); + +static void Bbr_bddImagePrintTree( Bbr_ImageTree_t * pTree ); +static void Bbr_bddImagePrintTree_rec( Bbr_ImageNode_t * pNode, int nOffset ); + +static void Bbr_bddPrint( DdManager * dd, DdNode * F ); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function************************************************************* + + Synopsis [Starts the image computation using tree-based scheduling.] + + Description [This procedure starts the image computation. It uses + the given care set to test-run the image computation and creates the + quantification tree by scheduling variable quantifications. The tree can + be used to compute images for other care sets without rescheduling. + In this case, Bbr_bddImageCompute() should be called.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bbr_ImageTree_t * Bbr_bddImageStart( + DdManager * dd, DdNode * bCare, // the care set + int nParts, DdNode ** pbParts, // the partitions for image computation + int nVars, DdNode ** pbVars, int nBddMax, int fVerbose ) // the NS and parameter variables (not quantified!) +{ + Bbr_ImageTree_t * pTree; + Bbr_ImagePart_t ** pParts; + Bbr_ImageVar_t ** pVars; + Bbr_ImageNode_t ** pNodes, * pCare; + int fStop, v; + + if ( fVerbose && dd->size <= 80 ) + Bbr_bddImagePrintLatchDependency( dd, bCare, nParts, pbParts, nVars, pbVars ); + + // create variables, partitions and leaf nodes + pParts = Bbr_CreateParts( dd, nParts, pbParts, bCare ); + pVars = Bbr_CreateVars( dd, nParts + 1, pParts, nVars, pbVars ); + pNodes = Bbr_CreateNodes( dd, nParts + 1, pParts, dd->size, pVars ); + pCare = pNodes[nParts]; + + // process the nodes + while ( Bbr_BuildTreeNode( dd, nParts + 1, pNodes, dd->size, pVars, &fStop, nBddMax ) ); + + // consider the case of BDD node blowup + if ( fStop ) + { + for ( v = 0; v < dd->size; v++ ) + if ( pVars[v] ) + ABC_FREE( pVars[v] ); + ABC_FREE( pVars ); + for ( v = 0; v <= nParts; v++ ) + if ( pNodes[v] ) + { + Bbr_DeleteParts_rec( pNodes[v] ); + Bbr_bddImageTreeDelete_rec( pNodes[v] ); + } + ABC_FREE( pNodes ); + ABC_FREE( pParts ); + return NULL; + } + + // make sure the variables are gone + for ( v = 0; v < dd->size; v++ ) + assert( pVars[v] == NULL ); + ABC_FREE( pVars ); + + // create the tree + pTree = ABC_ALLOC( Bbr_ImageTree_t, 1 ); + memset( pTree, 0, sizeof(Bbr_ImageTree_t) ); + pTree->pCare = pCare; + pTree->nBddMax = nBddMax; + pTree->fVerbose = fVerbose; + + // merge the topmost nodes + while ( (pTree->pRoot = Bbr_MergeTopNodes( dd, nParts + 1, pNodes )) == NULL ); + + // make sure the nodes are gone + for ( v = 0; v < nParts + 1; v++ ) + assert( pNodes[v] == NULL ); + ABC_FREE( pNodes ); + +// if ( fVerbose ) +// Bbr_bddImagePrintTree( pTree ); + + // set the support of the care set + pTree->bCareSupp = Cudd_Support( dd, bCare ); Cudd_Ref( pTree->bCareSupp ); + + // clean the partitions + Bbr_DeleteParts_rec( pTree->pRoot ); + ABC_FREE( pParts ); + + return pTree; +} + +/**Function************************************************************* + + Synopsis [Compute the image.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Bbr_bddImageCompute( Bbr_ImageTree_t * pTree, DdNode * bCare ) +{ + DdManager * dd = pTree->pCare->dd; + DdNode * bSupp, * bRem; + + pTree->nIter++; + + // make sure the supports are okay + bSupp = Cudd_Support( dd, bCare ); Cudd_Ref( bSupp ); + if ( bSupp != pTree->bCareSupp ) + { + bRem = Cudd_bddExistAbstract( dd, bSupp, pTree->bCareSupp ); Cudd_Ref( bRem ); + if ( bRem != b1 ) + { +printf( "Original care set support: " ); +ABC_PRB( dd, pTree->bCareSupp ); +printf( "Current care set support: " ); +ABC_PRB( dd, bSupp ); + Cudd_RecursiveDeref( dd, bSupp ); + Cudd_RecursiveDeref( dd, bRem ); + printf( "The care set depends on some vars that were not in the care set during scheduling.\n" ); + return NULL; + } + Cudd_RecursiveDeref( dd, bRem ); + } + Cudd_RecursiveDeref( dd, bSupp ); + + // remove the previous image + Cudd_RecursiveDeref( dd, pTree->pCare->bImage ); + pTree->pCare->bImage = bCare; Cudd_Ref( bCare ); + + // compute the image + pTree->nNodesMax = 0; + if ( !Bbr_bddImageCompute_rec( pTree, pTree->pRoot ) ) + return NULL; + if ( pTree->nNodesMaxT < pTree->nNodesMax ) + pTree->nNodesMaxT = pTree->nNodesMax; + +// if ( pTree->fVerbose ) +// printf( "Iter %2d : Max nodes = %5d.\n", pTree->nIter, pTree->nNodesMax ); + return pTree->pRoot->bImage; +} + +/**Function************************************************************* + + Synopsis [Delete the tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbr_bddImageTreeDelete( Bbr_ImageTree_t * pTree ) +{ + if ( pTree->bCareSupp ) + Cudd_RecursiveDeref( pTree->pRoot->dd, pTree->bCareSupp ); + Bbr_bddImageTreeDelete_rec( pTree->pRoot ); + ABC_FREE( pTree ); +} + +/**Function************************************************************* + + Synopsis [Reads the image from the tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Bbr_bddImageRead( Bbr_ImageTree_t * pTree ) +{ + return pTree->pRoot->bImage; +} + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Outputs the BDD in a readable format.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +void Bbr_bddPrint( DdManager * dd, DdNode * F ) +{ + DdGen * Gen; + int * Cube; + CUDD_VALUE_TYPE Value; + int nVars = dd->size; + int fFirstCube = 1; + int i; + + if ( F == NULL ) + { + printf("NULL"); + return; + } + if ( F == b0 ) + { + printf("Constant 0"); + return; + } + if ( F == b1 ) + { + printf("Constant 1"); + return; + } + + Cudd_ForeachCube( dd, F, Gen, Cube, Value ) + { + if ( fFirstCube ) + fFirstCube = 0; + else +// Output << " + "; + printf( " + " ); + + for ( i = 0; i < nVars; i++ ) + if ( Cube[i] == 0 ) + printf( "[%d]'", i ); +// printf( "%c'", (char)('a'+i) ); + else if ( Cube[i] == 1 ) + printf( "[%d]", i ); +// printf( "%c", (char)('a'+i) ); + } + +// printf("\n"); +} + +/*---------------------------------------------------------------------------*/ +/* Definition of static Functions */ +/*---------------------------------------------------------------------------*/ + +/**Function************************************************************* + + Synopsis [Creates partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bbr_ImagePart_t ** Bbr_CreateParts( DdManager * dd, + int nParts, DdNode ** pbParts, DdNode * bCare ) +{ + Bbr_ImagePart_t ** pParts; + int i; + + // start the partitions + pParts = ABC_ALLOC( Bbr_ImagePart_t *, nParts + 1 ); + // create structures for each variable + for ( i = 0; i < nParts; i++ ) + { + pParts[i] = ABC_ALLOC( Bbr_ImagePart_t, 1 ); + pParts[i]->bFunc = pbParts[i]; Cudd_Ref( pParts[i]->bFunc ); + pParts[i]->bSupp = Cudd_Support( dd, pParts[i]->bFunc ); Cudd_Ref( pParts[i]->bSupp ); + pParts[i]->nSupp = Cudd_SupportSize( dd, pParts[i]->bSupp ); + pParts[i]->nNodes = Cudd_DagSize( pParts[i]->bFunc ); + pParts[i]->iPart = i; + } + // add the care set as the last partition + pParts[nParts] = ABC_ALLOC( Bbr_ImagePart_t, 1 ); + pParts[nParts]->bFunc = bCare; Cudd_Ref( pParts[nParts]->bFunc ); + pParts[nParts]->bSupp = Cudd_Support( dd, pParts[nParts]->bFunc ); Cudd_Ref( pParts[nParts]->bSupp ); + pParts[nParts]->nSupp = Cudd_SupportSize( dd, pParts[nParts]->bSupp ); + pParts[nParts]->nNodes = Cudd_DagSize( pParts[nParts]->bFunc ); + pParts[nParts]->iPart = nParts; + return pParts; +} + +/**Function************************************************************* + + Synopsis [Creates variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bbr_ImageVar_t ** Bbr_CreateVars( DdManager * dd, + int nParts, Bbr_ImagePart_t ** pParts, + int nVars, DdNode ** pbVars ) +{ + Bbr_ImageVar_t ** pVars; + DdNode ** pbFuncs; + DdNode * bCubeNs, * bSupp, * bParts, * bTemp, * bSuppTemp; + int nVarsTotal, iVar, p, Counter; + + // put all the functions into one array + pbFuncs = ABC_ALLOC( DdNode *, nParts ); + for ( p = 0; p < nParts; p++ ) + pbFuncs[p] = pParts[p]->bSupp; + bSupp = Cudd_VectorSupport( dd, pbFuncs, nParts ); Cudd_Ref( bSupp ); + ABC_FREE( pbFuncs ); + + // remove the NS vars + bCubeNs = Cudd_bddComputeCube( dd, pbVars, NULL, nVars ); Cudd_Ref( bCubeNs ); + bSupp = Cudd_bddExistAbstract( dd, bTemp = bSupp, bCubeNs ); Cudd_Ref( bSupp ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCubeNs ); + + // get the number of I and CS variables to be quantified + nVarsTotal = Cudd_SupportSize( dd, bSupp ); + + // start the variables + pVars = ABC_ALLOC( Bbr_ImageVar_t *, dd->size ); + memset( pVars, 0, sizeof(Bbr_ImageVar_t *) * dd->size ); + // create structures for each variable + for ( bSuppTemp = bSupp; bSuppTemp != b1; bSuppTemp = cuddT(bSuppTemp) ) + { + iVar = bSuppTemp->index; + pVars[iVar] = ABC_ALLOC( Bbr_ImageVar_t, 1 ); + pVars[iVar]->iNum = iVar; + // collect all the parts this var belongs to + Counter = 0; + bParts = b1; Cudd_Ref( bParts ); + for ( p = 0; p < nParts; p++ ) + if ( Cudd_bddLeq( dd, pParts[p]->bSupp, dd->vars[bSuppTemp->index] ) ) + { + bParts = Cudd_bddAnd( dd, bTemp = bParts, dd->vars[p] ); Cudd_Ref( bParts ); + Cudd_RecursiveDeref( dd, bTemp ); + Counter++; + } + pVars[iVar]->bParts = bParts; // takes ref + pVars[iVar]->nParts = Counter; + } + Cudd_RecursiveDeref( dd, bSupp ); + return pVars; +} + +/**Function************************************************************* + + Synopsis [Creates variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bbr_ImageNode_t ** Bbr_CreateNodes( DdManager * dd, + int nParts, Bbr_ImagePart_t ** pParts, + int nVars, Bbr_ImageVar_t ** pVars ) +{ + Bbr_ImageNode_t ** pNodes; + Bbr_ImageNode_t * pNode; + DdNode * bTemp; + int i, v, iPart; +/* + DdManager * dd; // the manager + DdNode * bCube; // the cube to quantify + DdNode * bImage; // the partial image + Bbr_ImageNode_t * pNode1; // the first branch + Bbr_ImageNode_t * pNode2; // the second branch + Bbr_ImagePart_t * pPart; // the partition (temporary) +*/ + // start the partitions + pNodes = ABC_ALLOC( Bbr_ImageNode_t *, nParts ); + // create structures for each leaf nodes + for ( i = 0; i < nParts; i++ ) + { + pNodes[i] = ABC_ALLOC( Bbr_ImageNode_t, 1 ); + memset( pNodes[i], 0, sizeof(Bbr_ImageNode_t) ); + pNodes[i]->dd = dd; + pNodes[i]->pPart = pParts[i]; + } + // find the quantification cubes for each leaf node + for ( v = 0; v < nVars; v++ ) + { + if ( pVars[v] == NULL ) + continue; + assert( pVars[v]->nParts > 0 ); + if ( pVars[v]->nParts > 1 ) + continue; + iPart = pVars[v]->bParts->index; + if ( pNodes[iPart]->bCube == NULL ) + { + pNodes[iPart]->bCube = dd->vars[v]; + Cudd_Ref( dd->vars[v] ); + } + else + { + pNodes[iPart]->bCube = Cudd_bddAnd( dd, bTemp = pNodes[iPart]->bCube, dd->vars[v] ); + Cudd_Ref( pNodes[iPart]->bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + } + // remove these variables + Cudd_RecursiveDeref( dd, pVars[v]->bParts ); + ABC_FREE( pVars[v] ); + } + + // assign the leaf node images + for ( i = 0; i < nParts; i++ ) + { + pNode = pNodes[i]; + if ( pNode->bCube ) + { + // update the partition + pParts[i]->bFunc = Cudd_bddExistAbstract( dd, bTemp = pParts[i]->bFunc, pNode->bCube ); + Cudd_Ref( pParts[i]->bFunc ); + Cudd_RecursiveDeref( dd, bTemp ); + // update the support the partition + pParts[i]->bSupp = Cudd_bddExistAbstract( dd, bTemp = pParts[i]->bSupp, pNode->bCube ); + Cudd_Ref( pParts[i]->bSupp ); + Cudd_RecursiveDeref( dd, bTemp ); + // update the numbers + pParts[i]->nSupp = Cudd_SupportSize( dd, pParts[i]->bSupp ); + pParts[i]->nNodes = Cudd_DagSize( pParts[i]->bFunc ); + // get rid of the cube + // save the last (care set) quantification cube + if ( i < nParts - 1 ) + { + Cudd_RecursiveDeref( dd, pNode->bCube ); + pNode->bCube = NULL; + } + } + // copy the function + pNode->bImage = pParts[i]->bFunc; Cudd_Ref( pNode->bImage ); + } +/* + for ( i = 0; i < nParts; i++ ) + { + pNode = pNodes[i]; +ABC_PRB( dd, pNode->bCube ); +ABC_PRB( dd, pNode->pPart->bFunc ); +ABC_PRB( dd, pNode->pPart->bSupp ); +printf( "\n" ); + } +*/ + return pNodes; +} + + +/**Function************************************************************* + + Synopsis [Delete the partitions from the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbr_DeleteParts_rec( Bbr_ImageNode_t * pNode ) +{ + Bbr_ImagePart_t * pPart; + if ( pNode->pNode1 ) + Bbr_DeleteParts_rec( pNode->pNode1 ); + if ( pNode->pNode2 ) + Bbr_DeleteParts_rec( pNode->pNode2 ); + pPart = pNode->pPart; + Cudd_RecursiveDeref( pNode->dd, pPart->bFunc ); + Cudd_RecursiveDeref( pNode->dd, pPart->bSupp ); + ABC_FREE( pNode->pPart ); +} + +/**Function************************************************************* + + Synopsis [Delete the partitions from the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbr_bddImageTreeDelete_rec( Bbr_ImageNode_t * pNode ) +{ + if ( pNode->pNode1 ) + Bbr_bddImageTreeDelete_rec( pNode->pNode1 ); + if ( pNode->pNode2 ) + Bbr_bddImageTreeDelete_rec( pNode->pNode2 ); + if ( pNode->bCube ) + Cudd_RecursiveDeref( pNode->dd, pNode->bCube ); + if ( pNode->bImage ) + Cudd_RecursiveDeref( pNode->dd, pNode->bImage ); + assert( pNode->pPart == NULL ); + ABC_FREE( pNode ); +} + +/**Function************************************************************* + + Synopsis [Recompute the image.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bbr_bddImageCompute_rec( Bbr_ImageTree_t * pTree, Bbr_ImageNode_t * pNode ) +{ + DdManager * dd = pNode->dd; + DdNode * bTemp; + int nNodes; + + // trivial case + if ( pNode->pNode1 == NULL ) + { + if ( pNode->bCube ) + { + pNode->bImage = Cudd_bddExistAbstract( dd, bTemp = pNode->bImage, pNode->bCube ); + Cudd_Ref( pNode->bImage ); + Cudd_RecursiveDeref( dd, bTemp ); + } + return 1; + } + + // compute the children + if ( pNode->pNode1 ) + if ( !Bbr_bddImageCompute_rec( pTree, pNode->pNode1 ) ) + return 0; + if ( pNode->pNode2 ) + if ( !Bbr_bddImageCompute_rec( pTree, pNode->pNode2 ) ) + return 0; + + // clean the old image + if ( pNode->bImage ) + Cudd_RecursiveDeref( dd, pNode->bImage ); + pNode->bImage = NULL; + + // compute the new image + if ( pNode->bCube ) + pNode->bImage = Cudd_bddAndAbstract( dd, + pNode->pNode1->bImage, pNode->pNode2->bImage, pNode->bCube ); + else + pNode->bImage = Cudd_bddAnd( dd, pNode->pNode1->bImage, pNode->pNode2->bImage ); + Cudd_Ref( pNode->bImage ); + + if ( pTree->fVerbose ) + { + nNodes = Cudd_DagSize( pNode->bImage ); + if ( pTree->nNodesMax < nNodes ) + pTree->nNodesMax = nNodes; + } + if ( dd->keys-dd->dead > (unsigned)pTree->nBddMax ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Builds the tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bbr_BuildTreeNode( DdManager * dd, + int nNodes, Bbr_ImageNode_t ** pNodes, + int nVars, Bbr_ImageVar_t ** pVars, int * pfStop, int nBddMax ) +{ + Bbr_ImageNode_t * pNode1, * pNode2; + Bbr_ImageVar_t * pVar; + Bbr_ImageNode_t * pNode; + DdNode * bCube, * bTemp, * bSuppTemp;//, * bParts; + int iNode1, iNode2; + int iVarBest, nSupp, v; + + // find the best variable + iVarBest = Bbr_FindBestVariable( dd, nNodes, pNodes, nVars, pVars ); + if ( iVarBest == -1 ) + return 0; +/* +for ( v = 0; v < nVars; v++ ) +{ + DdNode * bSupp; + if ( pVars[v] == NULL ) + continue; + printf( "%3d :", v ); + printf( "%3d ", pVars[v]->nParts ); + bSupp = Cudd_Support( dd, pVars[v]->bParts ); Cudd_Ref( bSupp ); + Bbr_bddPrint( dd, bSupp ); printf( "\n" ); + Cudd_RecursiveDeref( dd, bSupp ); +} +*/ + pVar = pVars[iVarBest]; + + // this var cannot appear in one partition only + nSupp = Cudd_SupportSize( dd, pVar->bParts ); + assert( nSupp == pVar->nParts ); + assert( nSupp != 1 ); +//printf( "var = %d supp = %d\n\n", iVarBest, nSupp ); + + // if it appears in only two partitions, quantify it + if ( pVar->nParts == 2 ) + { + // get the nodes + iNode1 = pVar->bParts->index; + iNode2 = cuddT(pVar->bParts)->index; + pNode1 = pNodes[iNode1]; + pNode2 = pNodes[iNode2]; + + // get the quantification cube + bCube = dd->vars[pVar->iNum]; Cudd_Ref( bCube ); + // add the variables that appear only in these partitions + for ( v = 0; v < nVars; v++ ) + if ( pVars[v] && v != iVarBest && pVars[v]->bParts == pVars[iVarBest]->bParts ) + { + // add this var + bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[pVars[v]->iNum] ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + // clean this var + Cudd_RecursiveDeref( dd, pVars[v]->bParts ); + ABC_FREE( pVars[v] ); + } + // clean the best var + Cudd_RecursiveDeref( dd, pVars[iVarBest]->bParts ); + ABC_FREE( pVars[iVarBest] ); + + // combines two nodes + pNode = Bbr_CombineTwoNodes( dd, bCube, pNode1, pNode2 ); + Cudd_RecursiveDeref( dd, bCube ); + } + else // if ( pVar->nParts > 2 ) + { + // find two smallest BDDs that have this var + Bbr_FindBestPartitions( dd, pVar->bParts, nNodes, pNodes, &iNode1, &iNode2 ); + pNode1 = pNodes[iNode1]; + pNode2 = pNodes[iNode2]; +//printf( "smallest bdds with this var: %d %d\n", iNode1, iNode2 ); +/* + // it is not possible that a var appears only in these two + // otherwise, it would have a different cost + bParts = Cudd_bddAnd( dd, dd->vars[iNode1], dd->vars[iNode2] ); Cudd_Ref( bParts ); + for ( v = 0; v < nVars; v++ ) + if ( pVars[v] && pVars[v]->bParts == bParts ) + assert( 0 ); + Cudd_RecursiveDeref( dd, bParts ); +*/ + // combines two nodes + pNode = Bbr_CombineTwoNodes( dd, b1, pNode1, pNode2 ); + } + + // clean the old nodes + pNodes[iNode1] = pNode; + pNodes[iNode2] = NULL; +//printf( "Removing node %d (leaving node %d)\n", iNode2, iNode1 ); + + // update the variables that appear in pNode[iNode2] + for ( bSuppTemp = pNode2->pPart->bSupp; bSuppTemp != b1; bSuppTemp = cuddT(bSuppTemp) ) + { + pVar = pVars[bSuppTemp->index]; + if ( pVar == NULL ) // this variable is not be quantified + continue; + // quantify this var + assert( Cudd_bddLeq( dd, pVar->bParts, dd->vars[iNode2] ) ); + pVar->bParts = Cudd_bddExistAbstract( dd, bTemp = pVar->bParts, dd->vars[iNode2] ); Cudd_Ref( pVar->bParts ); + Cudd_RecursiveDeref( dd, bTemp ); + // add the new var + pVar->bParts = Cudd_bddAnd( dd, bTemp = pVar->bParts, dd->vars[iNode1] ); Cudd_Ref( pVar->bParts ); + Cudd_RecursiveDeref( dd, bTemp ); + // update the score + pVar->nParts = Cudd_SupportSize( dd, pVar->bParts ); + } + + *pfStop = 0; + if ( dd->keys-dd->dead > (unsigned)nBddMax ) + { + *pfStop = 1; + return 0; + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Merges the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bbr_ImageNode_t * Bbr_MergeTopNodes( + DdManager * dd, int nNodes, Bbr_ImageNode_t ** pNodes ) +{ + Bbr_ImageNode_t * pNode; + int n1 = -1, n2 = -1, n; + + // find the first and the second non-empty spots + for ( n = 0; n < nNodes; n++ ) + if ( pNodes[n] ) + { + if ( n1 == -1 ) + n1 = n; + else if ( n2 == -1 ) + { + n2 = n; + break; + } + } + assert( n1 != -1 ); + // check the situation when only one such node is detected + if ( n2 == -1 ) + { + // save the node + pNode = pNodes[n1]; + // clean the node + pNodes[n1] = NULL; + return pNode; + } + + // combines two nodes + pNode = Bbr_CombineTwoNodes( dd, b1, pNodes[n1], pNodes[n2] ); + + // clean the old nodes + pNodes[n1] = pNode; + pNodes[n2] = NULL; + return NULL; +} + +/**Function************************************************************* + + Synopsis [Merges two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bbr_ImageNode_t * Bbr_CombineTwoNodes( DdManager * dd, DdNode * bCube, + Bbr_ImageNode_t * pNode1, Bbr_ImageNode_t * pNode2 ) +{ + Bbr_ImageNode_t * pNode; + Bbr_ImagePart_t * pPart; + + // create a new partition + pPart = ABC_ALLOC( Bbr_ImagePart_t, 1 ); + memset( pPart, 0, sizeof(Bbr_ImagePart_t) ); + // create the function + pPart->bFunc = Cudd_bddAndAbstract( dd, pNode1->pPart->bFunc, pNode2->pPart->bFunc, bCube ); + Cudd_Ref( pPart->bFunc ); + // update the support the partition + pPart->bSupp = Cudd_bddAndAbstract( dd, pNode1->pPart->bSupp, pNode2->pPart->bSupp, bCube ); + Cudd_Ref( pPart->bSupp ); + // update the numbers + pPart->nSupp = Cudd_SupportSize( dd, pPart->bSupp ); + pPart->nNodes = Cudd_DagSize( pPart->bFunc ); + pPart->iPart = -1; +/* +ABC_PRB( dd, pNode1->pPart->bSupp ); +ABC_PRB( dd, pNode2->pPart->bSupp ); +ABC_PRB( dd, pPart->bSupp ); +*/ + // create a new node + pNode = ABC_ALLOC( Bbr_ImageNode_t, 1 ); + memset( pNode, 0, sizeof(Bbr_ImageNode_t) ); + pNode->dd = dd; + pNode->pPart = pPart; + pNode->pNode1 = pNode1; + pNode->pNode2 = pNode2; + // compute the image + pNode->bImage = Cudd_bddAndAbstract( dd, pNode1->bImage, pNode2->bImage, bCube ); + Cudd_Ref( pNode->bImage ); + // save the cube + if ( bCube != b1 ) + { + pNode->bCube = bCube; Cudd_Ref( bCube ); + } + return pNode; +} + +/**Function************************************************************* + + Synopsis [Computes the best variable.] + + Description [The variables is the best if the sum of squares of the + BDD sizes of the partitions, in which it participates, is the minimum.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bbr_FindBestVariable( DdManager * dd, + int nNodes, Bbr_ImageNode_t ** pNodes, + int nVars, Bbr_ImageVar_t ** pVars ) +{ + DdNode * bTemp; + int iVarBest, v; + double CostBest, CostCur; + + CostBest = 100000000000000.0; + iVarBest = -1; + + // check if there are two-variable partitions + for ( v = 0; v < nVars; v++ ) + if ( pVars[v] && pVars[v]->nParts == 2 ) + { + CostCur = 0; + for ( bTemp = pVars[v]->bParts; bTemp != b1; bTemp = cuddT(bTemp) ) + CostCur += pNodes[bTemp->index]->pPart->nNodes * + pNodes[bTemp->index]->pPart->nNodes; + if ( CostBest > CostCur ) + { + CostBest = CostCur; + iVarBest = v; + } + } + if ( iVarBest >= 0 ) + return iVarBest; + + // find other partition + for ( v = 0; v < nVars; v++ ) + if ( pVars[v] ) + { + assert( pVars[v]->nParts > 1 ); + CostCur = 0; + for ( bTemp = pVars[v]->bParts; bTemp != b1; bTemp = cuddT(bTemp) ) + CostCur += pNodes[bTemp->index]->pPart->nNodes * + pNodes[bTemp->index]->pPart->nNodes; + if ( CostBest > CostCur ) + { + CostBest = CostCur; + iVarBest = v; + } + } + return iVarBest; +} + +/**Function************************************************************* + + Synopsis [Computes two smallest partions that have this var.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbr_FindBestPartitions( DdManager * dd, DdNode * bParts, + int nNodes, Bbr_ImageNode_t ** pNodes, + int * piNode1, int * piNode2 ) +{ + DdNode * bTemp; + int iPart1, iPart2; + int CostMin1, CostMin2, Cost; + + // go through the partitions + iPart1 = iPart2 = -1; + CostMin1 = CostMin2 = 1000000; + for ( bTemp = bParts; bTemp != b1; bTemp = cuddT(bTemp) ) + { + Cost = pNodes[bTemp->index]->pPart->nNodes; + if ( CostMin1 > Cost ) + { + CostMin2 = CostMin1; iPart2 = iPart1; + CostMin1 = Cost; iPart1 = bTemp->index; + } + else if ( CostMin2 > Cost ) + { + CostMin2 = Cost; iPart2 = bTemp->index; + } + } + + *piNode1 = iPart1; + *piNode2 = iPart2; +} + +/**Function************************************************************* + + Synopsis [Prints the latch dependency matrix.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbr_bddImagePrintLatchDependency( + DdManager * dd, DdNode * bCare, // the care set + int nParts, DdNode ** pbParts, // the partitions for image computation + int nVars, DdNode ** pbVars ) // the NS and parameter variables (not quantified!) +{ + int i; + DdNode * bVarsCs, * bVarsNs; + + bVarsCs = Cudd_Support( dd, bCare ); Cudd_Ref( bVarsCs ); + bVarsNs = Cudd_bddComputeCube( dd, pbVars, NULL, nVars ); Cudd_Ref( bVarsNs ); + + printf( "The latch dependency matrix:\n" ); + printf( "Partitions = %d Variables: total = %d non-quantifiable = %d\n", + nParts, dd->size, nVars ); + printf( " : " ); + for ( i = 0; i < dd->size; i++ ) + printf( "%d", i % 10 ); + printf( "\n" ); + + for ( i = 0; i < nParts; i++ ) + Bbr_bddImagePrintLatchDependencyOne( dd, pbParts[i], bVarsCs, bVarsNs, i ); + Bbr_bddImagePrintLatchDependencyOne( dd, bCare, bVarsCs, bVarsNs, nParts ); + + Cudd_RecursiveDeref( dd, bVarsCs ); + Cudd_RecursiveDeref( dd, bVarsNs ); +} + +/**Function************************************************************* + + Synopsis [Prints one row of the latch dependency matrix.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbr_bddImagePrintLatchDependencyOne( + DdManager * dd, DdNode * bFunc, // the function + DdNode * bVarsCs, DdNode * bVarsNs, // the current/next state vars + int iPart ) +{ + DdNode * bSupport; + int v; + bSupport = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupport ); + printf( " %3d : ", iPart ); + for ( v = 0; v < dd->size; v++ ) + { + if ( Cudd_bddLeq( dd, bSupport, dd->vars[v] ) ) + { + if ( Cudd_bddLeq( dd, bVarsCs, dd->vars[v] ) ) + printf( "c" ); + else if ( Cudd_bddLeq( dd, bVarsNs, dd->vars[v] ) ) + printf( "n" ); + else + printf( "i" ); + } + else + printf( "." ); + } + printf( "\n" ); + Cudd_RecursiveDeref( dd, bSupport ); +} + + +/**Function************************************************************* + + Synopsis [Prints the tree for quenstification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbr_bddImagePrintTree( Bbr_ImageTree_t * pTree ) +{ + printf( "The quantification scheduling tree:\n" ); + Bbr_bddImagePrintTree_rec( pTree->pRoot, 1 ); +} + +/**Function************************************************************* + + Synopsis [Prints the tree for quenstification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbr_bddImagePrintTree_rec( Bbr_ImageNode_t * pNode, int Offset ) +{ + DdNode * Cube; + int i; + + Cube = pNode->bCube; + + if ( pNode->pNode1 == NULL ) + { + printf( "<%d> ", pNode->pPart->iPart ); + if ( Cube != NULL ) + { + ABC_PRB( pNode->dd, Cube ); + } + else + printf( "\n" ); + return; + } + + printf( "<*> " ); + if ( Cube != NULL ) + { + ABC_PRB( pNode->dd, Cube ); + } + else + printf( "\n" ); + + for ( i = 0; i < Offset; i++ ) + printf( " " ); + Bbr_bddImagePrintTree_rec( pNode->pNode1, Offset + 1 ); + + for ( i = 0; i < Offset; i++ ) + printf( " " ); + Bbr_bddImagePrintTree_rec( pNode->pNode2, Offset + 1 ); +} + +/**Function******************************************************************** + + Synopsis [Computes the positive polarty cube composed of the first vars in the array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Bbr_bddComputeCube( DdManager * dd, DdNode ** bXVars, int nVars ) +{ + DdNode * bRes; + DdNode * bTemp; + int i; + + bRes = b1; Cudd_Ref( bRes ); + for ( i = 0; i < nVars; i++ ) + { + bRes = Cudd_bddAnd( dd, bTemp = bRes, bXVars[i] ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + } + + Cudd_Deref( bRes ); + return bRes; +} + + + + + +struct Bbr_ImageTree2_t_ +{ + DdManager * dd; + DdNode * bRel; + DdNode * bCube; + DdNode * bImage; +}; + +/**Function************************************************************* + + Synopsis [Starts the monolithic image computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bbr_ImageTree2_t * Bbr_bddImageStart2( + DdManager * dd, DdNode * bCare, + int nParts, DdNode ** pbParts, + int nVars, DdNode ** pbVars, int fVerbose ) +{ + Bbr_ImageTree2_t * pTree; + DdNode * bCubeAll, * bCubeNot, * bTemp; + int i; + + pTree = ABC_ALLOC( Bbr_ImageTree2_t, 1 ); + pTree->dd = dd; + pTree->bImage = NULL; + + bCubeAll = Bbr_bddComputeCube( dd, dd->vars, dd->size ); Cudd_Ref( bCubeAll ); + bCubeNot = Bbr_bddComputeCube( dd, pbVars, nVars ); Cudd_Ref( bCubeNot ); + pTree->bCube = Cudd_bddExistAbstract( dd, bCubeAll, bCubeNot ); Cudd_Ref( pTree->bCube ); + Cudd_RecursiveDeref( dd, bCubeAll ); + Cudd_RecursiveDeref( dd, bCubeNot ); + + // derive the monolithic relation + pTree->bRel = b1; Cudd_Ref( pTree->bRel ); + for ( i = 0; i < nParts; i++ ) + { + pTree->bRel = Cudd_bddAnd( dd, bTemp = pTree->bRel, pbParts[i] ); Cudd_Ref( pTree->bRel ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Bbr_bddImageCompute2( pTree, bCare ); + return pTree; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Bbr_bddImageCompute2( Bbr_ImageTree2_t * pTree, DdNode * bCare ) +{ + if ( pTree->bImage ) + Cudd_RecursiveDeref( pTree->dd, pTree->bImage ); + pTree->bImage = Cudd_bddAndAbstract( pTree->dd, pTree->bRel, bCare, pTree->bCube ); + Cudd_Ref( pTree->bImage ); + return pTree->bImage; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbr_bddImageTreeDelete2( Bbr_ImageTree2_t * pTree ) +{ + if ( pTree->bRel ) + Cudd_RecursiveDeref( pTree->dd, pTree->bRel ); + if ( pTree->bCube ) + Cudd_RecursiveDeref( pTree->dd, pTree->bCube ); + if ( pTree->bImage ) + Cudd_RecursiveDeref( pTree->dd, pTree->bImage ); + ABC_FREE( pTree ); +} + +/**Function************************************************************* + + Synopsis [Returns the previously computed image.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Bbr_bddImageRead2( Bbr_ImageTree2_t * pTree ) +{ + return pTree->bImage; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/bbr/bbrNtbdd.c b/src/bdd/bbr/bbrNtbdd.c new file mode 100644 index 00000000..f61c3d73 --- /dev/null +++ b/src/bdd/bbr/bbrNtbdd.c @@ -0,0 +1,218 @@ +/**CFile**************************************************************** + + FileName [bbrNtbdd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD-based reachability analysis.] + + Synopsis [Procedures to construct global BDDs for the network.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: bbrNtbdd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "bbr.h" +//#include "bar.h" + +ABC_NAMESPACE_IMPL_START + + +typedef char ProgressBar; + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline void Aig_ObjSetGlobalBdd( Aig_Obj_t * pObj, DdNode * bFunc ) { pObj->pData = bFunc; } +static inline void Aig_ObjCleanGlobalBdd( DdManager * dd, Aig_Obj_t * pObj ) { Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); pObj->pData = NULL; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Derives the global BDD for one AIG node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Bbr_NodeGlobalBdds_rec( DdManager * dd, Aig_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose ) +{ + DdNode * bFunc, * bFunc0, * bFunc1; + assert( !Aig_IsComplement(pNode) ); + if ( Cudd_ReadKeys(dd)-Cudd_ReadDead(dd) > (unsigned)nBddSizeMax ) + { +// Extra_ProgressBarStop( pProgress ); + if ( fVerbose ) + printf( "The number of live nodes reached %d.\n", nBddSizeMax ); + fflush( stdout ); + return NULL; + } + // if the result is available return + if ( Aig_ObjGlobalBdd(pNode) == NULL ) + { + // compute the result for both branches + bFunc0 = Bbr_NodeGlobalBdds_rec( dd, Aig_ObjFanin0(pNode), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); + if ( bFunc0 == NULL ) + return NULL; + Cudd_Ref( bFunc0 ); + bFunc1 = Bbr_NodeGlobalBdds_rec( dd, Aig_ObjFanin1(pNode), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); + if ( bFunc1 == NULL ) + return NULL; + Cudd_Ref( bFunc1 ); + bFunc0 = Cudd_NotCond( bFunc0, Aig_ObjFaninC0(pNode) ); + bFunc1 = Cudd_NotCond( bFunc1, Aig_ObjFaninC1(pNode) ); + // get the final result + bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( dd, bFunc0 ); + Cudd_RecursiveDeref( dd, bFunc1 ); + // add the number of used nodes + (*pCounter)++; + // set the result + assert( Aig_ObjGlobalBdd(pNode) == NULL ); + Aig_ObjSetGlobalBdd( pNode, bFunc ); + // increment the progress bar +// if ( pProgress ) +// Extra_ProgressBarUpdate( pProgress, *pCounter, NULL ); + } + // prepare the return value + bFunc = Aig_ObjGlobalBdd(pNode); + // dereference BDD at the node + if ( --pNode->nRefs == 0 && fDropInternal ) + { + Cudd_Deref( bFunc ); + Aig_ObjSetGlobalBdd( pNode, NULL ); + } + return bFunc; +} + +/**Function************************************************************* + + Synopsis [Frees the global BDDs of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManFreeGlobalBdds( Aig_Man_t * p, DdManager * dd ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachObj( p, pObj, i ) + if ( Aig_ObjGlobalBdd(pObj) ) + Aig_ObjCleanGlobalBdd( dd, pObj ); +} + +/**Function************************************************************* + + Synopsis [Returns the shared size of global BDDs of the COs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManSizeOfGlobalBdds( Aig_Man_t * p ) +{ + Vec_Ptr_t * vFuncsGlob; + Aig_Obj_t * pObj; + int RetValue, i; + // complement the global functions + vFuncsGlob = Vec_PtrAlloc( Aig_ManCoNum(p) ); + Aig_ManForEachCo( p, pObj, i ) + Vec_PtrPush( vFuncsGlob, Aig_ObjGlobalBdd(pObj) ); + RetValue = Cudd_SharingSize( (DdNode **)Vec_PtrArray(vFuncsGlob), Vec_PtrSize(vFuncsGlob) ); + Vec_PtrFree( vFuncsGlob ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Recursively computes global BDDs for the AIG in the manager.] + + Description [On exit, BDDs are stored in the pNode->pData fields.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdManager * Aig_ManComputeGlobalBdds( Aig_Man_t * p, int nBddSizeMax, int fDropInternal, int fReorder, int fVerbose ) +{ + ProgressBar * pProgress = NULL; + Aig_Obj_t * pObj; + DdManager * dd; + DdNode * bFunc; + int i, Counter; + // start the manager + dd = Cudd_Init( Aig_ManCiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + // set reordering + if ( fReorder ) + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + // prepare to construct global BDDs + Aig_ManCleanData( p ); + // assign the constant node BDD + Aig_ObjSetGlobalBdd( Aig_ManConst1(p), dd->one ); Cudd_Ref( dd->one ); + // set the elementary variables + Aig_ManForEachCi( p, pObj, i ) + { + Aig_ObjSetGlobalBdd( pObj, dd->vars[i] ); Cudd_Ref( dd->vars[i] ); + } + + // collect the global functions of the COs + Counter = 0; + // construct the BDDs +// pProgress = Extra_ProgressBarStart( stdout, Aig_ManNodeNum(p) ); + Aig_ManForEachCo( p, pObj, i ) + { + bFunc = Bbr_NodeGlobalBdds_rec( dd, Aig_ObjFanin0(pObj), nBddSizeMax, fDropInternal, pProgress, &Counter, fVerbose ); + if ( bFunc == NULL ) + { + if ( fVerbose ) + printf( "Constructing global BDDs is aborted.\n" ); + Aig_ManFreeGlobalBdds( p, dd ); + Cudd_Quit( dd ); + // reset references + Aig_ManResetRefs( p ); + return NULL; + } + bFunc = Cudd_NotCond( bFunc, Aig_ObjFaninC0(pObj) ); Cudd_Ref( bFunc ); + Aig_ObjSetGlobalBdd( pObj, bFunc ); + } +// Extra_ProgressBarStop( pProgress ); + // reset references + Aig_ManResetRefs( p ); + // reorder one more time + if ( fReorder ) + { + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); + Cudd_AutodynDisable( dd ); + } +// Cudd_PrintInfo( dd, stdout ); + return dd; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/bbr/bbrReach.c b/src/bdd/bbr/bbrReach.c new file mode 100644 index 00000000..b5125ec7 --- /dev/null +++ b/src/bdd/bbr/bbrReach.c @@ -0,0 +1,615 @@ +/**CFile**************************************************************** + + FileName [bbrReach.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD-based reachability analysis.] + + Synopsis [Procedures to perform reachability analysis.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: bbrReach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "bbr.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern Abc_Cex_t * Aig_ManVerifyUsingBddsCountExample( Aig_Man_t * p, DdManager * dd, + DdNode ** pbParts, Vec_Ptr_t * vOnionRings, DdNode * bCubeFirst, + int iOutput, int fVerbose, int fSilent ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [This procedure sets default resynthesis parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbr_ManSetDefaultParams( Saig_ParBbr_t * p ) +{ + memset( p, 0, sizeof(Saig_ParBbr_t) ); + p->TimeLimit = 0; + p->nBddMax = 50000; + p->nIterMax = 1000; + p->fPartition = 1; + p->fReorder = 1; + p->fReorderImage = 1; + p->fVerbose = 0; + p->fSilent = 0; + p->iFrame = -1; +} + +/**Function******************************************************************** + + Synopsis [Performs the reordering-sensitive step of Extra_bddMove().] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Bbr_bddComputeRangeCube( DdManager * dd, int iStart, int iStop ) +{ + DdNode * bTemp, * bProd; + int i; + assert( iStart <= iStop ); + assert( iStart >= 0 && iStart <= dd->size ); + assert( iStop >= 0 && iStop <= dd->size ); + bProd = (dd)->one; Cudd_Ref( bProd ); + for ( i = iStart; i < iStop; i++ ) + { + bProd = Cudd_bddAnd( dd, bTemp = bProd, dd->vars[i] ); Cudd_Ref( bProd ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bProd ); + return bProd; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bbr_StopManager( DdManager * dd ) +{ + int RetValue; + // check for remaining references in the package + RetValue = Cudd_CheckZeroRef( dd ); + if ( RetValue > 0 ) + printf( "\nThe number of referenced nodes = %d\n\n", RetValue ); +// Cudd_PrintInfo( dd, stdout ); + Cudd_Quit( dd ); +} + +/**Function************************************************************* + + Synopsis [Computes the initial state and sets up the variable map.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Aig_ManInitStateVarMap( DdManager * dd, Aig_Man_t * p, int fVerbose ) +{ + DdNode ** pbVarsX, ** pbVarsY; + DdNode * bTemp, * bProd; + Aig_Obj_t * pLatch; + int i; + + // set the variable mapping for Cudd_bddVarMap() + pbVarsX = ABC_ALLOC( DdNode *, dd->size ); + pbVarsY = ABC_ALLOC( DdNode *, dd->size ); + bProd = (dd)->one; Cudd_Ref( bProd ); + Saig_ManForEachLo( p, pLatch, i ) + { + pbVarsX[i] = dd->vars[ Saig_ManPiNum(p) + i ]; + pbVarsY[i] = dd->vars[ Saig_ManCiNum(p) + i ]; + // get the initial value of the latch + bProd = Cudd_bddAnd( dd, bTemp = bProd, Cudd_Not(pbVarsX[i]) ); Cudd_Ref( bProd ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_SetVarMap( dd, pbVarsX, pbVarsY, Saig_ManRegNum(p) ); + ABC_FREE( pbVarsX ); + ABC_FREE( pbVarsY ); + + Cudd_Deref( bProd ); + return bProd; +} + +/**Function************************************************************* + + Synopsis [Collects the array of output BDDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode ** Aig_ManCreateOutputs( DdManager * dd, Aig_Man_t * p ) +{ + DdNode ** pbOutputs; + Aig_Obj_t * pNode; + int i; + // compute the transition relation + pbOutputs = ABC_ALLOC( DdNode *, Saig_ManPoNum(p) ); + Saig_ManForEachPo( p, pNode, i ) + { + pbOutputs[i] = Aig_ObjGlobalBdd(pNode); Cudd_Ref( pbOutputs[i] ); + } + return pbOutputs; +} + +/**Function************************************************************* + + Synopsis [Collects the array of partition BDDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode ** Aig_ManCreatePartitions( DdManager * dd, Aig_Man_t * p, int fReorder, int fVerbose ) +{ + DdNode ** pbParts; + DdNode * bVar; + Aig_Obj_t * pNode; + int i; + + // extand the BDD manager to represent NS variables + assert( dd->size == Saig_ManCiNum(p) ); + Cudd_bddIthVar( dd, Saig_ManCiNum(p) + Saig_ManRegNum(p) - 1 ); + + // enable reordering + if ( fReorder ) + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + else + Cudd_AutodynDisable( dd ); + + // compute the transition relation + pbParts = ABC_ALLOC( DdNode *, Saig_ManRegNum(p) ); + Saig_ManForEachLi( p, pNode, i ) + { + bVar = Cudd_bddIthVar( dd, Saig_ManCiNum(p) + i ); + pbParts[i] = Cudd_bddXnor( dd, bVar, Aig_ObjGlobalBdd(pNode) ); Cudd_Ref( pbParts[i] ); + } + // free global BDDs + Aig_ManFreeGlobalBdds( p, dd ); + + // reorder and disable reordering + if ( fReorder ) + { + if ( fVerbose ) + fprintf( stdout, "BDD nodes in the partitions before reordering %d.\n", Cudd_SharingSize(pbParts,Saig_ManRegNum(p)) ); + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + Cudd_AutodynDisable( dd ); + if ( fVerbose ) + fprintf( stdout, "BDD nodes in the partitions after reordering %d.\n", Cudd_SharingSize(pbParts,Saig_ManRegNum(p)) ); + } + return pbParts; +} + +/**Function************************************************************* + + Synopsis [Computes the set of unreachable states.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManComputeReachable( DdManager * dd, Aig_Man_t * p, DdNode ** pbParts, DdNode * bInitial, DdNode ** pbOutputs, Saig_ParBbr_t * pPars, int fCheckOutputs ) +{ + int fInternalReorder = 0; + Bbr_ImageTree_t * pTree = NULL; // Suppress "might be used uninitialized" + Bbr_ImageTree2_t * pTree2 = NULL; // Supprses "might be used uninitialized" + DdNode * bReached, * bCubeCs; + DdNode * bCurrent; + DdNode * bNext = NULL; // Suppress "might be used uninitialized" + DdNode * bTemp; + Cudd_ReorderingType method; + int i, nIters, nBddSize = 0, status; + int nThreshold = 10000; + abctime clk = Abc_Clock(); + Vec_Ptr_t * vOnionRings; + int fixedPoint = 0; + + status = Cudd_ReorderingStatus( dd, &method ); + if ( status ) + Cudd_AutodynDisable( dd ); + + // start the image computation + bCubeCs = Bbr_bddComputeRangeCube( dd, Saig_ManPiNum(p), Saig_ManCiNum(p) ); Cudd_Ref( bCubeCs ); + if ( pPars->fPartition ) + pTree = Bbr_bddImageStart( dd, bCubeCs, Saig_ManRegNum(p), pbParts, Saig_ManRegNum(p), dd->vars+Saig_ManCiNum(p), pPars->nBddMax, pPars->fVerbose ); + else + pTree2 = Bbr_bddImageStart2( dd, bCubeCs, Saig_ManRegNum(p), pbParts, Saig_ManRegNum(p), dd->vars+Saig_ManCiNum(p), pPars->fVerbose ); + Cudd_RecursiveDeref( dd, bCubeCs ); + if ( pTree == NULL ) + { + if ( !pPars->fSilent ) + printf( "BDDs blew up during qualitification scheduling. " ); + return -1; + } + + if ( status ) + Cudd_AutodynEnable( dd, method ); + + // start the onion rings + vOnionRings = Vec_PtrAlloc( 1000 ); + + // perform reachability analysis + bCurrent = bInitial; Cudd_Ref( bCurrent ); + bReached = bInitial; Cudd_Ref( bReached ); + Vec_PtrPush( vOnionRings, bCurrent ); Cudd_Ref( bCurrent ); + for ( nIters = 0; nIters < pPars->nIterMax; nIters++ ) + { + // check the runtime limit + if ( pPars->TimeLimit && pPars->TimeLimit <= (Abc_Clock()-clk)/CLOCKS_PER_SEC ) + { + printf( "Reached timeout after image computation (%d seconds).\n", pPars->TimeLimit ); + Vec_PtrFree( vOnionRings ); + // undo the image tree + if ( pPars->fPartition ) + Bbr_bddImageTreeDelete( pTree ); + else + Bbr_bddImageTreeDelete2( pTree2 ); + pPars->iFrame = nIters - 1; + return -1; + } + + // compute the next states + if ( pPars->fPartition ) + bNext = Bbr_bddImageCompute( pTree, bCurrent ); + else + bNext = Bbr_bddImageCompute2( pTree2, bCurrent ); + if ( bNext == NULL ) + { + if ( !pPars->fSilent ) + printf( "BDDs blew up during image computation. " ); + if ( pPars->fPartition ) + Bbr_bddImageTreeDelete( pTree ); + else + Bbr_bddImageTreeDelete2( pTree2 ); + Vec_PtrFree( vOnionRings ); + pPars->iFrame = nIters - 1; + return -1; + } + Cudd_Ref( bNext ); + Cudd_RecursiveDeref( dd, bCurrent ); + + // remap these states into the current state vars + bNext = Cudd_bddVarMap( dd, bTemp = bNext ); Cudd_Ref( bNext ); + Cudd_RecursiveDeref( dd, bTemp ); + // check if there are any new states + if ( Cudd_bddLeq( dd, bNext, bReached ) ) { + fixedPoint = 1; + break; + } + // check the BDD size + nBddSize = Cudd_DagSize(bNext); + if ( nBddSize > pPars->nBddMax ) + break; + // check the result + for ( i = 0; i < Saig_ManPoNum(p); i++ ) + { + if ( fCheckOutputs && !Cudd_bddLeq( dd, bNext, Cudd_Not(pbOutputs[i]) ) ) + { + DdNode * bIntersect; + bIntersect = Cudd_bddIntersect( dd, bNext, pbOutputs[i] ); Cudd_Ref( bIntersect ); + assert( p->pSeqModel == NULL ); + p->pSeqModel = Aig_ManVerifyUsingBddsCountExample( p, dd, pbParts, + vOnionRings, bIntersect, i, pPars->fVerbose, pPars->fSilent ); + Cudd_RecursiveDeref( dd, bIntersect ); + if ( !pPars->fSilent ) + Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", i, p->pName, Vec_PtrSize(vOnionRings) ); + Cudd_RecursiveDeref( dd, bReached ); + bReached = NULL; + pPars->iFrame = nIters; + break; + } + } + if ( i < Saig_ManPoNum(p) ) + break; + // get the new states + bCurrent = Cudd_bddAnd( dd, bNext, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); + Vec_PtrPush( vOnionRings, bCurrent ); Cudd_Ref( bCurrent ); + // minimize the new states with the reached states +// bCurrent = Cudd_bddConstrain( dd, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); +// Cudd_RecursiveDeref( dd, bTemp ); + // add to the reached states + bReached = Cudd_bddOr( dd, bTemp = bReached, bNext ); Cudd_Ref( bReached ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bNext ); + if ( pPars->fVerbose ) + fprintf( stdout, "Frame = %3d. BDD = %5d. ", nIters, nBddSize ); + if ( fInternalReorder && pPars->fReorder && nBddSize > nThreshold ) + { + if ( pPars->fVerbose ) + fprintf( stdout, "Reordering... Before = %5d. ", Cudd_DagSize(bReached) ); + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + Cudd_AutodynDisable( dd ); + if ( pPars->fVerbose ) + fprintf( stdout, "After = %5d.\r", Cudd_DagSize(bReached) ); + nThreshold *= 2; + } + if ( pPars->fVerbose ) +// fprintf( stdout, "\r" ); + fprintf( stdout, "\n" ); + + if ( pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(dd, bReached, Saig_ManRegNum(p) ); +// Extra_bddPrint( dd, bReached );printf( "\n" ); + fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p)) ); + fflush( stdout ); + } + + } + Cudd_RecursiveDeref( dd, bNext ); + // free the onion rings + Vec_PtrForEachEntry( DdNode *, vOnionRings, bTemp, i ) + Cudd_RecursiveDeref( dd, bTemp ); + Vec_PtrFree( vOnionRings ); + // undo the image tree + if ( pPars->fPartition ) + Bbr_bddImageTreeDelete( pTree ); + else + Bbr_bddImageTreeDelete2( pTree2 ); + if ( bReached == NULL ) + return 0; // proved reachable + // report the stats + if ( pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(dd, bReached, Saig_ManRegNum(p) ); + if ( nIters > pPars->nIterMax || nBddSize > pPars->nBddMax ) + fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters ); + else + fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters ); + fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p)) ); + fflush( stdout ); + } +//ABC_PRB( dd, bReached ); + Cudd_RecursiveDeref( dd, bReached ); + // SPG + // + if ( fixedPoint ) { + if ( !pPars->fSilent ) { + printf( "The miter is proved unreachable after %d iterations. ", nIters ); + } + pPars->iFrame = nIters - 1; + return 1; + } + assert(nIters >= pPars->nIterMax || nBddSize >= pPars->nBddMax); + if ( !pPars->fSilent ) + printf( "Verified only for states reachable in %d frames. ", nIters ); + pPars->iFrame = nIters - 1; + return -1; // undecided +} + +/**Function************************************************************* + + Synopsis [Performs reachability to see if any PO can be asserted.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManVerifyUsingBdds_int( Aig_Man_t * p, Saig_ParBbr_t * pPars ) +{ + int fCheckOutputs = !pPars->fSkipOutCheck; + DdManager * dd; + DdNode ** pbParts, ** pbOutputs; + DdNode * bInitial, * bTemp; + int RetValue, i; + abctime clk = Abc_Clock(); + Vec_Ptr_t * vOnionRings; + + assert( Saig_ManRegNum(p) > 0 ); + + // compute the global BDDs of the latches + dd = Aig_ManComputeGlobalBdds( p, pPars->nBddMax, 1, pPars->fReorder, pPars->fVerbose ); + if ( dd == NULL ) + { + if ( !pPars->fSilent ) + printf( "The number of intermediate BDD nodes exceeded the limit (%d).\n", pPars->nBddMax ); + return -1; + } + if ( pPars->fVerbose ) + printf( "Shared BDD size is %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + + // check the runtime limit + if ( pPars->TimeLimit && pPars->TimeLimit <= (Abc_Clock()-clk)/CLOCKS_PER_SEC ) + { + printf( "Reached timeout after constructing global BDDs (%d seconds).\n", pPars->TimeLimit ); + Cudd_Quit( dd ); + return -1; + } + + // start the onion rings + vOnionRings = Vec_PtrAlloc( 1000 ); + + // save outputs + pbOutputs = Aig_ManCreateOutputs( dd, p ); + + // create partitions + pbParts = Aig_ManCreatePartitions( dd, p, pPars->fReorder, pPars->fVerbose ); + + // create the initial state and the variable map + bInitial = Aig_ManInitStateVarMap( dd, p, pPars->fVerbose ); Cudd_Ref( bInitial ); + + // set reordering + if ( pPars->fReorderImage ) + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + + // check the result + RetValue = -1; + for ( i = 0; i < Saig_ManPoNum(p); i++ ) + { + if ( fCheckOutputs && !Cudd_bddLeq( dd, bInitial, Cudd_Not(pbOutputs[i]) ) ) + { + DdNode * bIntersect; + bIntersect = Cudd_bddIntersect( dd, bInitial, pbOutputs[i] ); Cudd_Ref( bIntersect ); + assert( p->pSeqModel == NULL ); + p->pSeqModel = Aig_ManVerifyUsingBddsCountExample( p, dd, pbParts, + vOnionRings, bIntersect, i, pPars->fVerbose, pPars->fSilent ); + Cudd_RecursiveDeref( dd, bIntersect ); + if ( !pPars->fSilent ) + Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", i, p->pName, -1 ); + RetValue = 0; + break; + } + } + // free the onion rings + Vec_PtrForEachEntry( DdNode *, vOnionRings, bTemp, i ) + Cudd_RecursiveDeref( dd, bTemp ); + Vec_PtrFree( vOnionRings ); + // explore reachable states + if ( RetValue == -1 ) + RetValue = Aig_ManComputeReachable( dd, p, pbParts, bInitial, pbOutputs, pPars, fCheckOutputs ); + + // cleanup + Cudd_RecursiveDeref( dd, bInitial ); + for ( i = 0; i < Saig_ManRegNum(p); i++ ) + Cudd_RecursiveDeref( dd, pbParts[i] ); + ABC_FREE( pbParts ); + for ( i = 0; i < Saig_ManPoNum(p); i++ ) + Cudd_RecursiveDeref( dd, pbOutputs[i] ); + ABC_FREE( pbOutputs ); +// if ( RetValue == -1 ) + Cudd_Quit( dd ); +// else +// Bbr_StopManager( dd ); + + // report the runtime + if ( !pPars->fSilent ) + { + ABC_PRT( "Time", Abc_Clock() - clk ); + fflush( stdout ); + } + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Performs reachability to see if any PO can be asserted.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManVerifyUsingBdds( Aig_Man_t * pInit, Saig_ParBbr_t * pPars ) +{ + Abc_Cex_t * pCexOld, * pCexNew; + Aig_Man_t * p; + Aig_Obj_t * pObj; + Vec_Int_t * vInputMap; + int i, k, Entry, iBitOld, iBitNew, RetValue; +// pPars->fVerbose = 1; + // check if there are PIs without fanout + Saig_ManForEachPi( pInit, pObj, i ) + if ( Aig_ObjRefs(pObj) == 0 ) + break; + if ( i == Saig_ManPiNum(pInit) ) + return Aig_ManVerifyUsingBdds_int( pInit, pPars ); + // create new AIG + p = Aig_ManDupTrim( pInit ); + assert( Aig_ManCiNum(p) < Aig_ManCiNum(pInit) ); + assert( Aig_ManRegNum(p) == Aig_ManRegNum(pInit) ); + RetValue = Aig_ManVerifyUsingBdds_int( p, pPars ); + if ( RetValue != 0 ) + { + Aig_ManStop( p ); + return RetValue; + } + // the problem is satisfiable - remap the pattern + pCexOld = p->pSeqModel; + assert( pCexOld != NULL ); + // create input map + vInputMap = Vec_IntAlloc( Saig_ManPiNum(pInit) ); + Saig_ManForEachPi( pInit, pObj, i ) + if ( pObj->pData != NULL ) + Vec_IntPush( vInputMap, Aig_ObjCioId((Aig_Obj_t *)pObj->pData) ); + else + Vec_IntPush( vInputMap, -1 ); + // create new pattern + pCexNew = Abc_CexAlloc( Saig_ManRegNum(pInit), Saig_ManPiNum(pInit), pCexOld->iFrame+1 ); + pCexNew->iFrame = pCexOld->iFrame; + pCexNew->iPo = pCexOld->iPo; + // copy the bit-data + for ( iBitOld = 0; iBitOld < pCexOld->nRegs; iBitOld++ ) + if ( Abc_InfoHasBit( pCexOld->pData, iBitOld ) ) + Abc_InfoSetBit( pCexNew->pData, iBitOld ); + // copy the primary input data + iBitNew = iBitOld; + for ( i = 0; i <= pCexNew->iFrame; i++ ) + { + Vec_IntForEachEntry( vInputMap, Entry, k ) + { + if ( Entry == -1 ) + continue; + if ( Abc_InfoHasBit( pCexOld->pData, iBitOld + Entry ) ) + Abc_InfoSetBit( pCexNew->pData, iBitNew + k ); + } + iBitOld += Saig_ManPiNum(p); + iBitNew += Saig_ManPiNum(pInit); + } + assert( iBitOld < iBitNew ); + assert( iBitOld == pCexOld->nBits ); + assert( iBitNew == pCexNew->nBits ); + Vec_IntFree( vInputMap ); + pInit->pSeqModel = pCexNew; + Aig_ManStop( p ); + return 0; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/bbr/bbr_.c b/src/bdd/bbr/bbr_.c new file mode 100644 index 00000000..df934f7d --- /dev/null +++ b/src/bdd/bbr/bbr_.c @@ -0,0 +1,52 @@ +/**CFile**************************************************************** + + FileName [.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: .c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "__Int.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/bbr/module.make b/src/bdd/bbr/module.make new file mode 100644 index 00000000..4bb1a292 --- /dev/null +++ b/src/bdd/bbr/module.make @@ -0,0 +1,4 @@ +SRC += src/bdd/bbr/bbrCex.c \ + src/bdd/bbr/bbrImage.c \ + src/bdd/bbr/bbrNtbdd.c \ + src/bdd/bbr/bbrReach.c diff --git a/src/bdd/extrab/extraBdd.h b/src/bdd/extrab/extraBdd.h new file mode 100644 index 00000000..3dbc6264 --- /dev/null +++ b/src/bdd/extrab/extraBdd.h @@ -0,0 +1,317 @@ +/**CFile**************************************************************** + + FileName [extraBdd.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [extra] + + Synopsis [Various reusable software utilities.] + + Description [This library contains a number of operators and + traversal routines developed to extend the functionality of + CUDD v.2.3.x, by Fabio Somenzi (http://vlsi.colorado.edu/~fabio/) + To compile your code with the library, #include "extra.h" + in your source files and link your project to CUDD and this + library. Use the library at your own risk and with caution. + Note that debugging of some operators still continues.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: extraBdd.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__misc__extra__extra_bdd_h +#define ABC__misc__extra__extra_bdd_h + + +#ifdef _WIN32 +#define inline __inline // compatible with MS VS 6.0 +#endif + +/*---------------------------------------------------------------------------*/ +/* Nested includes */ +/*---------------------------------------------------------------------------*/ + +#include +#include +#include +#include + +#include "misc/st/st.h" +#include "bdd/cudd/cuddInt.h" +#include "misc/extra/extra.h" + + +ABC_NAMESPACE_HEADER_START + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/* constants of the manager */ +#define b0 Cudd_Not((dd)->one) +#define b1 (dd)->one +#define z0 (dd)->zero +#define z1 (dd)->one +#define a0 (dd)->zero +#define a1 (dd)->one + +// hash key macros +#define hashKey1(a,TSIZE) \ +((ABC_PTRUINT_T)(a) % TSIZE) + +#define hashKey2(a,b,TSIZE) \ +(((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b) * DD_P1) % TSIZE) + +#define hashKey3(a,b,c,TSIZE) \ +(((((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b)) * DD_P1 + (ABC_PTRUINT_T)(c)) * DD_P2 ) % TSIZE) + +#define hashKey4(a,b,c,d,TSIZE) \ +((((((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b)) * DD_P1 + (ABC_PTRUINT_T)(c)) * DD_P2 + \ + (ABC_PTRUINT_T)(d)) * DD_P3) % TSIZE) + +#define hashKey5(a,b,c,d,e,TSIZE) \ +(((((((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b)) * DD_P1 + (ABC_PTRUINT_T)(c)) * DD_P2 + \ + (ABC_PTRUINT_T)(d)) * DD_P3 + (ABC_PTRUINT_T)(e)) * DD_P1) % TSIZE) + +/*===========================================================================*/ +/* Various Utilities */ +/*===========================================================================*/ + +/*=== extraBddAuto.c ========================================================*/ + +extern DdNode * Extra_bddSpaceFromFunctionFast( DdManager * dd, DdNode * bFunc ); +extern DdNode * Extra_bddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG ); +extern DdNode * extraBddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG ); +extern DdNode * Extra_bddSpaceFromFunctionPos( DdManager * dd, DdNode * bFunc ); +extern DdNode * extraBddSpaceFromFunctionPos( DdManager * dd, DdNode * bFunc ); +extern DdNode * Extra_bddSpaceFromFunctionNeg( DdManager * dd, DdNode * bFunc ); +extern DdNode * extraBddSpaceFromFunctionNeg( DdManager * dd, DdNode * bFunc ); + +extern DdNode * Extra_bddSpaceCanonVars( DdManager * dd, DdNode * bSpace ); +extern DdNode * extraBddSpaceCanonVars( DdManager * dd, DdNode * bSpace ); + +extern DdNode * Extra_bddSpaceEquations( DdManager * dd, DdNode * bSpace ); +extern DdNode * Extra_bddSpaceEquationsNeg( DdManager * dd, DdNode * bSpace ); +extern DdNode * extraBddSpaceEquationsNeg( DdManager * dd, DdNode * bSpace ); +extern DdNode * Extra_bddSpaceEquationsPos( DdManager * dd, DdNode * bSpace ); +extern DdNode * extraBddSpaceEquationsPos( DdManager * dd, DdNode * bSpace ); + +extern DdNode * Extra_bddSpaceFromMatrixPos( DdManager * dd, DdNode * zA ); +extern DdNode * extraBddSpaceFromMatrixPos( DdManager * dd, DdNode * zA ); +extern DdNode * Extra_bddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA ); +extern DdNode * extraBddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA ); + +extern DdNode * Extra_bddSpaceReduce( DdManager * dd, DdNode * bFunc, DdNode * bCanonVars ); +extern DdNode ** Extra_bddSpaceExorGates( DdManager * dd, DdNode * bFuncRed, DdNode * zEquations ); + +/*=== extraBddCas.c =============================================================*/ + +/* performs the binary encoding of the set of function using the given vars */ +extern DdNode * Extra_bddEncodingBinary( DdManager * dd, DdNode ** pbFuncs, int nFuncs, DdNode ** pbVars, int nVars ); +/* solves the column encoding problem using a sophisticated method */ +extern DdNode * Extra_bddEncodingNonStrict( DdManager * dd, DdNode ** pbColumns, int nColumns, DdNode * bVarsCol, DdNode ** pCVars, int nMulti, int * pSimple ); +/* collects the nodes under the cut and, for each node, computes the sum of paths leading to it from the root */ +extern st__table * Extra_bddNodePathsUnderCut( DdManager * dd, DdNode * bFunc, int CutLevel ); +/* collects the nodes under the cut starting from the given set of ADD nodes */ +extern int Extra_bddNodePathsUnderCutArray( DdManager * dd, DdNode ** paNodes, DdNode ** pbCubes, int nNodes, DdNode ** paNodesRes, DdNode ** pbCubesRes, int CutLevel ); +/* find the profile of a DD (the number of edges crossing each level) */ +extern int Extra_ProfileWidth( DdManager * dd, DdNode * F, int * Profile, int CutLevel ); + +/*=== extraBddImage.c ================================================================*/ + +typedef struct Extra_ImageTree_t_ Extra_ImageTree_t; +extern Extra_ImageTree_t * Extra_bddImageStart( + DdManager * dd, DdNode * bCare, + int nParts, DdNode ** pbParts, + int nVars, DdNode ** pbVars, int fVerbose ); +extern DdNode * Extra_bddImageCompute( Extra_ImageTree_t * pTree, DdNode * bCare ); +extern void Extra_bddImageTreeDelete( Extra_ImageTree_t * pTree ); +extern DdNode * Extra_bddImageRead( Extra_ImageTree_t * pTree ); + +typedef struct Extra_ImageTree2_t_ Extra_ImageTree2_t; +extern Extra_ImageTree2_t * Extra_bddImageStart2( + DdManager * dd, DdNode * bCare, + int nParts, DdNode ** pbParts, + int nVars, DdNode ** pbVars, int fVerbose ); +extern DdNode * Extra_bddImageCompute2( Extra_ImageTree2_t * pTree, DdNode * bCare ); +extern void Extra_bddImageTreeDelete2( Extra_ImageTree2_t * pTree ); +extern DdNode * Extra_bddImageRead2( Extra_ImageTree2_t * pTree ); + +/*=== extraBddMisc.c ========================================================*/ + +extern DdNode * Extra_TransferPermute( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute ); +extern DdNode * Extra_TransferLevelByLevel( DdManager * ddSource, DdManager * ddDestination, DdNode * f ); +extern DdNode * Extra_bddRemapUp( DdManager * dd, DdNode * bF ); +extern DdNode * Extra_bddMove( DdManager * dd, DdNode * bF, int nVars ); +extern DdNode * extraBddMove( DdManager * dd, DdNode * bF, DdNode * bFlag ); +extern void Extra_StopManager( DdManager * dd ); +extern void Extra_bddPrint( DdManager * dd, DdNode * F ); +extern void Extra_bddPrintSupport( DdManager * dd, DdNode * F ); +extern void extraDecomposeCover( DdManager* dd, DdNode* zC, DdNode** zC0, DdNode** zC1, DdNode** zC2 ); +extern int Extra_bddSuppSize( DdManager * dd, DdNode * bSupp ); +extern int Extra_bddSuppContainVar( DdManager * dd, DdNode * bS, DdNode * bVar ); +extern int Extra_bddSuppOverlapping( DdManager * dd, DdNode * S1, DdNode * S2 ); +extern int Extra_bddSuppDifferentVars( DdManager * dd, DdNode * S1, DdNode * S2, int DiffMax ); +extern int Extra_bddSuppCheckContainment( DdManager * dd, DdNode * bL, DdNode * bH, DdNode ** bLarge, DdNode ** bSmall ); +extern int * Extra_SupportArray( DdManager * dd, DdNode * F, int * support ); +extern int * Extra_VectorSupportArray( DdManager * dd, DdNode ** F, int n, int * support ); +extern DdNode * Extra_bddFindOneCube( DdManager * dd, DdNode * bF ); +extern DdNode * Extra_bddGetOneCube( DdManager * dd, DdNode * bFunc ); +extern DdNode * Extra_bddComputeRangeCube( DdManager * dd, int iStart, int iStop ); +extern DdNode * Extra_bddBitsToCube( DdManager * dd, int Code, int CodeWidth, DdNode ** pbVars, int fMsbFirst ); +extern DdNode * Extra_bddSupportNegativeCube( DdManager * dd, DdNode * f ); +extern int Extra_bddIsVar( DdNode * bFunc ); +extern DdNode * Extra_bddCreateAnd( DdManager * dd, int nVars ); +extern DdNode * Extra_bddCreateOr( DdManager * dd, int nVars ); +extern DdNode * Extra_bddCreateExor( DdManager * dd, int nVars ); +extern DdNode * Extra_zddPrimes( DdManager * dd, DdNode * F ); +extern void Extra_bddPermuteArray( DdManager * dd, DdNode ** bNodesIn, DdNode ** bNodesOut, int nNodes, int *permut ); +extern DdNode * Extra_bddComputeCube( DdManager * dd, DdNode ** bXVars, int nVars ); +extern DdNode * Extra_bddChangePolarity( DdManager * dd, DdNode * bFunc, DdNode * bVars ); +extern DdNode * extraBddChangePolarity( DdManager * dd, DdNode * bFunc, DdNode * bVars ); +extern int Extra_bddVarIsInCube( DdNode * bCube, int iVar ); +extern DdNode * Extra_bddAndPermute( DdManager * ddF, DdNode * bF, DdManager * ddG, DdNode * bG, int * pPermute ); +extern int Extra_bddCountCubes( DdManager * dd, DdNode ** pFuncs, int nFuncs, int fMode, int nLimit, int * pGuide ); +extern void Extra_zddDumpPla( DdManager * dd, DdNode * zCover, int nVars, char * pFileName ); + +#ifndef ABC_PRB +#define ABC_PRB(dd,f) printf("%s = ", #f); Extra_bddPrint(dd,f); printf("\n") +#endif + +/*=== extraBddKmap.c ================================================================*/ + +/* displays the Karnaugh Map of a function */ +extern void Extra_PrintKMap( FILE * pFile, DdManager * dd, DdNode * OnSet, DdNode * OffSet, int nVars, DdNode ** XVars, int fSuppType, char ** pVarNames ); +/* displays the Karnaugh Map of a relation */ +extern void Extra_PrintKMapRelation( FILE * pFile, DdManager * dd, DdNode * OnSet, DdNode * OffSet, int nXVars, int nYVars, DdNode ** XVars, DdNode ** YVars ); + +/*=== extraBddSymm.c =================================================================*/ + +typedef struct Extra_SymmInfo_t_ Extra_SymmInfo_t; +struct Extra_SymmInfo_t_ { + int nVars; // the number of variables in the support + int nVarsMax; // the number of variables in the DD manager + int nSymms; // the number of pair-wise symmetries + int nNodes; // the number of nodes in a ZDD (if applicable) + int * pVars; // the list of all variables present in the support + char ** pSymms; // the symmetry information +}; + +/* computes the classical symmetry information for the function - recursive */ +extern Extra_SymmInfo_t * Extra_SymmPairsCompute( DdManager * dd, DdNode * bFunc ); +/* computes the classical symmetry information for the function - using naive approach */ +extern Extra_SymmInfo_t * Extra_SymmPairsComputeNaive( DdManager * dd, DdNode * bFunc ); +extern int Extra_bddCheckVarsSymmetricNaive( DdManager * dd, DdNode * bF, int iVar1, int iVar2 ); + +/* allocates the data structure */ +extern Extra_SymmInfo_t * Extra_SymmPairsAllocate( int nVars ); +/* deallocates the data structure */ +extern void Extra_SymmPairsDissolve( Extra_SymmInfo_t * ); +/* print the contents the data structure */ +extern void Extra_SymmPairsPrint( Extra_SymmInfo_t * ); +/* converts the ZDD into the Extra_SymmInfo_t structure */ +extern Extra_SymmInfo_t * Extra_SymmPairsCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bVars ); + +/* computes the classical symmetry information as a ZDD */ +extern DdNode * Extra_zddSymmPairsCompute( DdManager * dd, DdNode * bF, DdNode * bVars ); +extern DdNode * extraZddSymmPairsCompute( DdManager * dd, DdNode * bF, DdNode * bVars ); +/* returns a singleton-set ZDD containing all variables that are symmetric with the given one */ +extern DdNode * Extra_zddGetSymmetricVars( DdManager * dd, DdNode * bF, DdNode * bG, DdNode * bVars ); +extern DdNode * extraZddGetSymmetricVars( DdManager * dd, DdNode * bF, DdNode * bG, DdNode * bVars ); +/* converts a set of variables into a set of singleton subsets */ +extern DdNode * Extra_zddGetSingletons( DdManager * dd, DdNode * bVars ); +extern DdNode * extraZddGetSingletons( DdManager * dd, DdNode * bVars ); +/* filters the set of variables using the support of the function */ +extern DdNode * Extra_bddReduceVarSet( DdManager * dd, DdNode * bVars, DdNode * bF ); +extern DdNode * extraBddReduceVarSet( DdManager * dd, DdNode * bVars, DdNode * bF ); + +/* checks the possibility that the two vars are symmetric */ +extern int Extra_bddCheckVarsSymmetric( DdManager * dd, DdNode * bF, int iVar1, int iVar2 ); +extern DdNode * extraBddCheckVarsSymmetric( DdManager * dd, DdNode * bF, DdNode * bVars ); + +/* build the set of all tuples of K variables out of N from the BDD cube */ +extern DdNode * Extra_zddTuplesFromBdd( DdManager * dd, int K, DdNode * bVarsN ); +extern DdNode * extraZddTuplesFromBdd( DdManager * dd, DdNode * bVarsK, DdNode * bVarsN ); +/* selects one subset from a ZDD representing the set of subsets */ +extern DdNode * Extra_zddSelectOneSubset( DdManager * dd, DdNode * zS ); +extern DdNode * extraZddSelectOneSubset( DdManager * dd, DdNode * zS ); + +/*=== extraBddUnate.c =================================================================*/ + +extern DdNode * Extra_bddAndTime( DdManager * dd, DdNode * f, DdNode * g, int TimeOut ); +extern DdNode * Extra_bddAndAbstractTime( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube, int TimeOut ); +extern DdNode * Extra_TransferPermuteTime( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute, int TimeOut ); + +/*=== extraBddUnate.c =================================================================*/ + +typedef struct Extra_UnateVar_t_ Extra_UnateVar_t; +struct Extra_UnateVar_t_ { + unsigned iVar : 30; // index of the variable + unsigned Pos : 1; // 1 if positive unate + unsigned Neg : 1; // 1 if negative unate +}; + +typedef struct Extra_UnateInfo_t_ Extra_UnateInfo_t; +struct Extra_UnateInfo_t_ { + int nVars; // the number of variables in the support + int nVarsMax; // the number of variables in the DD manager + int nUnate; // the number of unate variables + Extra_UnateVar_t * pVars; // the array of variables present in the support +}; + +/* allocates the data structure */ +extern Extra_UnateInfo_t * Extra_UnateInfoAllocate( int nVars ); +/* deallocates the data structure */ +extern void Extra_UnateInfoDissolve( Extra_UnateInfo_t * ); +/* print the contents the data structure */ +extern void Extra_UnateInfoPrint( Extra_UnateInfo_t * ); +/* converts the ZDD into the Extra_SymmInfo_t structure */ +extern Extra_UnateInfo_t * Extra_UnateInfoCreateFromZdd( DdManager * dd, DdNode * zUnate, DdNode * bVars ); +/* naive check of unateness of one variable */ +extern int Extra_bddCheckUnateNaive( DdManager * dd, DdNode * bF, int iVar ); + +/* computes the unateness information for the function */ +extern Extra_UnateInfo_t * Extra_UnateComputeFast( DdManager * dd, DdNode * bFunc ); +extern Extra_UnateInfo_t * Extra_UnateComputeSlow( DdManager * dd, DdNode * bFunc ); + +/* computes the classical symmetry information as a ZDD */ +extern DdNode * Extra_zddUnateInfoCompute( DdManager * dd, DdNode * bF, DdNode * bVars ); +extern DdNode * extraZddUnateInfoCompute( DdManager * dd, DdNode * bF, DdNode * bVars ); + +/* converts a set of variables into a set of singleton subsets */ +extern DdNode * Extra_zddGetSingletonsBoth( DdManager * dd, DdNode * bVars ); +extern DdNode * extraZddGetSingletonsBoth( DdManager * dd, DdNode * bVars ); + +/**AutomaticEnd***************************************************************/ + + + +ABC_NAMESPACE_HEADER_END + + + +#endif /* __EXTRA_H__ */ diff --git a/src/bdd/extrab/extraBddAuto.c b/src/bdd/extrab/extraBddAuto.c new file mode 100644 index 00000000..5fb38aec --- /dev/null +++ b/src/bdd/extrab/extraBddAuto.c @@ -0,0 +1,1563 @@ +/**CFile**************************************************************** + + FileName [extraBddAuto.c] + + PackageName [extra] + + Synopsis [Computation of autosymmetries.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - September 1, 2003.] + + Revision [$Id: extraBddAuto.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $] + +***********************************************************************/ + +#include "extraBdd.h" + +ABC_NAMESPACE_IMPL_START + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticEnd***************************************************************/ + + +/* + LinearSpace(f) = Space(f,f) + + Space(f,g) + { + if ( f = const ) + { + if ( f = g ) return 1; + else return 0; + } + if ( g = const ) return 0; + return x' * Space(fx',gx') * Space(fx,gx) + x * Space(fx',gx) * Space(fx,gx'); + } + + Equations(s) = Pos(s) + Neg(s); + + Pos(s) + { + if ( s = 0 ) return 1; + if ( s = 1 ) return 0; + if ( sx'= 0 ) return Pos(sx) + x; + if ( sx = 0 ) return Pos(sx'); + return 1 * [Pos(sx') & Pos(sx)] + x * [Pos(sx') & Neg(sx)]; + } + + Neg(s) + { + if ( s = 0 ) return 1; + if ( s = 1 ) return 0; + if ( sx'= 0 ) return Neg(sx); + if ( sx = 0 ) return Neg(sx') + x; + return 1 * [Neg(sx') & Neg(sx)] + x * [Neg(sx') & Pos(sx)]; + } + + + SpaceP(A) + { + if ( A = 0 ) return 1; + if ( A = 1 ) return 1; + return x' * SpaceP(Ax') * SpaceP(Ax) + x * SpaceP(Ax') * SpaceN(Ax); + } + + SpaceN(A) + { + if ( A = 0 ) return 1; + if ( A = 1 ) return 0; + return x' * SpaceN(Ax') * SpaceN(Ax) + x * SpaceN(Ax') * SpaceP(Ax); + } + + + LinInd(A) + { + if ( A = const ) return 1; + if ( !LinInd(Ax') ) return 0; + if ( !LinInd(Ax) ) return 0; + if ( LinSumOdd(Ax') & LinSumEven(Ax) != 0 ) return 0; + if ( LinSumEven(Ax') & LinSumEven(Ax) != 0 ) return 0; + return 1; + } + + LinSumOdd(A) + { + if ( A = 0 ) return 0; // Odd0 ---e-- Odd1 + if ( A = 1 ) return 1; // \ o + Odd0 = LinSumOdd(Ax'); // x is absent // \ + Even0 = LinSumEven(Ax'); // x is absent // / o + Odd1 = LinSumOdd(Ax); // x is present // Even0 ---e-- Even1 + Even1 = LinSumEven(Ax); // x is absent + return 1 * [Odd0 + ExorP(Odd0, Even1)] + x * [Odd1 + ExorP(Odd1, Even0)]; + } + + LinSumEven(A) + { + if ( A = 0 ) return 0; + if ( A = 1 ) return 0; + Odd0 = LinSumOdd(Ax'); // x is absent + Even0 = LinSumEven(Ax'); // x is absent + Odd1 = LinSumOdd(Ax); // x is present + Even1 = LinSumEven(Ax); // x is absent + return 1 * [Even0 + Even1 + ExorP(Even0, Even1)] + x * [ExorP(Odd0, Odd1)]; + } + +*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddSpaceFromFunctionFast( DdManager * dd, DdNode * bFunc ) +{ + int * pSupport; + int * pPermute; + int * pPermuteBack; + DdNode ** pCompose; + DdNode * bCube, * bTemp; + DdNode * bSpace, * bFunc1, * bFunc2, * bSpaceShift; + int nSupp, Counter; + int i, lev; + + // get the support + pSupport = ABC_ALLOC( int, ddMax(dd->size,dd->sizeZ) ); + Extra_SupportArray( dd, bFunc, pSupport ); + nSupp = 0; + for ( i = 0; i < dd->size; i++ ) + if ( pSupport[i] ) + nSupp++; + + // make sure the manager has enough variables + if ( 2*nSupp > dd->size ) + { + printf( "Cannot derive linear space, because DD manager does not have enough variables.\n" ); + fflush( stdout ); + ABC_FREE( pSupport ); + return NULL; + } + + // create the permutation arrays + pPermute = ABC_ALLOC( int, dd->size ); + pPermuteBack = ABC_ALLOC( int, dd->size ); + pCompose = ABC_ALLOC( DdNode *, dd->size ); + for ( i = 0; i < dd->size; i++ ) + { + pPermute[i] = i; + pPermuteBack[i] = i; + pCompose[i] = dd->vars[i]; Cudd_Ref( pCompose[i] ); + } + + // remap the function in such a way that the variables are interleaved + Counter = 0; + bCube = b1; Cudd_Ref( bCube ); + for ( lev = 0; lev < dd->size; lev++ ) + if ( pSupport[ dd->invperm[lev] ] ) + { // var "dd->invperm[lev]" on level "lev" should go to level 2*Counter; + pPermute[ dd->invperm[lev] ] = dd->invperm[2*Counter]; + // var from level 2*Counter+1 should go back to the place of this var + pPermuteBack[ dd->invperm[2*Counter+1] ] = dd->invperm[lev]; + // the permutation should be defined in such a way that variable + // on level 2*Counter is replaced by an EXOR of itself and var on the next level + Cudd_Deref( pCompose[ dd->invperm[2*Counter] ] ); + pCompose[ dd->invperm[2*Counter] ] = + Cudd_bddXor( dd, dd->vars[ dd->invperm[2*Counter] ], dd->vars[ dd->invperm[2*Counter+1] ] ); + Cudd_Ref( pCompose[ dd->invperm[2*Counter] ] ); + // add this variable to the cube + bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[ dd->invperm[2*Counter] ] ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + // increment the counter + Counter ++; + } + + // permute the functions + bFunc1 = Cudd_bddPermute( dd, bFunc, pPermute ); Cudd_Ref( bFunc1 ); + // compose to gate the function depending on both vars + bFunc2 = Cudd_bddVectorCompose( dd, bFunc1, pCompose ); Cudd_Ref( bFunc2 ); + // gate the vector space + // L(a) = ForAll x [ F(x) = F(x+a) ] = Not( Exist x [ F(x) (+) F(x+a) ] ) + bSpaceShift = Cudd_bddXorExistAbstract( dd, bFunc1, bFunc2, bCube ); Cudd_Ref( bSpaceShift ); + bSpaceShift = Cudd_Not( bSpaceShift ); + // permute the space back into the original mapping + bSpace = Cudd_bddPermute( dd, bSpaceShift, pPermuteBack ); Cudd_Ref( bSpace ); + Cudd_RecursiveDeref( dd, bFunc1 ); + Cudd_RecursiveDeref( dd, bFunc2 ); + Cudd_RecursiveDeref( dd, bSpaceShift ); + Cudd_RecursiveDeref( dd, bCube ); + + for ( i = 0; i < dd->size; i++ ) + Cudd_RecursiveDeref( dd, pCompose[i] ); + ABC_FREE( pPermute ); + ABC_FREE( pPermuteBack ); + ABC_FREE( pCompose ); + ABC_FREE( pSupport ); + + Cudd_Deref( bSpace ); + return bSpace; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG ) +{ + DdNode * bRes; + do { + dd->reordered = 0; + bRes = extraBddSpaceFromFunction( dd, bF, bG ); + } while (dd->reordered == 1); + return bRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddSpaceFromFunctionPos( DdManager * dd, DdNode * bFunc ) +{ + DdNode * bRes; + do { + dd->reordered = 0; + bRes = extraBddSpaceFromFunctionPos( dd, bFunc ); + } while (dd->reordered == 1); + return bRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddSpaceFromFunctionNeg( DdManager * dd, DdNode * bFunc ) +{ + DdNode * bRes; + do { + dd->reordered = 0; + bRes = extraBddSpaceFromFunctionNeg( dd, bFunc ); + } while (dd->reordered == 1); + return bRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddSpaceCanonVars( DdManager * dd, DdNode * bSpace ) +{ + DdNode * bRes; + do { + dd->reordered = 0; + bRes = extraBddSpaceCanonVars( dd, bSpace ); + } while (dd->reordered == 1); + return bRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddSpaceReduce( DdManager * dd, DdNode * bFunc, DdNode * bCanonVars ) +{ + DdNode * bNegCube; + DdNode * bResult; + bNegCube = Extra_bddSupportNegativeCube( dd, bCanonVars ); Cudd_Ref( bNegCube ); + bResult = Cudd_Cofactor( dd, bFunc, bNegCube ); Cudd_Ref( bResult ); + Cudd_RecursiveDeref( dd, bNegCube ); + Cudd_Deref( bResult ); + return bResult; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddSpaceEquations( DdManager * dd, DdNode * bSpace ) +{ + DdNode * zRes; + DdNode * zEquPos; + DdNode * zEquNeg; + zEquPos = Extra_bddSpaceEquationsPos( dd, bSpace ); Cudd_Ref( zEquPos ); + zEquNeg = Extra_bddSpaceEquationsNeg( dd, bSpace ); Cudd_Ref( zEquNeg ); + zRes = Cudd_zddUnion( dd, zEquPos, zEquNeg ); Cudd_Ref( zRes ); + Cudd_RecursiveDerefZdd( dd, zEquPos ); + Cudd_RecursiveDerefZdd( dd, zEquNeg ); + Cudd_Deref( zRes ); + return zRes; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddSpaceEquationsPos( DdManager * dd, DdNode * bSpace ) +{ + DdNode * zRes; + do { + dd->reordered = 0; + zRes = extraBddSpaceEquationsPos( dd, bSpace ); + } while (dd->reordered == 1); + return zRes; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddSpaceEquationsNeg( DdManager * dd, DdNode * bSpace ) +{ + DdNode * zRes; + do { + dd->reordered = 0; + zRes = extraBddSpaceEquationsNeg( dd, bSpace ); + } while (dd->reordered == 1); + return zRes; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddSpaceFromMatrixPos( DdManager * dd, DdNode * zA ) +{ + DdNode * bRes; + do { + dd->reordered = 0; + bRes = extraBddSpaceFromMatrixPos( dd, zA ); + } while (dd->reordered == 1); + return bRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA ) +{ + DdNode * bRes; + do { + dd->reordered = 0; + bRes = extraBddSpaceFromMatrixNeg( dd, zA ); + } while (dd->reordered == 1); + return bRes; +} + +/**Function************************************************************* + + Synopsis [Counts the number of literals in one combination.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_zddLitCountComb( DdManager * dd, DdNode * zComb ) +{ + int Counter; + if ( zComb == z0 ) + return 0; + Counter = 0; + for ( ; zComb != z1; zComb = cuddT(zComb) ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [] + + Description [Returns the array of ZDDs with the number equal to the number of + vars in the DD manager. If the given var is non-canonical, this array contains + the referenced ZDD representing literals in the corresponding EXOR equation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode ** Extra_bddSpaceExorGates( DdManager * dd, DdNode * bFuncRed, DdNode * zEquations ) +{ + DdNode ** pzRes; + int * pVarsNonCan; + DdNode * zEquRem; + int iVarNonCan; + DdNode * zExor, * zTemp; + + // get the set of non-canonical variables + pVarsNonCan = ABC_ALLOC( int, ddMax(dd->size,dd->sizeZ) ); + Extra_SupportArray( dd, bFuncRed, pVarsNonCan ); + + // allocate storage for the EXOR sets + pzRes = ABC_ALLOC( DdNode *, dd->size ); + memset( pzRes, 0, sizeof(DdNode *) * dd->size ); + + // go through all the equations + zEquRem = zEquations; Cudd_Ref( zEquRem ); + while ( zEquRem != z0 ) + { + // extract one product + zExor = Extra_zddSelectOneSubset( dd, zEquRem ); Cudd_Ref( zExor ); + // remove it from the set + zEquRem = Cudd_zddDiff( dd, zTemp = zEquRem, zExor ); Cudd_Ref( zEquRem ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + + // locate the non-canonical variable + iVarNonCan = -1; + for ( zTemp = zExor; zTemp != z1; zTemp = cuddT(zTemp) ) + { + if ( pVarsNonCan[zTemp->index/2] == 1 ) + { + assert( iVarNonCan == -1 ); + iVarNonCan = zTemp->index/2; + } + } + assert( iVarNonCan != -1 ); + + if ( Extra_zddLitCountComb( dd, zExor ) > 1 ) + pzRes[ iVarNonCan ] = zExor; // takes ref + else + Cudd_RecursiveDerefZdd( dd, zExor ); + } + Cudd_RecursiveDerefZdd( dd, zEquRem ); + + ABC_FREE( pVarsNonCan ); + return pzRes; +} + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Performs the recursive steps of Extra_bddSpaceFromFunction.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * extraBddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG ) +{ + DdNode * bRes; + DdNode * bFR, * bGR; + + bFR = Cudd_Regular( bF ); + bGR = Cudd_Regular( bG ); + if ( cuddIsConstant(bFR) ) + { + if ( bF == bG ) + return b1; + else + return b0; + } + if ( cuddIsConstant(bGR) ) + return b0; + // both bFunc and bCore are not constants + + // the operation is commutative - normalize the problem + if ( (unsigned)(ABC_PTRUINT_T)bF > (unsigned)(ABC_PTRUINT_T)bG ) + return extraBddSpaceFromFunction(dd, bG, bF); + + + if ( (bRes = cuddCacheLookup2(dd, extraBddSpaceFromFunction, bF, bG)) ) + return bRes; + else + { + DdNode * bF0, * bF1; + DdNode * bG0, * bG1; + DdNode * bTemp1, * bTemp2; + DdNode * bRes0, * bRes1; + int LevelF, LevelG; + int index; + + LevelF = dd->perm[bFR->index]; + LevelG = dd->perm[bGR->index]; + if ( LevelF <= LevelG ) + { + index = dd->invperm[LevelF]; + if ( bFR != bF ) + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + } + else + { + index = dd->invperm[LevelG]; + bF0 = bF1 = bF; + } + + if ( LevelG <= LevelF ) + { + if ( bGR != bG ) + { + bG0 = Cudd_Not( cuddE(bGR) ); + bG1 = Cudd_Not( cuddT(bGR) ); + } + else + { + bG0 = cuddE(bGR); + bG1 = cuddT(bGR); + } + } + else + bG0 = bG1 = bG; + + bTemp1 = extraBddSpaceFromFunction( dd, bF0, bG0 ); + if ( bTemp1 == NULL ) + return NULL; + cuddRef( bTemp1 ); + + bTemp2 = extraBddSpaceFromFunction( dd, bF1, bG1 ); + if ( bTemp2 == NULL ) + { + Cudd_RecursiveDeref( dd, bTemp1 ); + return NULL; + } + cuddRef( bTemp2 ); + + + bRes0 = cuddBddAndRecur( dd, bTemp1, bTemp2 ); + if ( bRes0 == NULL ) + { + Cudd_RecursiveDeref( dd, bTemp1 ); + Cudd_RecursiveDeref( dd, bTemp2 ); + return NULL; + } + cuddRef( bRes0 ); + Cudd_RecursiveDeref( dd, bTemp1 ); + Cudd_RecursiveDeref( dd, bTemp2 ); + + + bTemp1 = extraBddSpaceFromFunction( dd, bF0, bG1 ); + if ( bTemp1 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + return NULL; + } + cuddRef( bTemp1 ); + + bTemp2 = extraBddSpaceFromFunction( dd, bF1, bG0 ); + if ( bTemp2 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + Cudd_RecursiveDeref( dd, bTemp1 ); + return NULL; + } + cuddRef( bTemp2 ); + + bRes1 = cuddBddAndRecur( dd, bTemp1, bTemp2 ); + if ( bRes1 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + Cudd_RecursiveDeref( dd, bTemp1 ); + Cudd_RecursiveDeref( dd, bTemp2 ); + return NULL; + } + cuddRef( bRes1 ); + Cudd_RecursiveDeref( dd, bTemp1 ); + Cudd_RecursiveDeref( dd, bTemp2 ); + + + + // consider the case when Res0 and Res1 are the same node + if ( bRes0 == bRes1 ) + bRes = bRes1; + // consider the case when Res1 is complemented + else if ( Cudd_IsComplement(bRes1) ) + { + bRes = cuddUniqueInter(dd, index, Cudd_Not(bRes1), Cudd_Not(bRes0)); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref(dd,bRes0); + Cudd_RecursiveDeref(dd,bRes1); + return NULL; + } + bRes = Cudd_Not(bRes); + } + else + { + bRes = cuddUniqueInter( dd, index, bRes1, bRes0 ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref(dd,bRes0); + Cudd_RecursiveDeref(dd,bRes1); + return NULL; + } + } + cuddDeref( bRes0 ); + cuddDeref( bRes1 ); + + // insert the result into cache + cuddCacheInsert2(dd, extraBddSpaceFromFunction, bF, bG, bRes); + return bRes; + } +} /* end of extraBddSpaceFromFunction */ + + + +/**Function************************************************************* + + Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * extraBddSpaceFromFunctionPos( DdManager * dd, DdNode * bF ) +{ + DdNode * bRes, * bFR; + statLine( dd ); + + bFR = Cudd_Regular(bF); + if ( cuddIsConstant(bFR) ) + return b1; + + if ( (bRes = cuddCacheLookup1(dd, extraBddSpaceFromFunctionPos, bF)) ) + return bRes; + else + { + DdNode * bF0, * bF1; + DdNode * bPos0, * bPos1; + DdNode * bNeg0, * bNeg1; + DdNode * bRes0, * bRes1; + + if ( bFR != bF ) // bF is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + + + bPos0 = extraBddSpaceFromFunctionPos( dd, bF0 ); + if ( bPos0 == NULL ) + return NULL; + cuddRef( bPos0 ); + + bPos1 = extraBddSpaceFromFunctionPos( dd, bF1 ); + if ( bPos1 == NULL ) + { + Cudd_RecursiveDeref( dd, bPos0 ); + return NULL; + } + cuddRef( bPos1 ); + + bRes0 = cuddBddAndRecur( dd, bPos0, bPos1 ); + if ( bRes0 == NULL ) + { + Cudd_RecursiveDeref( dd, bPos0 ); + Cudd_RecursiveDeref( dd, bPos1 ); + return NULL; + } + cuddRef( bRes0 ); + Cudd_RecursiveDeref( dd, bPos0 ); + Cudd_RecursiveDeref( dd, bPos1 ); + + + bNeg0 = extraBddSpaceFromFunctionNeg( dd, bF0 ); + if ( bNeg0 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + return NULL; + } + cuddRef( bNeg0 ); + + bNeg1 = extraBddSpaceFromFunctionNeg( dd, bF1 ); + if ( bNeg1 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + Cudd_RecursiveDeref( dd, bNeg0 ); + return NULL; + } + cuddRef( bNeg1 ); + + bRes1 = cuddBddAndRecur( dd, bNeg0, bNeg1 ); + if ( bRes1 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + Cudd_RecursiveDeref( dd, bNeg0 ); + Cudd_RecursiveDeref( dd, bNeg1 ); + return NULL; + } + cuddRef( bRes1 ); + Cudd_RecursiveDeref( dd, bNeg0 ); + Cudd_RecursiveDeref( dd, bNeg1 ); + + + // consider the case when Res0 and Res1 are the same node + if ( bRes0 == bRes1 ) + bRes = bRes1; + // consider the case when Res1 is complemented + else if ( Cudd_IsComplement(bRes1) ) + { + bRes = cuddUniqueInter( dd, bFR->index, Cudd_Not(bRes1), Cudd_Not(bRes0) ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref(dd,bRes0); + Cudd_RecursiveDeref(dd,bRes1); + return NULL; + } + bRes = Cudd_Not(bRes); + } + else + { + bRes = cuddUniqueInter( dd, bFR->index, bRes1, bRes0 ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref(dd,bRes0); + Cudd_RecursiveDeref(dd,bRes1); + return NULL; + } + } + cuddDeref( bRes0 ); + cuddDeref( bRes1 ); + + cuddCacheInsert1( dd, extraBddSpaceFromFunctionPos, bF, bRes ); + return bRes; + } +} + + + +/**Function************************************************************* + + Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * extraBddSpaceFromFunctionNeg( DdManager * dd, DdNode * bF ) +{ + DdNode * bRes, * bFR; + statLine( dd ); + + bFR = Cudd_Regular(bF); + if ( cuddIsConstant(bFR) ) + return b0; + + if ( (bRes = cuddCacheLookup1(dd, extraBddSpaceFromFunctionNeg, bF)) ) + return bRes; + else + { + DdNode * bF0, * bF1; + DdNode * bPos0, * bPos1; + DdNode * bNeg0, * bNeg1; + DdNode * bRes0, * bRes1; + + if ( bFR != bF ) // bF is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + + + bPos0 = extraBddSpaceFromFunctionNeg( dd, bF0 ); + if ( bPos0 == NULL ) + return NULL; + cuddRef( bPos0 ); + + bPos1 = extraBddSpaceFromFunctionNeg( dd, bF1 ); + if ( bPos1 == NULL ) + { + Cudd_RecursiveDeref( dd, bPos0 ); + return NULL; + } + cuddRef( bPos1 ); + + bRes0 = cuddBddAndRecur( dd, bPos0, bPos1 ); + if ( bRes0 == NULL ) + { + Cudd_RecursiveDeref( dd, bPos0 ); + Cudd_RecursiveDeref( dd, bPos1 ); + return NULL; + } + cuddRef( bRes0 ); + Cudd_RecursiveDeref( dd, bPos0 ); + Cudd_RecursiveDeref( dd, bPos1 ); + + + bNeg0 = extraBddSpaceFromFunctionPos( dd, bF0 ); + if ( bNeg0 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + return NULL; + } + cuddRef( bNeg0 ); + + bNeg1 = extraBddSpaceFromFunctionPos( dd, bF1 ); + if ( bNeg1 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + Cudd_RecursiveDeref( dd, bNeg0 ); + return NULL; + } + cuddRef( bNeg1 ); + + bRes1 = cuddBddAndRecur( dd, bNeg0, bNeg1 ); + if ( bRes1 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + Cudd_RecursiveDeref( dd, bNeg0 ); + Cudd_RecursiveDeref( dd, bNeg1 ); + return NULL; + } + cuddRef( bRes1 ); + Cudd_RecursiveDeref( dd, bNeg0 ); + Cudd_RecursiveDeref( dd, bNeg1 ); + + + // consider the case when Res0 and Res1 are the same node + if ( bRes0 == bRes1 ) + bRes = bRes1; + // consider the case when Res1 is complemented + else if ( Cudd_IsComplement(bRes1) ) + { + bRes = cuddUniqueInter( dd, bFR->index, Cudd_Not(bRes1), Cudd_Not(bRes0) ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref(dd,bRes0); + Cudd_RecursiveDeref(dd,bRes1); + return NULL; + } + bRes = Cudd_Not(bRes); + } + else + { + bRes = cuddUniqueInter( dd, bFR->index, bRes1, bRes0 ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref(dd,bRes0); + Cudd_RecursiveDeref(dd,bRes1); + return NULL; + } + } + cuddDeref( bRes0 ); + cuddDeref( bRes1 ); + + cuddCacheInsert1( dd, extraBddSpaceFromFunctionNeg, bF, bRes ); + return bRes; + } +} + + + +/**Function************************************************************* + + Synopsis [Performs the recursive step of Extra_bddSpaceCanonVars().] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * extraBddSpaceCanonVars( DdManager * dd, DdNode * bF ) +{ + DdNode * bRes, * bFR; + statLine( dd ); + + bFR = Cudd_Regular(bF); + if ( cuddIsConstant(bFR) ) + return bF; + + if ( (bRes = cuddCacheLookup1(dd, extraBddSpaceCanonVars, bF)) ) + return bRes; + else + { + DdNode * bF0, * bF1; + DdNode * bRes, * bRes0; + + if ( bFR != bF ) // bF is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + + if ( bF0 == b0 ) + { + bRes = extraBddSpaceCanonVars( dd, bF1 ); + if ( bRes == NULL ) + return NULL; + } + else if ( bF1 == b0 ) + { + bRes = extraBddSpaceCanonVars( dd, bF0 ); + if ( bRes == NULL ) + return NULL; + } + else + { + bRes0 = extraBddSpaceCanonVars( dd, bF0 ); + if ( bRes0 == NULL ) + return NULL; + cuddRef( bRes0 ); + + bRes = cuddUniqueInter( dd, bFR->index, bRes0, b0 ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref( dd,bRes0 ); + return NULL; + } + cuddDeref( bRes0 ); + } + + cuddCacheInsert1( dd, extraBddSpaceCanonVars, bF, bRes ); + return bRes; + } +} + +/**Function************************************************************* + + Synopsis [Performs the recursive step of Extra_bddSpaceEquationsPos().] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * extraBddSpaceEquationsPos( DdManager * dd, DdNode * bF ) +{ + DdNode * zRes; + statLine( dd ); + + if ( bF == b0 ) + return z1; + if ( bF == b1 ) + return z0; + + if ( (zRes = cuddCacheLookup1Zdd(dd, extraBddSpaceEquationsPos, bF)) ) + return zRes; + else + { + DdNode * bFR, * bF0, * bF1; + DdNode * zPos0, * zPos1, * zNeg1; + DdNode * zRes, * zRes0, * zRes1; + + bFR = Cudd_Regular(bF); + if ( bFR != bF ) // bF is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + + if ( bF0 == b0 ) + { + zRes1 = extraBddSpaceEquationsPos( dd, bF1 ); + if ( zRes1 == NULL ) + return NULL; + cuddRef( zRes1 ); + + // add the current element to the set + zRes = cuddZddGetNode( dd, 2*bFR->index, z1, zRes1 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zRes1); + return NULL; + } + cuddDeref( zRes1 ); + } + else if ( bF1 == b0 ) + { + zRes = extraBddSpaceEquationsPos( dd, bF0 ); + if ( zRes == NULL ) + return NULL; + } + else + { + zPos0 = extraBddSpaceEquationsPos( dd, bF0 ); + if ( zPos0 == NULL ) + return NULL; + cuddRef( zPos0 ); + + zPos1 = extraBddSpaceEquationsPos( dd, bF1 ); + if ( zPos1 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zPos0); + return NULL; + } + cuddRef( zPos1 ); + + zNeg1 = extraBddSpaceEquationsNeg( dd, bF1 ); + if ( zNeg1 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zPos0); + Cudd_RecursiveDerefZdd(dd, zPos1); + return NULL; + } + cuddRef( zNeg1 ); + + + zRes0 = cuddZddIntersect( dd, zPos0, zPos1 ); + if ( zRes0 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zNeg1); + Cudd_RecursiveDerefZdd(dd, zPos0); + Cudd_RecursiveDerefZdd(dd, zPos1); + return NULL; + } + cuddRef( zRes0 ); + + zRes1 = cuddZddIntersect( dd, zPos0, zNeg1 ); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zRes0); + Cudd_RecursiveDerefZdd(dd, zNeg1); + Cudd_RecursiveDerefZdd(dd, zPos0); + Cudd_RecursiveDerefZdd(dd, zPos1); + return NULL; + } + cuddRef( zRes1 ); + Cudd_RecursiveDerefZdd(dd, zNeg1); + Cudd_RecursiveDerefZdd(dd, zPos0); + Cudd_RecursiveDerefZdd(dd, zPos1); + // only zRes0 and zRes1 are refed at this point + + zRes = cuddZddGetNode( dd, 2*bFR->index, zRes1, zRes0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zRes0); + Cudd_RecursiveDerefZdd(dd, zRes1); + return NULL; + } + cuddDeref( zRes0 ); + cuddDeref( zRes1 ); + } + + cuddCacheInsert1( dd, extraBddSpaceEquationsPos, bF, zRes ); + return zRes; + } +} + + +/**Function************************************************************* + + Synopsis [Performs the recursive step of Extra_bddSpaceEquationsNev().] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * extraBddSpaceEquationsNeg( DdManager * dd, DdNode * bF ) +{ + DdNode * zRes; + statLine( dd ); + + if ( bF == b0 ) + return z1; + if ( bF == b1 ) + return z0; + + if ( (zRes = cuddCacheLookup1Zdd(dd, extraBddSpaceEquationsNeg, bF)) ) + return zRes; + else + { + DdNode * bFR, * bF0, * bF1; + DdNode * zPos0, * zPos1, * zNeg1; + DdNode * zRes, * zRes0, * zRes1; + + bFR = Cudd_Regular(bF); + if ( bFR != bF ) // bF is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + + if ( bF0 == b0 ) + { + zRes = extraBddSpaceEquationsNeg( dd, bF1 ); + if ( zRes == NULL ) + return NULL; + } + else if ( bF1 == b0 ) + { + zRes0 = extraBddSpaceEquationsNeg( dd, bF0 ); + if ( zRes0 == NULL ) + return NULL; + cuddRef( zRes0 ); + + // add the current element to the set + zRes = cuddZddGetNode( dd, 2*bFR->index, z1, zRes0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zRes0); + return NULL; + } + cuddDeref( zRes0 ); + } + else + { + zPos0 = extraBddSpaceEquationsNeg( dd, bF0 ); + if ( zPos0 == NULL ) + return NULL; + cuddRef( zPos0 ); + + zPos1 = extraBddSpaceEquationsNeg( dd, bF1 ); + if ( zPos1 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zPos0); + return NULL; + } + cuddRef( zPos1 ); + + zNeg1 = extraBddSpaceEquationsPos( dd, bF1 ); + if ( zNeg1 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zPos0); + Cudd_RecursiveDerefZdd(dd, zPos1); + return NULL; + } + cuddRef( zNeg1 ); + + + zRes0 = cuddZddIntersect( dd, zPos0, zPos1 ); + if ( zRes0 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zNeg1); + Cudd_RecursiveDerefZdd(dd, zPos0); + Cudd_RecursiveDerefZdd(dd, zPos1); + return NULL; + } + cuddRef( zRes0 ); + + zRes1 = cuddZddIntersect( dd, zPos0, zNeg1 ); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zRes0); + Cudd_RecursiveDerefZdd(dd, zNeg1); + Cudd_RecursiveDerefZdd(dd, zPos0); + Cudd_RecursiveDerefZdd(dd, zPos1); + return NULL; + } + cuddRef( zRes1 ); + Cudd_RecursiveDerefZdd(dd, zNeg1); + Cudd_RecursiveDerefZdd(dd, zPos0); + Cudd_RecursiveDerefZdd(dd, zPos1); + // only zRes0 and zRes1 are refed at this point + + zRes = cuddZddGetNode( dd, 2*bFR->index, zRes1, zRes0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zRes0); + Cudd_RecursiveDerefZdd(dd, zRes1); + return NULL; + } + cuddDeref( zRes0 ); + cuddDeref( zRes1 ); + } + + cuddCacheInsert1( dd, extraBddSpaceEquationsNeg, bF, zRes ); + return zRes; + } +} + + + + +/**Function************************************************************* + + Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * extraBddSpaceFromMatrixPos( DdManager * dd, DdNode * zA ) +{ + DdNode * bRes; + statLine( dd ); + + if ( zA == z0 ) + return b1; + if ( zA == z1 ) + return b1; + + if ( (bRes = cuddCacheLookup1(dd, extraBddSpaceFromMatrixPos, zA)) ) + return bRes; + else + { + DdNode * bP0, * bP1; + DdNode * bN0, * bN1; + DdNode * bRes0, * bRes1; + + bP0 = extraBddSpaceFromMatrixPos( dd, cuddE(zA) ); + if ( bP0 == NULL ) + return NULL; + cuddRef( bP0 ); + + bP1 = extraBddSpaceFromMatrixPos( dd, cuddT(zA) ); + if ( bP1 == NULL ) + { + Cudd_RecursiveDeref( dd, bP0 ); + return NULL; + } + cuddRef( bP1 ); + + bRes0 = cuddBddAndRecur( dd, bP0, bP1 ); + if ( bRes0 == NULL ) + { + Cudd_RecursiveDeref( dd, bP0 ); + Cudd_RecursiveDeref( dd, bP1 ); + return NULL; + } + cuddRef( bRes0 ); + Cudd_RecursiveDeref( dd, bP0 ); + Cudd_RecursiveDeref( dd, bP1 ); + + + bN0 = extraBddSpaceFromMatrixPos( dd, cuddE(zA) ); + if ( bN0 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + return NULL; + } + cuddRef( bN0 ); + + bN1 = extraBddSpaceFromMatrixNeg( dd, cuddT(zA) ); + if ( bN1 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + Cudd_RecursiveDeref( dd, bN0 ); + return NULL; + } + cuddRef( bN1 ); + + bRes1 = cuddBddAndRecur( dd, bN0, bN1 ); + if ( bRes1 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + Cudd_RecursiveDeref( dd, bN0 ); + Cudd_RecursiveDeref( dd, bN1 ); + return NULL; + } + cuddRef( bRes1 ); + Cudd_RecursiveDeref( dd, bN0 ); + Cudd_RecursiveDeref( dd, bN1 ); + + + // consider the case when Res0 and Res1 are the same node + if ( bRes0 == bRes1 ) + bRes = bRes1; + // consider the case when Res1 is complemented + else if ( Cudd_IsComplement(bRes1) ) + { + bRes = cuddUniqueInter( dd, zA->index/2, Cudd_Not(bRes1), Cudd_Not(bRes0) ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref(dd,bRes0); + Cudd_RecursiveDeref(dd,bRes1); + return NULL; + } + bRes = Cudd_Not(bRes); + } + else + { + bRes = cuddUniqueInter( dd, zA->index/2, bRes1, bRes0 ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref(dd,bRes0); + Cudd_RecursiveDeref(dd,bRes1); + return NULL; + } + } + cuddDeref( bRes0 ); + cuddDeref( bRes1 ); + + cuddCacheInsert1( dd, extraBddSpaceFromMatrixPos, zA, bRes ); + return bRes; + } +} + + +/**Function************************************************************* + + Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * extraBddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA ) +{ + DdNode * bRes; + statLine( dd ); + + if ( zA == z0 ) + return b1; + if ( zA == z1 ) + return b0; + + if ( (bRes = cuddCacheLookup1(dd, extraBddSpaceFromMatrixNeg, zA)) ) + return bRes; + else + { + DdNode * bP0, * bP1; + DdNode * bN0, * bN1; + DdNode * bRes0, * bRes1; + + bP0 = extraBddSpaceFromMatrixNeg( dd, cuddE(zA) ); + if ( bP0 == NULL ) + return NULL; + cuddRef( bP0 ); + + bP1 = extraBddSpaceFromMatrixNeg( dd, cuddT(zA) ); + if ( bP1 == NULL ) + { + Cudd_RecursiveDeref( dd, bP0 ); + return NULL; + } + cuddRef( bP1 ); + + bRes0 = cuddBddAndRecur( dd, bP0, bP1 ); + if ( bRes0 == NULL ) + { + Cudd_RecursiveDeref( dd, bP0 ); + Cudd_RecursiveDeref( dd, bP1 ); + return NULL; + } + cuddRef( bRes0 ); + Cudd_RecursiveDeref( dd, bP0 ); + Cudd_RecursiveDeref( dd, bP1 ); + + + bN0 = extraBddSpaceFromMatrixNeg( dd, cuddE(zA) ); + if ( bN0 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + return NULL; + } + cuddRef( bN0 ); + + bN1 = extraBddSpaceFromMatrixPos( dd, cuddT(zA) ); + if ( bN1 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + Cudd_RecursiveDeref( dd, bN0 ); + return NULL; + } + cuddRef( bN1 ); + + bRes1 = cuddBddAndRecur( dd, bN0, bN1 ); + if ( bRes1 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + Cudd_RecursiveDeref( dd, bN0 ); + Cudd_RecursiveDeref( dd, bN1 ); + return NULL; + } + cuddRef( bRes1 ); + Cudd_RecursiveDeref( dd, bN0 ); + Cudd_RecursiveDeref( dd, bN1 ); + + + // consider the case when Res0 and Res1 are the same node + if ( bRes0 == bRes1 ) + bRes = bRes1; + // consider the case when Res1 is complemented + else if ( Cudd_IsComplement(bRes1) ) + { + bRes = cuddUniqueInter( dd, zA->index/2, Cudd_Not(bRes1), Cudd_Not(bRes0) ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref(dd,bRes0); + Cudd_RecursiveDeref(dd,bRes1); + return NULL; + } + bRes = Cudd_Not(bRes); + } + else + { + bRes = cuddUniqueInter( dd, zA->index/2, bRes1, bRes0 ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref(dd,bRes0); + Cudd_RecursiveDeref(dd,bRes1); + return NULL; + } + } + cuddDeref( bRes0 ); + cuddDeref( bRes1 ); + + cuddCacheInsert1( dd, extraBddSpaceFromMatrixNeg, zA, bRes ); + return bRes; + } +} + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/extrab/extraBddCas.c b/src/bdd/extrab/extraBddCas.c new file mode 100644 index 00000000..024e4462 --- /dev/null +++ b/src/bdd/extrab/extraBddCas.c @@ -0,0 +1,1235 @@ +/**CFile**************************************************************** + + FileName [extraBddCas.c] + + PackageName [extra] + + Synopsis [Procedures related to LUT cascade synthesis.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - September 1, 2003.] + + Revision [$Id: extraBddCas.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $] + +***********************************************************************/ + +#include "extraBdd.h" + +ABC_NAMESPACE_IMPL_START + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +// the table to store cofactor operations +#define _TABLESIZE_COF 51113 +typedef struct +{ + unsigned Sign; + DdNode * Arg1; +} _HashEntry_cof; +_HashEntry_cof HHTable1[_TABLESIZE_COF]; + +// the table to store the result of computation of the number of minterms +#define _TABLESIZE_MINT 15113 +typedef struct +{ + DdNode * Arg1; + unsigned Arg2; + unsigned Res; +} _HashEntry_mint; +_HashEntry_mint HHTable2[_TABLESIZE_MINT]; + +typedef struct +{ + int nEdges; // the number of in-coming edges of the node + DdNode * bSum; // the sum of paths of the incoming edges +} traventry; + +// the signature used for hashing +static unsigned s_Signature = 1; + +static int s_CutLevel = 0; + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +// because the proposed solution to the optimal encoding problem has exponential complexity +// we limit the depth of the branch and bound procedure to 5 levels +static int s_MaxDepth = 5; + +static int s_nVarsBest; // the number of vars in the best ordering +static int s_VarOrderBest[32]; // storing the best ordering of vars in the "simple encoding" +static int s_VarOrderCur[32]; // storing the current ordering of vars + +// the place to store the supports of the encoded function +static DdNode * s_Field[8][256]; // the size should be K, 2^K, where K is no less than MaxDepth +static DdNode * s_Encoded; // this is the original function +static DdNode * s_VarAll; // the set of all column variables +static int s_MultiStart; // the total number of encoding variables used +// the array field now stores the supports + +static DdNode ** s_pbTemp; // the temporary storage for the columns + +static int s_BackTracks; +static int s_BackTrackLimit = 100; + +static DdNode * s_Terminal; // the terminal value for counting minterms + + +static int s_EncodingVarsLevel; + + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static DdNode * CreateTheCodes_rec( DdManager * dd, DdNode * bEncoded, int Level, DdNode ** pCVars ); +static void EvaluateEncodings_rec( DdManager * dd, DdNode * bVarsCol, int nVarsCol, int nMulti, int Level ); +// functions called from EvaluateEncodings_rec() +static DdNode * ComputeVarSetAndCountMinterms( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost ); +static DdNode * ComputeVarSetAndCountMinterms2( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost ); +unsigned Extra_CountCofactorMinterms( DdManager * dd, DdNode * bFunc, DdNode * bVarsCof, DdNode * bVarsAll ); +static unsigned Extra_CountMintermsSimple( DdNode * bFunc, unsigned max ); + +static void CountNodeVisits_rec( DdManager * dd, DdNode * aFunc, st__table * Visited ); +static void CollectNodesAndComputePaths_rec( DdManager * dd, DdNode * aFunc, DdNode * bCube, st__table * Visited, st__table * CutNodes ); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Performs the binary encoding of the set of function using the given vars.] + + Description [Performs a straight binary encoding of the set of functions using + the variable cubes formed from the given set of variables. ] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * +Extra_bddEncodingBinary( + DdManager * dd, + DdNode ** pbFuncs, // pbFuncs is the array of columns to be encoded + int nFuncs, // nFuncs is the number of columns in the array + DdNode ** pbVars, // pbVars is the array of variables to use for the codes + int nVars ) // nVars is the column multiplicity, [log2(nFuncs)] +{ + int i; + DdNode * bResult; + DdNode * bCube, * bTemp, * bProd; + + assert( nVars >= Abc_Base2Log(nFuncs) ); + + bResult = b0; Cudd_Ref( bResult ); + for ( i = 0; i < nFuncs; i++ ) + { + bCube = Extra_bddBitsToCube( dd, i, nVars, pbVars, 1 ); Cudd_Ref( bCube ); + bProd = Cudd_bddAnd( dd, bCube, pbFuncs[i] ); Cudd_Ref( bProd ); + Cudd_RecursiveDeref( dd, bCube ); + + bResult = Cudd_bddOr( dd, bProd, bTemp = bResult ); Cudd_Ref( bResult ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bProd ); + } + + Cudd_Deref( bResult ); + return bResult; +} /* end of Extra_bddEncodingBinary */ + + +/**Function******************************************************************** + + Synopsis [Solves the column encoding problem using a sophisticated method.] + + Description [The encoding is based on the idea of deriving functions which + depend on only one variable, which corresponds to the case of non-disjoint + decompostion. It is assumed that the variables pCVars are ordered below the variables + representing the solumns, and the first variable pCVars[0] is the topmost one.] + + SideEffects [] + + SeeAlso [Extra_bddEncodingBinary] + +******************************************************************************/ + +DdNode * +Extra_bddEncodingNonStrict( + DdManager * dd, + DdNode ** pbColumns, // pbColumns is the array of columns to be encoded; + int nColumns, // nColumns is the number of columns in the array + DdNode * bVarsCol, // bVarsCol is the cube of variables on which the columns depend + DdNode ** pCVars, // pCVars is the array of variables to use for the codes + int nMulti, // nMulti is the column multiplicity, [log2(nColumns)] + int * pSimple ) // pSimple gets the number of code variables taken from the input varibles without change +{ + DdNode * bEncoded, * bResult; + int nVarsCol = Cudd_SupportSize(dd,bVarsCol); + abctime clk; + + // cannot work with more that 32-bit codes + assert( nMulti < 32 ); + + // perform the preliminary encoding using the straight binary code + bEncoded = Extra_bddEncodingBinary( dd, pbColumns, nColumns, pCVars, nMulti ); Cudd_Ref( bEncoded ); + //printf( "Node count = %d", Cudd_DagSize(bEncoded) ); + + // set the backgroup value for counting minterms + s_Terminal = b0; + // set the level of the encoding variables + s_EncodingVarsLevel = dd->invperm[pCVars[0]->index]; + + // the current number of backtracks + s_BackTracks = 0; + // the variables that are cofactored on the topmost level where everything starts (no vars) + s_Field[0][0] = b1; + // the size of the best set of "simple" encoding variables found so far + s_nVarsBest = 0; + + // set the relation to be accessible to traversal procedures + s_Encoded = bEncoded; + // the set of all vars to be accessible to traversal procedures + s_VarAll = bVarsCol; + // the column multiplicity + s_MultiStart = nMulti; + + + clk = Abc_Clock(); + // find the simplest encoding + if ( nColumns > 2 ) + EvaluateEncodings_rec( dd, bVarsCol, nVarsCol, nMulti, 1 ); +// printf( "The number of backtracks = %d\n", s_BackTracks ); +// s_EncSearchTime += Abc_Clock() - clk; + + // allocate the temporary storage for the columns + s_pbTemp = (DdNode **)ABC_ALLOC( char, nColumns * sizeof(DdNode *) ); + +// clk = Abc_Clock(); + bResult = CreateTheCodes_rec( dd, bEncoded, 0, pCVars ); Cudd_Ref( bResult ); +// s_EncComputeTime += Abc_Clock() - clk; + + // delocate the preliminarily encoded set + Cudd_RecursiveDeref( dd, bEncoded ); +// Cudd_RecursiveDeref( dd, aEncoded ); + + ABC_FREE( s_pbTemp ); + + *pSimple = s_nVarsBest; + Cudd_Deref( bResult ); + return bResult; +} + +/**Function******************************************************************** + + Synopsis [Collects the nodes under the cut and, for each node, computes the sum of paths leading to it from the root.] + + Description [The table returned contains the set of BDD nodes pointed to under the cut + and, for each node, the BDD of the sum of paths leading to this node from the root + The sums of paths in the table are referenced. CutLevel is the first DD level + considered to be under the cut.] + + SideEffects [] + + SeeAlso [Extra_bddNodePaths] + +******************************************************************************/ + st__table * Extra_bddNodePathsUnderCut( DdManager * dd, DdNode * bFunc, int CutLevel ) +{ + st__table * Visited; // temporary table to remember the visited nodes + st__table * CutNodes; // the result goes here + st__table * Result; // the result goes here + DdNode * aFunc; + + s_CutLevel = CutLevel; + + Result = st__init_table( st__ptrcmp, st__ptrhash);; + // the terminal cases + if ( Cudd_IsConstant( bFunc ) ) + { + if ( bFunc == b1 ) + { + st__insert( Result, (char*)b1, (char*)b1 ); + Cudd_Ref( b1 ); + Cudd_Ref( b1 ); + } + else + { + st__insert( Result, (char*)b0, (char*)b0 ); + Cudd_Ref( b0 ); + Cudd_Ref( b0 ); + } + return Result; + } + + // create the ADD to simplify processing (no complemented edges) + aFunc = Cudd_BddToAdd( dd, bFunc ); Cudd_Ref( aFunc ); + + // Step 1: Start the tables and collect information about the nodes above the cut + // this information tells how many edges point to each node + Visited = st__init_table( st__ptrcmp, st__ptrhash);; + CutNodes = st__init_table( st__ptrcmp, st__ptrhash);; + + CountNodeVisits_rec( dd, aFunc, Visited ); + + // Step 2: Traverse the BDD using the visited table and compute the sum of paths + CollectNodesAndComputePaths_rec( dd, aFunc, b1, Visited, CutNodes ); + + // at this point the table of cut nodes is ready and the table of visited is useless + { + st__generator * gen; + DdNode * aNode; + traventry * p; + st__foreach_item( Visited, gen, (const char**)&aNode, (char**)&p ) + { + Cudd_RecursiveDeref( dd, p->bSum ); + ABC_FREE( p ); + } + st__free_table( Visited ); + } + + // go through the table CutNodes and create the BDD and the path to be returned + { + st__generator * gen; + DdNode * aNode, * bNode, * bSum; + st__foreach_item( CutNodes, gen, (const char**)&aNode, (char**)&bSum) + { + // aNode is not referenced, because aFunc is holding it + bNode = Cudd_addBddPattern( dd, aNode ); Cudd_Ref( bNode ); + st__insert( Result, (char*)bNode, (char*)bSum ); + // the new table takes both refs + } + st__free_table( CutNodes ); + } + + // dereference the ADD + Cudd_RecursiveDeref( dd, aFunc ); + + // return the table + return Result; + +} /* end of Extra_bddNodePathsUnderCut */ + +/**Function******************************************************************** + + Synopsis [Collects the nodes under the cut in the ADD starting from the given set of ADD nodes.] + + Description [Takes the array, paNodes, of ADD nodes to start the traversal, + the array, pbCubes, of BDD cubes to start the traversal with in each node, + and the number, nNodes, of ADD nodes and BDD cubes in paNodes and pbCubes. + Returns the number of columns found. Fills in paNodesRes (pbCubesRes) + with the set of ADD columns (BDD paths). These arrays should be allocated + by the user.] + + SideEffects [] + + SeeAlso [Extra_bddNodePaths] + +******************************************************************************/ +int Extra_bddNodePathsUnderCutArray( DdManager * dd, DdNode ** paNodes, DdNode ** pbCubes, int nNodes, DdNode ** paNodesRes, DdNode ** pbCubesRes, int CutLevel ) +{ + st__table * Visited; // temporary table to remember the visited nodes + st__table * CutNodes; // the nodes under the cut go here + int i, Counter; + + s_CutLevel = CutLevel; + + // there should be some nodes + assert( nNodes > 0 ); + if ( nNodes == 1 && Cudd_IsConstant( paNodes[0] ) ) + { + if ( paNodes[0] == a1 ) + { + paNodesRes[0] = a1; Cudd_Ref( a1 ); + pbCubesRes[0] = pbCubes[0]; Cudd_Ref( pbCubes[0] ); + } + else + { + paNodesRes[0] = a0; Cudd_Ref( a0 ); + pbCubesRes[0] = pbCubes[0]; Cudd_Ref( pbCubes[0] ); + } + return 1; + } + + // Step 1: Start the table and collect information about the nodes above the cut + // this information tells how many edges point to each node + CutNodes = st__init_table( st__ptrcmp, st__ptrhash);; + Visited = st__init_table( st__ptrcmp, st__ptrhash);; + + for ( i = 0; i < nNodes; i++ ) + CountNodeVisits_rec( dd, paNodes[i], Visited ); + + // Step 2: Traverse the BDD using the visited table and compute the sum of paths + for ( i = 0; i < nNodes; i++ ) + CollectNodesAndComputePaths_rec( dd, paNodes[i], pbCubes[i], Visited, CutNodes ); + + // at this point, the table of cut nodes is ready and the table of visited is useless + { + st__generator * gen; + DdNode * aNode; + traventry * p; + st__foreach_item( Visited, gen, (const char**)&aNode, (char**)&p ) + { + Cudd_RecursiveDeref( dd, p->bSum ); + ABC_FREE( p ); + } + st__free_table( Visited ); + } + + // go through the table CutNodes and create the BDD and the path to be returned + { + st__generator * gen; + DdNode * aNode, * bSum; + Counter = 0; + st__foreach_item( CutNodes, gen, (const char**)&aNode, (char**)&bSum) + { + paNodesRes[Counter] = aNode; Cudd_Ref( aNode ); + pbCubesRes[Counter] = bSum; + Counter++; + } + st__free_table( CutNodes ); + } + + // return the number of cofactors found + return Counter; + +} /* end of Extra_bddNodePathsUnderCutArray */ + +/**Function************************************************************* + + Synopsis [Collects all the BDD nodes into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void extraCollectNodes( DdNode * Func, st__table * tNodes ) +{ + DdNode * FuncR; + FuncR = Cudd_Regular(Func); + if ( st__find_or_add( tNodes, (char*)FuncR, NULL ) ) + return; + if ( cuddIsConstant(FuncR) ) + return; + extraCollectNodes( cuddE(FuncR), tNodes ); + extraCollectNodes( cuddT(FuncR), tNodes ); +} + +/**Function************************************************************* + + Synopsis [Collects all the nodes of one DD into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + st__table * Extra_CollectNodes( DdNode * Func ) +{ + st__table * tNodes; + tNodes = st__init_table( st__ptrcmp, st__ptrhash ); + extraCollectNodes( Func, tNodes ); + return tNodes; +} + +/**Function************************************************************* + + Synopsis [Updates the topmost level from which the given node is referenced.] + + Description [Takes the table which maps each BDD nodes (including the constants) + into the topmost level on which this node counts as a cofactor. Takes the topmost + level, on which this node counts as a cofactor (see Extra_ProfileWidthFast(). + Takes the node, for which the table entry should be updated.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void extraProfileUpdateTopLevel( st__table * tNodeTopRef, int TopLevelNew, DdNode * node ) +{ + int * pTopLevel; + + if ( st__find_or_add( tNodeTopRef, (char*)node, (char***)&pTopLevel ) ) + { // the node is already referenced + // the current top level should be updated if it is larger than the new level + if ( *pTopLevel > TopLevelNew ) + *pTopLevel = TopLevelNew; + } + else + { // the node is not referenced + // its level should be set to the current new level + *pTopLevel = TopLevelNew; + } +} +/**Function************************************************************* + + Synopsis [Fast computation of the BDD profile.] + + Description [The array to store the profile is given by the user and should + contain at least as many entries as there is the maximum of the BDD/ZDD + size of the manager PLUS ONE. + When we say that the widths of the DD on level L is W, we mean the following. + Let us create the cut between the level L-1 and the level L and count the number + of different DD nodes pointed to across the cut. This number is the width W. + From this it follows the on level 0, the width is equal to the number of external + pointers to the considered DDs. If there is only one DD, then the profile on + level 0 is always 1. If this DD is rooted in the topmost variable, then the width + on level 1 is always 2, etc. The width at the level equal to dd->size is the + number of terminal nodes in the DD. (Because we consider the first level #0 + and the last level #dd->size, the profile array should contain dd->size+1 entries.) + ] + + SideEffects [This procedure will not work for BDDs w/ complement edges, only for ADDs and ZDDs] + + SeeAlso [] + +***********************************************************************/ +int Extra_ProfileWidth( DdManager * dd, DdNode * Func, int * pProfile, int CutLevel ) +{ + st__generator * gen; + st__table * tNodeTopRef; // this table stores the top level from which this node is pointed to + st__table * tNodes; + DdNode * node; + DdNode * nodeR; + int LevelStart, Limit; + int i, size; + int WidthMax; + + // start the mapping table + tNodeTopRef = st__init_table( st__ptrcmp, st__ptrhash);; + // add the topmost node to the profile + extraProfileUpdateTopLevel( tNodeTopRef, 0, Func ); + + // collect all nodes + tNodes = Extra_CollectNodes( Func ); + // go though all the nodes and set the top level the cofactors are pointed from +// Cudd_ForeachNode( dd, Func, genDD, node ) + st__foreach_item( tNodes, gen, (const char**)&node, NULL ) + { +// assert( Cudd_Regular(node) ); // this procedure works only with ADD/ZDD (not BDD w/ compl.edges) + nodeR = Cudd_Regular(node); + if ( cuddIsConstant(nodeR) ) + continue; + // this node is not a constant - consider its cofactors + extraProfileUpdateTopLevel( tNodeTopRef, dd->perm[node->index]+1, cuddE(nodeR) ); + extraProfileUpdateTopLevel( tNodeTopRef, dd->perm[node->index]+1, cuddT(nodeR) ); + } + st__free_table( tNodes ); + + // clean the profile + size = ddMax(dd->size, dd->sizeZ) + 1; + for ( i = 0; i < size; i++ ) + pProfile[i] = 0; + + // create the profile + st__foreach_item( tNodeTopRef, gen, (const char**)&node, (char**)&LevelStart ) + { + nodeR = Cudd_Regular(node); + Limit = (cuddIsConstant(nodeR))? dd->size: dd->perm[nodeR->index]; + for ( i = LevelStart; i <= Limit; i++ ) + pProfile[i]++; + } + + if ( CutLevel != -1 && CutLevel != 0 ) + size = CutLevel; + + // get the max width + WidthMax = 0; + for ( i = 0; i < size; i++ ) + if ( WidthMax < pProfile[i] ) + WidthMax = pProfile[i]; + + // deref the table + st__free_table( tNodeTopRef ); + + return WidthMax; +} /* end of Extra_ProfileWidth */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Computes the non-strict codes when evaluation is finished.] + + Description [The information about the best code is stored in s_VarOrderBest, + which has s_nVarsBest entries.] + + SideEffects [None] + +******************************************************************************/ +DdNode * CreateTheCodes_rec( DdManager * dd, DdNode * bEncoded, int Level, DdNode ** pCVars ) +// bEncoded is the preliminarily encoded set of columns +// Level is the current level in the recursion +// pCVars are the variables to be used for encoding +{ + DdNode * bRes; + if ( Level == s_nVarsBest ) + { // the terminal case, when we need to remap the encoded function + // from the preliminary encoded variables to the new ones + st__table * CutNodes; + int nCols; +// double nMints; +/* +#ifdef _DEBUG + + { + DdNode * bTemp; + // make sure that the given number of variables is enough + bTemp = Cudd_bddExistAbstract( dd, bEncoded, s_VarAll ); Cudd_Ref( bTemp ); +// nMints = Cudd_CountMinterm( dd, bTemp, s_MultiStart ); + nMints = Extra_CountMintermsSimple( bTemp, (1< Extra_Power2( s_MultiStart-Level ) ) + { // the number of minterms is too large to encode the columns + // using the given minimum number of encoding variables + assert( 0 ); + } + Cudd_RecursiveDeref( dd, bTemp ); + } +#endif +*/ + // get the columns to be re-encoded + CutNodes = Extra_bddNodePathsUnderCut( dd, bEncoded, s_EncodingVarsLevel ); + // LUT size is the cut level because because the temporary encoding variables + // are above the functional variables - this is not true!!! + // the temporary variables are below! + + // put the entries from the table into the temporary array + { + st__generator * gen; + DdNode * bColumn, * bCode; + nCols = 0; + st__foreach_item( CutNodes, gen, (const char**)&bCode, (char**)&bColumn ) + { + if ( bCode == b0 ) + { // the unused part of the columns + Cudd_RecursiveDeref( dd, bColumn ); + Cudd_RecursiveDeref( dd, bCode ); + continue; + } + else + { + s_pbTemp[ nCols ] = bColumn; // takes ref + Cudd_RecursiveDeref( dd, bCode ); + nCols++; + } + } + st__free_table( CutNodes ); +// assert( nCols == (int)nMints ); + } + + // encode the columns + if ( s_MultiStart-Level == 0 ) // we reached the bottom level of recursion + { + assert( nCols == 1 ); +// assert( (int)nMints == 1 ); + bRes = s_pbTemp[0]; Cudd_Ref( bRes ); + } + else + { + bRes = Extra_bddEncodingBinary( dd, s_pbTemp, nCols, pCVars+Level, s_MultiStart-Level ); Cudd_Ref( bRes ); + } + + // deref the columns + { + int i; + for ( i = 0; i < nCols; i++ ) + Cudd_RecursiveDeref( dd, s_pbTemp[i] ); + } + } + else + { + // cofactor the problem as specified in the best solution + DdNode * bCof0, * bCof1; + DdNode * bRes0, * bRes1; + DdNode * bProd0, * bProd1; + DdNode * bTemp; + DdNode * bVarNext = dd->vars[ s_VarOrderBest[Level] ]; + + bCof0 = Cudd_Cofactor( dd, bEncoded, Cudd_Not( bVarNext ) ); Cudd_Ref( bCof0 ); + bCof1 = Cudd_Cofactor( dd, bEncoded, bVarNext ); Cudd_Ref( bCof1 ); + + // call recursively + bRes0 = CreateTheCodes_rec( dd, bCof0, Level+1, pCVars ); Cudd_Ref( bRes0 ); + bRes1 = CreateTheCodes_rec( dd, bCof1, Level+1, pCVars ); Cudd_Ref( bRes1 ); + + Cudd_RecursiveDeref( dd, bCof0 ); + Cudd_RecursiveDeref( dd, bCof1 ); + + // compose the result using the identity (bVarNext <=> pCVars[Level]) - this is wrong! + // compose the result as follows: x'y'F0 + xyF1 + bProd0 = Cudd_bddAnd( dd, Cudd_Not(bVarNext), Cudd_Not(pCVars[Level]) ); Cudd_Ref( bProd0 ); + bProd1 = Cudd_bddAnd( dd, bVarNext , pCVars[Level] ); Cudd_Ref( bProd1 ); + + bProd0 = Cudd_bddAnd( dd, bTemp = bProd0, bRes0 ); Cudd_Ref( bProd0 ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bRes0 ); + + bProd1 = Cudd_bddAnd( dd, bTemp = bProd1, bRes1 ); Cudd_Ref( bProd1 ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bRes1 ); + + bRes = Cudd_bddOr( dd, bProd0, bProd1 ); Cudd_Ref( bRes ); + + Cudd_RecursiveDeref( dd, bProd0 ); + Cudd_RecursiveDeref( dd, bProd1 ); + } + Cudd_Deref( bRes ); + return bRes; +} + +/**Function******************************************************************** + + Synopsis [Computes the current set of variables and counts the number of minterms.] + + Description [Old implementation.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void EvaluateEncodings_rec( DdManager * dd, DdNode * bVarsCol, int nVarsCol, int nMulti, int Level ) +// bVarsCol is the set of remaining variables +// nVarsCol is the number of remaining variables +// nMulti is the number of encoding variables to be used +// Level is the level of recursion, from which this function is called +// if we successfully finish this procedure, Level also stands for how many encoding variabled we saved +{ + int i, k; + int nEntries = (1<<(Level-1)); // the number of entries in the field of the previous level + DdNode * bVars0, * bVars1; // the cofactors + unsigned nMint0, nMint1; // the number of minterms + DdNode * bTempV; + DdNode * bVarTop; + int fBreak; + + + // there is no need to search above this level + if ( Level > s_MaxDepth ) + return; + + // if there are no variables left, quit the research + if ( bVarsCol == b1 ) + return; + + if ( s_BackTracks > s_BackTrackLimit ) + return; + + s_BackTracks++; + + // otherwise, go through the remaining variables + for ( bTempV = bVarsCol; bTempV != b1; bTempV = cuddT(bTempV) ) + { + // the currently tested variable + bVarTop = dd->vars[bTempV->index]; + + // put it into the array + s_VarOrderCur[Level-1] = bTempV->index; + + // go through the entries and fill them out by cofactoring + fBreak = 0; + for ( i = 0; i < nEntries; i++ ) + { + bVars0 = ComputeVarSetAndCountMinterms( dd, s_Field[Level-1][i], Cudd_Not(bVarTop), &nMint0 ); + Cudd_Ref( bVars0 ); + + if ( nMint0 > Extra_Power2( nMulti-1 ) ) + { + // there is no way to encode - dereference and return + Cudd_RecursiveDeref( dd, bVars0 ); + fBreak = 1; + break; + } + + bVars1 = ComputeVarSetAndCountMinterms( dd, s_Field[Level-1][i], bVarTop, &nMint1 ); + Cudd_Ref( bVars1 ); + + if ( nMint1 > Extra_Power2( nMulti-1 ) ) + { + // there is no way to encode - dereference and return + Cudd_RecursiveDeref( dd, bVars0 ); + Cudd_RecursiveDeref( dd, bVars1 ); + fBreak = 1; + break; + } + + // otherwise, add these two cofactors + s_Field[Level][2*i + 0] = bVars0; // takes ref + s_Field[Level][2*i + 1] = bVars1; // takes ref + } + + if ( !fBreak ) + { + DdNode * bVarsRem; + // if we ended up here, it means that the cofactors w.r.t. variable bVarTop satisfy the condition + // save this situation + if ( s_nVarsBest < Level ) + { + s_nVarsBest = Level; + // copy the variable assignment + for ( k = 0; k < Level; k++ ) + s_VarOrderBest[k] = s_VarOrderCur[k]; + } + + // call recursively + // get the new variable set + if ( nMulti-1 > 0 ) + { + bVarsRem = Cudd_bddExistAbstract( dd, bVarsCol, bVarTop ); Cudd_Ref( bVarsRem ); + EvaluateEncodings_rec( dd, bVarsRem, nVarsCol-1, nMulti-1, Level+1 ); + Cudd_RecursiveDeref( dd, bVarsRem ); + } + } + + // deref the contents of the array + for ( k = 0; k < i; k++ ) + { + Cudd_RecursiveDeref( dd, s_Field[Level][2*k + 0] ); + Cudd_RecursiveDeref( dd, s_Field[Level][2*k + 1] ); + } + + // if the solution is found, there is no need to continue + if ( s_nVarsBest == s_MaxDepth ) + return; + + // if the solution is found, there is no need to continue + if ( s_nVarsBest == s_MultiStart ) + return; + } + // at this point, we have tried all possible directions in the space of variables +} + +/**Function******************************************************************** + + Synopsis [Computes the current set of variables and counts the number of minterms.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * ComputeVarSetAndCountMinterms( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost ) +// takes bVars - the variables cofactored so far (some of them may be in negative polarity) +// bVarTop - the topmost variable w.r.t. which to cofactor (may be in negative polarity) +// returns the cost and the new set of variables (bVars & bVarTop) +{ + DdNode * bVarsRes; + + // get the resulting set of variables + bVarsRes = Cudd_bddAnd( dd, bVars, bVarTop ); Cudd_Ref( bVarsRes ); + + // increment signature before calling Cudd_CountCofactorMinterms() + s_Signature++; + *Cost = Extra_CountCofactorMinterms( dd, s_Encoded, bVarsRes, s_VarAll ); + + Cudd_Deref( bVarsRes ); +// s_CountCalls++; + return bVarsRes; +} + +/**Function******************************************************************** + + Synopsis [Computes the current set of variables and counts the number of minterms.] + + Description [The old implementation, which is approximately 4 times slower.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * ComputeVarSetAndCountMinterms2( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost ) +{ + DdNode * bVarsRes; + DdNode * bCof, * bFun; + + bVarsRes = Cudd_bddAnd( dd, bVars, bVarTop ); Cudd_Ref( bVarsRes ); + + bCof = Cudd_Cofactor( dd, s_Encoded, bVarsRes ); Cudd_Ref( bCof ); + bFun = Cudd_bddExistAbstract( dd, bCof, s_VarAll ); Cudd_Ref( bFun ); + *Cost = (unsigned)Cudd_CountMinterm( dd, bFun, s_MultiStart ); + Cudd_RecursiveDeref( dd, bFun ); + Cudd_RecursiveDeref( dd, bCof ); + + Cudd_Deref( bVarsRes ); +// s_CountCalls++; + return bVarsRes; +} + + +/**Function******************************************************************** + + Synopsis [Counts the number of encoding minterms pointed to by the cofactor of the function.] + + Description [] + + SideEffects [None] + +******************************************************************************/ +unsigned Extra_CountCofactorMinterms( DdManager * dd, DdNode * bFunc, DdNode * bVarsCof, DdNode * bVarsAll ) +// this function computes how many minterms depending on the encoding variables +// are there in the cofactor of bFunc w.r.t. variables bVarsCof +// bFunc is assumed to depend on variables s_VarsAll +// the variables s_VarsAll should be ordered above the encoding variables +{ + unsigned HKey; + DdNode * bFuncR; + + // if the function is zero, there are no minterms +// if ( bFunc == b0 ) +// return 0; + +// if ( st__lookup(Visited, (char*)bFunc, NULL) ) +// return 0; + +// HKey = hashKey2c( s_Signature, bFuncR ); +// if ( HHTable1[HKey].Sign == s_Signature && HHTable1[HKey].Arg1 == bFuncR ) // this node is visited +// return 0; + + + // check the hash-table + bFuncR = Cudd_Regular(bFunc); +// HKey = hashKey2( s_Signature, bFuncR, _TABLESIZE_COF ); + HKey = hashKey2( s_Signature, bFunc, _TABLESIZE_COF ); + for ( ; HHTable1[HKey].Sign == s_Signature; HKey = (HKey+1) % _TABLESIZE_COF ) +// if ( HHTable1[HKey].Arg1 == bFuncR ) // this node is visited + if ( HHTable1[HKey].Arg1 == bFunc ) // this node is visited + return 0; + + + // if the function is already the code + if ( dd->perm[bFuncR->index] >= s_EncodingVarsLevel ) + { +// st__insert(Visited, (char*)bFunc, NULL); + +// HHTable1[HKey].Sign = s_Signature; +// HHTable1[HKey].Arg1 = bFuncR; + + assert( HHTable1[HKey].Sign != s_Signature ); + HHTable1[HKey].Sign = s_Signature; +// HHTable1[HKey].Arg1 = bFuncR; + HHTable1[HKey].Arg1 = bFunc; + + return Extra_CountMintermsSimple( bFunc, (1<perm[bFuncR->index]; + int LevelC = cuddI(dd,bVarsCofR->index); + int LevelA = dd->perm[bVarsAll->index]; + + int LevelTop = LevelF; + + if ( LevelTop > LevelC ) + LevelTop = LevelC; + + if ( LevelTop > LevelA ) + LevelTop = LevelA; + + // the top var in the function or in cofactoring vars always belongs to the set of all vars + assert( !( LevelTop == LevelF || LevelTop == LevelC ) || LevelTop == LevelA ); + + // cofactor the function + if ( LevelTop == LevelF ) + { + if ( bFuncR != bFunc ) // bFunc is complemented + { + bFunc0 = Cudd_Not( cuddE(bFuncR) ); + bFunc1 = Cudd_Not( cuddT(bFuncR) ); + } + else + { + bFunc0 = cuddE(bFuncR); + bFunc1 = cuddT(bFuncR); + } + } + else // bVars is higher in the variable order + bFunc0 = bFunc1 = bFunc; + + // cofactor the cube + if ( LevelTop == LevelC ) + { + if ( bVarsCofR != bVarsCof ) // bFunc is complemented + { + bVarsCof0 = Cudd_Not( cuddE(bVarsCofR) ); + bVarsCof1 = Cudd_Not( cuddT(bVarsCofR) ); + } + else + { + bVarsCof0 = cuddE(bVarsCofR); + bVarsCof1 = cuddT(bVarsCofR); + } + } + else // bVars is higher in the variable order + bVarsCof0 = bVarsCof1 = bVarsCof; + + // there are two cases: + // (1) the top variable belongs to the cofactoring variables + // (2) the top variable does not belong to the cofactoring variables + + // (1) the top variable belongs to the cofactoring variables + Res = 0; + if ( LevelTop == LevelC ) + { + if ( bVarsCof1 == b0 ) // this is a negative cofactor + { + if ( bFunc0 != b0 ) + Res = Extra_CountCofactorMinterms( dd, bFunc0, bVarsCof0, cuddT(bVarsAll) ); + } + else // this is a positive cofactor + { + if ( bFunc1 != b0 ) + Res = Extra_CountCofactorMinterms( dd, bFunc1, bVarsCof1, cuddT(bVarsAll) ); + } + } + else + { + if ( bFunc0 != b0 ) + Res += Extra_CountCofactorMinterms( dd, bFunc0, bVarsCof0, cuddT(bVarsAll) ); + + if ( bFunc1 != b0 ) + Res += Extra_CountCofactorMinterms( dd, bFunc1, bVarsCof1, cuddT(bVarsAll) ); + } + +// st__insert(Visited, (char*)bFunc, NULL); + +// HHTable1[HKey].Sign = s_Signature; +// HHTable1[HKey].Arg1 = bFuncR; + + // skip through the entries with the same signatures + // (these might have been created at the time of recursive calls) + for ( ; HHTable1[HKey].Sign == s_Signature; HKey = (HKey+1) % _TABLESIZE_COF ); + assert( HHTable1[HKey].Sign != s_Signature ); + HHTable1[HKey].Sign = s_Signature; +// HHTable1[HKey].Arg1 = bFuncR; + HHTable1[HKey].Arg1 = bFunc; + + return Res; + } +} + +/**Function******************************************************************** + + Synopsis [Counts the number of minterms.] + + Description [This function counts minterms for functions up to 32 variables + using a local cache. The terminal value (s_Termina) should be adjusted for + BDDs and ADDs.] + + SideEffects [None] + +******************************************************************************/ +unsigned Extra_CountMintermsSimple( DdNode * bFunc, unsigned max ) +{ + unsigned HKey; + + // normalize + if ( Cudd_IsComplement(bFunc) ) + return max - Extra_CountMintermsSimple( Cudd_Not(bFunc), max ); + + // now it is known that the function is not complemented + if ( cuddIsConstant(bFunc) ) + return ((bFunc==s_Terminal)? 0: max); + + // check cache + HKey = hashKey2( bFunc, max, _TABLESIZE_MINT ); + if ( HHTable2[HKey].Arg1 == bFunc && HHTable2[HKey].Arg2 == max ) + return HHTable2[HKey].Res; + else + { + // min = min0/2 + min1/2; + unsigned min = (Extra_CountMintermsSimple( cuddE(bFunc), max ) >> 1) + + (Extra_CountMintermsSimple( cuddT(bFunc), max ) >> 1); + + HHTable2[HKey].Arg1 = bFunc; + HHTable2[HKey].Arg2 = max; + HHTable2[HKey].Res = min; + + return min; + } +} /* end of Extra_CountMintermsSimple */ + + +/**Function******************************************************************** + + Synopsis [Visits the nodes.] + + Description [Visits the nodes above the cut and the nodes pointed to below the cut; + collects the visited nodes, counts how many times each node is visited, and sets + the path-sum to be the constant zero BDD.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void CountNodeVisits_rec( DdManager * dd, DdNode * aFunc, st__table * Visited ) + +{ + traventry * p; + char **slot; + if ( st__find_or_add(Visited, (char*)aFunc, &slot) ) + { // the entry already exists + p = (traventry*) *slot; + // increment the counter of incoming edges + p->nEdges++; + return; + } + // this node has not been visited + assert( !Cudd_IsComplement(aFunc) ); + + // create the new traversal entry + p = (traventry *) ABC_ALLOC( char, sizeof(traventry) ); + // set the initial sum of edges to zero BDD + p->bSum = b0; Cudd_Ref( b0 ); + // set the starting number of incoming edges + p->nEdges = 1; + // set this entry into the slot + *slot = (char*)p; + + // recur if the node is above the cut + if ( cuddI(dd,aFunc->index) < s_CutLevel ) + { + CountNodeVisits_rec( dd, cuddE(aFunc), Visited ); + CountNodeVisits_rec( dd, cuddT(aFunc), Visited ); + } +} /* end of CountNodeVisits_rec */ + + +/**Function******************************************************************** + + Synopsis [Revisits the nodes and computes the paths.] + + Description [This function visits the nodes above the cut having the goal of + summing all the incomming BDD edges; when this function comes across the node + below the cut, it saves this node in the CutNode table.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void CollectNodesAndComputePaths_rec( DdManager * dd, DdNode * aFunc, DdNode * bCube, st__table * Visited, st__table * CutNodes ) +{ + // find the node in the visited table + DdNode * bTemp; + traventry * p; + char **slot; + if ( st__find_or_add(Visited, (char*)aFunc, &slot) ) + { // the node is found + // get the pointer to the traversal entry + p = (traventry*) *slot; + + // make sure that the counter of incoming edges is positive + assert( p->nEdges > 0 ); + + // add the cube to the currently accumulated cubes + p->bSum = Cudd_bddOr( dd, bTemp = p->bSum, bCube ); Cudd_Ref( p->bSum ); + Cudd_RecursiveDeref( dd, bTemp ); + + // decrement the number of visits + p->nEdges--; + + // if more visits to this node are expected, return + if ( p->nEdges ) + return; + else // if ( p->nEdges == 0 ) + { // this is the last visit - propagate the cube + + // check where this node is + if ( cuddI(dd,aFunc->index) < s_CutLevel ) + { // the node is above the cut + DdNode * bCube0, * bCube1; + + // get the top-most variable + DdNode * bVarTop = dd->vars[aFunc->index]; + + // compute the propagated cubes + bCube0 = Cudd_bddAnd( dd, p->bSum, Cudd_Not( bVarTop ) ); Cudd_Ref( bCube0 ); + bCube1 = Cudd_bddAnd( dd, p->bSum, bVarTop ); Cudd_Ref( bCube1 ); + + // call recursively + CollectNodesAndComputePaths_rec( dd, cuddE(aFunc), bCube0, Visited, CutNodes ); + CollectNodesAndComputePaths_rec( dd, cuddT(aFunc), bCube1, Visited, CutNodes ); + + // dereference the cubes + Cudd_RecursiveDeref( dd, bCube0 ); + Cudd_RecursiveDeref( dd, bCube1 ); + return; + } + else + { // the node is below the cut + // add this node to the cut node table, if it is not yet there + +// DdNode * bNode; +// bNode = Cudd_addBddPattern( dd, aFunc ); Cudd_Ref( bNode ); + if ( st__find_or_add(CutNodes, (char*)aFunc, &slot) ) + { // the node exists - should never happen + assert( 0 ); + } + *slot = (char*) p->bSum; Cudd_Ref( p->bSum ); + // the table takes the reference of bNode + return; + } + } + } + + // the node does not exist in the visited table - should never happen + assert(0); + +} /* end of CollectNodesAndComputePaths_rec */ + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/extrab/extraBddImage.c b/src/bdd/extrab/extraBddImage.c new file mode 100644 index 00000000..46afb4f2 --- /dev/null +++ b/src/bdd/extrab/extraBddImage.c @@ -0,0 +1,1162 @@ +/**CFile**************************************************************** + + FileName [extraBddImage.c] + + PackageName [extra] + + Synopsis [Various reusable software utilities.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 1, 2003.] + + Revision [$Id: extraBddImage.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "extraBdd.h" + +ABC_NAMESPACE_IMPL_START + + +/* + The ideas implemented in this file are inspired by the paper: + Pankaj Chauhan, Edmund Clarke, Somesh Jha, Jim Kukula, Tom Shiple, + Helmut Veith, Dong Wang. Non-linear Quantification Scheduling in + Image Computation. ICCAD, 2001. +*/ + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +typedef struct Extra_ImageNode_t_ Extra_ImageNode_t; +typedef struct Extra_ImagePart_t_ Extra_ImagePart_t; +typedef struct Extra_ImageVar_t_ Extra_ImageVar_t; + +struct Extra_ImageTree_t_ +{ + Extra_ImageNode_t * pRoot; // the root of quantification tree + Extra_ImageNode_t * pCare; // the leaf node with the care set + DdNode * bCareSupp; // the cube to quantify from the care + int fVerbose; // the verbosity flag + int nNodesMax; // the max number of nodes in one iter + int nNodesMaxT; // the overall max number of nodes + int nIter; // the number of iterations with this tree +}; + +struct Extra_ImageNode_t_ +{ + DdManager * dd; // the manager + DdNode * bCube; // the cube to quantify + DdNode * bImage; // the partial image + Extra_ImageNode_t * pNode1; // the first branch + Extra_ImageNode_t * pNode2; // the second branch + Extra_ImagePart_t * pPart; // the partition (temporary) +}; + +struct Extra_ImagePart_t_ +{ + DdNode * bFunc; // the partition + DdNode * bSupp; // the support of this partition + int nNodes; // the number of BDD nodes + short nSupp; // the number of support variables + short iPart; // the number of this partition +}; + +struct Extra_ImageVar_t_ +{ + int iNum; // the BDD index of this variable + DdNode * bParts; // the partition numbers + int nParts; // the number of partitions +}; + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static Extra_ImagePart_t ** Extra_CreateParts( DdManager * dd, + int nParts, DdNode ** pbParts, DdNode * bCare ); +static Extra_ImageVar_t ** Extra_CreateVars( DdManager * dd, + int nParts, Extra_ImagePart_t ** pParts, + int nVars, DdNode ** pbVarsNs ); +static Extra_ImageNode_t ** Extra_CreateNodes( DdManager * dd, + int nParts, Extra_ImagePart_t ** pParts, + int nVars, Extra_ImageVar_t ** pVars ); +static void Extra_DeleteParts_rec( Extra_ImageNode_t * pNode ); +static int Extra_BuildTreeNode( DdManager * dd, + int nNodes, Extra_ImageNode_t ** pNodes, + int nVars, Extra_ImageVar_t ** pVars ); +static Extra_ImageNode_t * Extra_MergeTopNodes( DdManager * dd, + int nNodes, Extra_ImageNode_t ** pNodes ); +static void Extra_bddImageTreeDelete_rec( Extra_ImageNode_t * pNode ); +static void Extra_bddImageCompute_rec( Extra_ImageTree_t * pTree, Extra_ImageNode_t * pNode ); +static int Extra_FindBestVariable( DdManager * dd, + int nNodes, Extra_ImageNode_t ** pNodes, + int nVars, Extra_ImageVar_t ** pVars ); +static void Extra_FindBestPartitions( DdManager * dd, DdNode * bParts, + int nNodes, Extra_ImageNode_t ** pNodes, + int * piNode1, int * piNode2 ); +static Extra_ImageNode_t * Extra_CombineTwoNodes( DdManager * dd, DdNode * bCube, + Extra_ImageNode_t * pNode1, Extra_ImageNode_t * pNode2 ); + +static void Extra_bddImagePrintLatchDependency( DdManager * dd, DdNode * bCare, + int nParts, DdNode ** pbParts, + int nVars, DdNode ** pbVars ); +static void Extra_bddImagePrintLatchDependencyOne( DdManager * dd, DdNode * bFunc, + DdNode * bVarsCs, DdNode * bVarsNs, int iPart ); + +static void Extra_bddImagePrintTree( Extra_ImageTree_t * pTree ); +static void Extra_bddImagePrintTree_rec( Extra_ImageNode_t * pNode, int nOffset ); + + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function************************************************************* + + Synopsis [Starts the image computation using tree-based scheduling.] + + Description [This procedure starts the image computation. It uses + the given care set to test-run the image computation and creates the + quantification tree by scheduling variable quantifications. The tree can + be used to compute images for other care sets without rescheduling. + In this case, Extra_bddImageCompute() should be called.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Extra_ImageTree_t * Extra_bddImageStart( + DdManager * dd, DdNode * bCare, // the care set + int nParts, DdNode ** pbParts, // the partitions for image computation + int nVars, DdNode ** pbVars, int fVerbose ) // the NS and parameter variables (not quantified!) +{ + Extra_ImageTree_t * pTree; + Extra_ImagePart_t ** pParts; + Extra_ImageVar_t ** pVars; + Extra_ImageNode_t ** pNodes; + int v; + + if ( fVerbose && dd->size <= 80 ) + Extra_bddImagePrintLatchDependency( dd, bCare, nParts, pbParts, nVars, pbVars ); + + // create variables, partitions and leaf nodes + pParts = Extra_CreateParts( dd, nParts, pbParts, bCare ); + pVars = Extra_CreateVars( dd, nParts + 1, pParts, nVars, pbVars ); + pNodes = Extra_CreateNodes( dd, nParts + 1, pParts, dd->size, pVars ); + + // create the tree + pTree = ABC_ALLOC( Extra_ImageTree_t, 1 ); + memset( pTree, 0, sizeof(Extra_ImageTree_t) ); + pTree->pCare = pNodes[nParts]; + pTree->fVerbose = fVerbose; + + // process the nodes + while ( Extra_BuildTreeNode( dd, nParts + 1, pNodes, dd->size, pVars ) ); + + // make sure the variables are gone + for ( v = 0; v < dd->size; v++ ) + assert( pVars[v] == NULL ); + ABC_FREE( pVars ); + + // merge the topmost nodes + while ( (pTree->pRoot = Extra_MergeTopNodes( dd, nParts + 1, pNodes )) == NULL ); + + // make sure the nodes are gone + for ( v = 0; v < nParts + 1; v++ ) + assert( pNodes[v] == NULL ); + ABC_FREE( pNodes ); + +// if ( fVerbose ) +// Extra_bddImagePrintTree( pTree ); + + // set the support of the care set + pTree->bCareSupp = Cudd_Support( dd, bCare ); Cudd_Ref( pTree->bCareSupp ); + + // clean the partitions + Extra_DeleteParts_rec( pTree->pRoot ); + ABC_FREE( pParts ); + return pTree; +} + +/**Function************************************************************* + + Synopsis [Compute the image.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddImageCompute( Extra_ImageTree_t * pTree, DdNode * bCare ) +{ + DdManager * dd = pTree->pCare->dd; + DdNode * bSupp, * bRem; + + pTree->nIter++; + + // make sure the supports are okay + bSupp = Cudd_Support( dd, bCare ); Cudd_Ref( bSupp ); + if ( bSupp != pTree->bCareSupp ) + { + bRem = Cudd_bddExistAbstract( dd, bSupp, pTree->bCareSupp ); Cudd_Ref( bRem ); + if ( bRem != b1 ) + { +printf( "Original care set support: " ); +ABC_PRB( dd, pTree->bCareSupp ); +printf( "Current care set support: " ); +ABC_PRB( dd, bSupp ); + Cudd_RecursiveDeref( dd, bSupp ); + Cudd_RecursiveDeref( dd, bRem ); + printf( "The care set depends on some vars that were not in the care set during scheduling.\n" ); + return NULL; + } + Cudd_RecursiveDeref( dd, bRem ); + } + Cudd_RecursiveDeref( dd, bSupp ); + + // remove the previous image + Cudd_RecursiveDeref( dd, pTree->pCare->bImage ); + pTree->pCare->bImage = bCare; Cudd_Ref( bCare ); + + // compute the image + pTree->nNodesMax = 0; + Extra_bddImageCompute_rec( pTree, pTree->pRoot ); + if ( pTree->nNodesMaxT < pTree->nNodesMax ) + pTree->nNodesMaxT = pTree->nNodesMax; + +// if ( pTree->fVerbose ) +// printf( "Iter %2d : Max nodes = %5d.\n", pTree->nIter, pTree->nNodesMax ); + return pTree->pRoot->bImage; +} + +/**Function************************************************************* + + Synopsis [Delete the tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_bddImageTreeDelete( Extra_ImageTree_t * pTree ) +{ + if ( pTree->bCareSupp ) + Cudd_RecursiveDeref( pTree->pRoot->dd, pTree->bCareSupp ); + Extra_bddImageTreeDelete_rec( pTree->pRoot ); + ABC_FREE( pTree ); +} + +/**Function************************************************************* + + Synopsis [Reads the image from the tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddImageRead( Extra_ImageTree_t * pTree ) +{ + return pTree->pRoot->bImage; +} + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of static Functions */ +/*---------------------------------------------------------------------------*/ + +/**Function************************************************************* + + Synopsis [Creates partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Extra_ImagePart_t ** Extra_CreateParts( DdManager * dd, + int nParts, DdNode ** pbParts, DdNode * bCare ) +{ + Extra_ImagePart_t ** pParts; + int i; + + // start the partitions + pParts = ABC_ALLOC( Extra_ImagePart_t *, nParts + 1 ); + // create structures for each variable + for ( i = 0; i < nParts; i++ ) + { + pParts[i] = ABC_ALLOC( Extra_ImagePart_t, 1 ); + pParts[i]->bFunc = pbParts[i]; Cudd_Ref( pParts[i]->bFunc ); + pParts[i]->bSupp = Cudd_Support( dd, pParts[i]->bFunc ); Cudd_Ref( pParts[i]->bSupp ); + pParts[i]->nSupp = Extra_bddSuppSize( dd, pParts[i]->bSupp ); + pParts[i]->nNodes = Cudd_DagSize( pParts[i]->bFunc ); + pParts[i]->iPart = i; + } + // add the care set as the last partition + pParts[nParts] = ABC_ALLOC( Extra_ImagePart_t, 1 ); + pParts[nParts]->bFunc = bCare; Cudd_Ref( pParts[nParts]->bFunc ); + pParts[nParts]->bSupp = Cudd_Support( dd, pParts[nParts]->bFunc ); Cudd_Ref( pParts[nParts]->bSupp ); + pParts[nParts]->nSupp = Extra_bddSuppSize( dd, pParts[nParts]->bSupp ); + pParts[nParts]->nNodes = Cudd_DagSize( pParts[nParts]->bFunc ); + pParts[nParts]->iPart = nParts; + return pParts; +} + +/**Function************************************************************* + + Synopsis [Creates variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Extra_ImageVar_t ** Extra_CreateVars( DdManager * dd, + int nParts, Extra_ImagePart_t ** pParts, + int nVars, DdNode ** pbVars ) +{ + Extra_ImageVar_t ** pVars; + DdNode ** pbFuncs; + DdNode * bCubeNs, * bSupp, * bParts, * bTemp, * bSuppTemp; + int nVarsTotal, iVar, p, Counter; + + // put all the functions into one array + pbFuncs = ABC_ALLOC( DdNode *, nParts ); + for ( p = 0; p < nParts; p++ ) + pbFuncs[p] = pParts[p]->bSupp; + bSupp = Cudd_VectorSupport( dd, pbFuncs, nParts ); Cudd_Ref( bSupp ); + ABC_FREE( pbFuncs ); + + // remove the NS vars + bCubeNs = Cudd_bddComputeCube( dd, pbVars, NULL, nVars ); Cudd_Ref( bCubeNs ); + bSupp = Cudd_bddExistAbstract( dd, bTemp = bSupp, bCubeNs ); Cudd_Ref( bSupp ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCubeNs ); + + // get the number of I and CS variables to be quantified + nVarsTotal = Extra_bddSuppSize( dd, bSupp ); + + // start the variables + pVars = ABC_ALLOC( Extra_ImageVar_t *, dd->size ); + memset( pVars, 0, sizeof(Extra_ImageVar_t *) * dd->size ); + // create structures for each variable + for ( bSuppTemp = bSupp; bSuppTemp != b1; bSuppTemp = cuddT(bSuppTemp) ) + { + iVar = bSuppTemp->index; + pVars[iVar] = ABC_ALLOC( Extra_ImageVar_t, 1 ); + pVars[iVar]->iNum = iVar; + // collect all the parts this var belongs to + Counter = 0; + bParts = b1; Cudd_Ref( bParts ); + for ( p = 0; p < nParts; p++ ) + if ( Cudd_bddLeq( dd, pParts[p]->bSupp, dd->vars[bSuppTemp->index] ) ) + { + bParts = Cudd_bddAnd( dd, bTemp = bParts, dd->vars[p] ); Cudd_Ref( bParts ); + Cudd_RecursiveDeref( dd, bTemp ); + Counter++; + } + pVars[iVar]->bParts = bParts; // takes ref + pVars[iVar]->nParts = Counter; + } + Cudd_RecursiveDeref( dd, bSupp ); + return pVars; +} + +/**Function************************************************************* + + Synopsis [Creates variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Extra_ImageNode_t ** Extra_CreateNodes( DdManager * dd, + int nParts, Extra_ImagePart_t ** pParts, + int nVars, Extra_ImageVar_t ** pVars ) +{ + Extra_ImageNode_t ** pNodes; + Extra_ImageNode_t * pNode; + DdNode * bTemp; + int i, v, iPart; +/* + DdManager * dd; // the manager + DdNode * bCube; // the cube to quantify + DdNode * bImage; // the partial image + Extra_ImageNode_t * pNode1; // the first branch + Extra_ImageNode_t * pNode2; // the second branch + Extra_ImagePart_t * pPart; // the partition (temporary) +*/ + // start the partitions + pNodes = ABC_ALLOC( Extra_ImageNode_t *, nParts ); + // create structures for each leaf nodes + for ( i = 0; i < nParts; i++ ) + { + pNodes[i] = ABC_ALLOC( Extra_ImageNode_t, 1 ); + memset( pNodes[i], 0, sizeof(Extra_ImageNode_t) ); + pNodes[i]->dd = dd; + pNodes[i]->pPart = pParts[i]; + } + // find the quantification cubes for each leaf node + for ( v = 0; v < nVars; v++ ) + { + if ( pVars[v] == NULL ) + continue; + assert( pVars[v]->nParts > 0 ); + if ( pVars[v]->nParts > 1 ) + continue; + iPart = pVars[v]->bParts->index; + if ( pNodes[iPart]->bCube == NULL ) + { + pNodes[iPart]->bCube = dd->vars[v]; + Cudd_Ref( dd->vars[v] ); + } + else + { + pNodes[iPart]->bCube = Cudd_bddAnd( dd, bTemp = pNodes[iPart]->bCube, dd->vars[v] ); + Cudd_Ref( pNodes[iPart]->bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + } + // remove these variables + Cudd_RecursiveDeref( dd, pVars[v]->bParts ); + ABC_FREE( pVars[v] ); + } + + // assign the leaf node images + for ( i = 0; i < nParts; i++ ) + { + pNode = pNodes[i]; + if ( pNode->bCube ) + { + // update the partition + pParts[i]->bFunc = Cudd_bddExistAbstract( dd, bTemp = pParts[i]->bFunc, pNode->bCube ); + Cudd_Ref( pParts[i]->bFunc ); + Cudd_RecursiveDeref( dd, bTemp ); + // update the support the partition + pParts[i]->bSupp = Cudd_bddExistAbstract( dd, bTemp = pParts[i]->bSupp, pNode->bCube ); + Cudd_Ref( pParts[i]->bSupp ); + Cudd_RecursiveDeref( dd, bTemp ); + // update the numbers + pParts[i]->nSupp = Extra_bddSuppSize( dd, pParts[i]->bSupp ); + pParts[i]->nNodes = Cudd_DagSize( pParts[i]->bFunc ); + // get rid of the cube + // save the last (care set) quantification cube + if ( i < nParts - 1 ) + { + Cudd_RecursiveDeref( dd, pNode->bCube ); + pNode->bCube = NULL; + } + } + // copy the function + pNode->bImage = pParts[i]->bFunc; Cudd_Ref( pNode->bImage ); + } +/* + for ( i = 0; i < nParts; i++ ) + { + pNode = pNodes[i]; +ABC_PRB( dd, pNode->bCube ); +ABC_PRB( dd, pNode->pPart->bFunc ); +ABC_PRB( dd, pNode->pPart->bSupp ); +printf( "\n" ); + } +*/ + return pNodes; +} + + +/**Function************************************************************* + + Synopsis [Delete the partitions from the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_DeleteParts_rec( Extra_ImageNode_t * pNode ) +{ + Extra_ImagePart_t * pPart; + if ( pNode->pNode1 ) + Extra_DeleteParts_rec( pNode->pNode1 ); + if ( pNode->pNode2 ) + Extra_DeleteParts_rec( pNode->pNode2 ); + pPart = pNode->pPart; + Cudd_RecursiveDeref( pNode->dd, pPart->bFunc ); + Cudd_RecursiveDeref( pNode->dd, pPart->bSupp ); + ABC_FREE( pNode->pPart ); +} + +/**Function************************************************************* + + Synopsis [Delete the partitions from the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_bddImageTreeDelete_rec( Extra_ImageNode_t * pNode ) +{ + if ( pNode->pNode1 ) + Extra_bddImageTreeDelete_rec( pNode->pNode1 ); + if ( pNode->pNode2 ) + Extra_bddImageTreeDelete_rec( pNode->pNode2 ); + if ( pNode->bCube ) + Cudd_RecursiveDeref( pNode->dd, pNode->bCube ); + if ( pNode->bImage ) + Cudd_RecursiveDeref( pNode->dd, pNode->bImage ); + assert( pNode->pPart == NULL ); + ABC_FREE( pNode ); +} + +/**Function************************************************************* + + Synopsis [Recompute the image.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_bddImageCompute_rec( Extra_ImageTree_t * pTree, Extra_ImageNode_t * pNode ) +{ + DdManager * dd = pNode->dd; + DdNode * bTemp; + int nNodes; + + // trivial case + if ( pNode->pNode1 == NULL ) + { + if ( pNode->bCube ) + { + pNode->bImage = Cudd_bddExistAbstract( dd, bTemp = pNode->bImage, pNode->bCube ); + Cudd_Ref( pNode->bImage ); + Cudd_RecursiveDeref( dd, bTemp ); + } + return; + } + + // compute the children + if ( pNode->pNode1 ) + Extra_bddImageCompute_rec( pTree, pNode->pNode1 ); + if ( pNode->pNode2 ) + Extra_bddImageCompute_rec( pTree, pNode->pNode2 ); + + // clean the old image + if ( pNode->bImage ) + Cudd_RecursiveDeref( dd, pNode->bImage ); + pNode->bImage = NULL; + + // compute the new image + if ( pNode->bCube ) + pNode->bImage = Cudd_bddAndAbstract( dd, + pNode->pNode1->bImage, pNode->pNode2->bImage, pNode->bCube ); + else + pNode->bImage = Cudd_bddAnd( dd, pNode->pNode1->bImage, pNode->pNode2->bImage ); + Cudd_Ref( pNode->bImage ); + + if ( pTree->fVerbose ) + { + nNodes = Cudd_DagSize( pNode->bImage ); + if ( pTree->nNodesMax < nNodes ) + pTree->nNodesMax = nNodes; + } +} + +/**Function************************************************************* + + Synopsis [Builds the tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_BuildTreeNode( DdManager * dd, + int nNodes, Extra_ImageNode_t ** pNodes, + int nVars, Extra_ImageVar_t ** pVars ) +{ + Extra_ImageNode_t * pNode1, * pNode2; + Extra_ImageVar_t * pVar; + Extra_ImageNode_t * pNode; + DdNode * bCube, * bTemp, * bSuppTemp, * bParts; + int iNode1, iNode2; + int iVarBest, nSupp, v; + + // find the best variable + iVarBest = Extra_FindBestVariable( dd, nNodes, pNodes, nVars, pVars ); + if ( iVarBest == -1 ) + return 0; + + pVar = pVars[iVarBest]; + + // this var cannot appear in one partition only + nSupp = Extra_bddSuppSize( dd, pVar->bParts ); + assert( nSupp == pVar->nParts ); + assert( nSupp != 1 ); + + // if it appears in only two partitions, quantify it + if ( pVar->nParts == 2 ) + { + // get the nodes + iNode1 = pVar->bParts->index; + iNode2 = cuddT(pVar->bParts)->index; + pNode1 = pNodes[iNode1]; + pNode2 = pNodes[iNode2]; + + // get the quantification cube + bCube = dd->vars[pVar->iNum]; Cudd_Ref( bCube ); + // add the variables that appear only in these partitions + for ( v = 0; v < nVars; v++ ) + if ( pVars[v] && v != iVarBest && pVars[v]->bParts == pVars[iVarBest]->bParts ) + { + // add this var + bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[pVars[v]->iNum] ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + // clean this var + Cudd_RecursiveDeref( dd, pVars[v]->bParts ); + ABC_FREE( pVars[v] ); + } + // clean the best var + Cudd_RecursiveDeref( dd, pVars[iVarBest]->bParts ); + ABC_FREE( pVars[iVarBest] ); + + // combines two nodes + pNode = Extra_CombineTwoNodes( dd, bCube, pNode1, pNode2 ); + Cudd_RecursiveDeref( dd, bCube ); + } + else // if ( pVar->nParts > 2 ) + { + // find two smallest BDDs that have this var + Extra_FindBestPartitions( dd, pVar->bParts, nNodes, pNodes, &iNode1, &iNode2 ); + pNode1 = pNodes[iNode1]; + pNode2 = pNodes[iNode2]; + + // it is not possible that a var appears only in these two + // otherwise, it would have a different cost + bParts = Cudd_bddAnd( dd, dd->vars[iNode1], dd->vars[iNode2] ); Cudd_Ref( bParts ); + for ( v = 0; v < nVars; v++ ) + if ( pVars[v] && pVars[v]->bParts == bParts ) + assert( 0 ); + Cudd_RecursiveDeref( dd, bParts ); + + // combines two nodes + pNode = Extra_CombineTwoNodes( dd, b1, pNode1, pNode2 ); + } + + // clean the old nodes + pNodes[iNode1] = pNode; + pNodes[iNode2] = NULL; + + // update the variables that appear in pNode[iNode2] + for ( bSuppTemp = pNode2->pPart->bSupp; bSuppTemp != b1; bSuppTemp = cuddT(bSuppTemp) ) + { + pVar = pVars[bSuppTemp->index]; + if ( pVar == NULL ) // this variable is not be quantified + continue; + // quantify this var + assert( Cudd_bddLeq( dd, pVar->bParts, dd->vars[iNode2] ) ); + pVar->bParts = Cudd_bddExistAbstract( dd, bTemp = pVar->bParts, dd->vars[iNode2] ); Cudd_Ref( pVar->bParts ); + Cudd_RecursiveDeref( dd, bTemp ); + // add the new var + pVar->bParts = Cudd_bddAnd( dd, bTemp = pVar->bParts, dd->vars[iNode1] ); Cudd_Ref( pVar->bParts ); + Cudd_RecursiveDeref( dd, bTemp ); + // update the score + pVar->nParts = Extra_bddSuppSize( dd, pVar->bParts ); + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Merges the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Extra_ImageNode_t * Extra_MergeTopNodes( + DdManager * dd, int nNodes, Extra_ImageNode_t ** pNodes ) +{ + Extra_ImageNode_t * pNode; + int n1 = -1, n2 = -1, n; + + // find the first and the second non-empty spots + for ( n = 0; n < nNodes; n++ ) + if ( pNodes[n] ) + { + if ( n1 == -1 ) + n1 = n; + else if ( n2 == -1 ) + { + n2 = n; + break; + } + } + assert( n1 != -1 ); + // check the situation when only one such node is detected + if ( n2 == -1 ) + { + // save the node + pNode = pNodes[n1]; + // clean the node + pNodes[n1] = NULL; + return pNode; + } + + // combines two nodes + pNode = Extra_CombineTwoNodes( dd, b1, pNodes[n1], pNodes[n2] ); + + // clean the old nodes + pNodes[n1] = pNode; + pNodes[n2] = NULL; + return NULL; +} + +/**Function************************************************************* + + Synopsis [Merges two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Extra_ImageNode_t * Extra_CombineTwoNodes( DdManager * dd, DdNode * bCube, + Extra_ImageNode_t * pNode1, Extra_ImageNode_t * pNode2 ) +{ + Extra_ImageNode_t * pNode; + Extra_ImagePart_t * pPart; + + // create a new partition + pPart = ABC_ALLOC( Extra_ImagePart_t, 1 ); + memset( pPart, 0, sizeof(Extra_ImagePart_t) ); + // create the function + pPart->bFunc = Cudd_bddAndAbstract( dd, pNode1->pPart->bFunc, pNode2->pPart->bFunc, bCube ); + Cudd_Ref( pPart->bFunc ); + // update the support the partition + pPart->bSupp = Cudd_bddAndAbstract( dd, pNode1->pPart->bSupp, pNode2->pPart->bSupp, bCube ); + Cudd_Ref( pPart->bSupp ); + // update the numbers + pPart->nSupp = Extra_bddSuppSize( dd, pPart->bSupp ); + pPart->nNodes = Cudd_DagSize( pPart->bFunc ); + pPart->iPart = -1; +/* +ABC_PRB( dd, pNode1->pPart->bSupp ); +ABC_PRB( dd, pNode2->pPart->bSupp ); +ABC_PRB( dd, pPart->bSupp ); +*/ + // create a new node + pNode = ABC_ALLOC( Extra_ImageNode_t, 1 ); + memset( pNode, 0, sizeof(Extra_ImageNode_t) ); + pNode->dd = dd; + pNode->pPart = pPart; + pNode->pNode1 = pNode1; + pNode->pNode2 = pNode2; + // compute the image + pNode->bImage = Cudd_bddAndAbstract( dd, pNode1->bImage, pNode2->bImage, bCube ); + Cudd_Ref( pNode->bImage ); + // save the cube + if ( bCube != b1 ) + { + pNode->bCube = bCube; Cudd_Ref( bCube ); + } + return pNode; +} + +/**Function************************************************************* + + Synopsis [Computes the best variable.] + + Description [The variables is the best if the sum of squares of the + BDD sizes of the partitions, in which it participates, is the minimum.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_FindBestVariable( DdManager * dd, + int nNodes, Extra_ImageNode_t ** pNodes, + int nVars, Extra_ImageVar_t ** pVars ) +{ + DdNode * bTemp; + int iVarBest, v; + double CostBest, CostCur; + + CostBest = 100000000000000.0; + iVarBest = -1; + for ( v = 0; v < nVars; v++ ) + if ( pVars[v] ) + { + CostCur = 0; + for ( bTemp = pVars[v]->bParts; bTemp != b1; bTemp = cuddT(bTemp) ) + CostCur += pNodes[bTemp->index]->pPart->nNodes * + pNodes[bTemp->index]->pPart->nNodes; + if ( CostBest > CostCur ) + { + CostBest = CostCur; + iVarBest = v; + } + } + return iVarBest; +} + +/**Function************************************************************* + + Synopsis [Computes two smallest partions that have this var.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_FindBestPartitions( DdManager * dd, DdNode * bParts, + int nNodes, Extra_ImageNode_t ** pNodes, + int * piNode1, int * piNode2 ) +{ + DdNode * bTemp; + int iPart1, iPart2; + int CostMin1, CostMin2, Cost; + + // go through the partitions + iPart1 = iPart2 = -1; + CostMin1 = CostMin2 = 1000000; + for ( bTemp = bParts; bTemp != b1; bTemp = cuddT(bTemp) ) + { + Cost = pNodes[bTemp->index]->pPart->nNodes; + if ( CostMin1 > Cost ) + { + CostMin2 = CostMin1; iPart2 = iPart1; + CostMin1 = Cost; iPart1 = bTemp->index; + } + else if ( CostMin2 > Cost ) + { + CostMin2 = Cost; iPart2 = bTemp->index; + } + } + + *piNode1 = iPart1; + *piNode2 = iPart2; +} + +/**Function************************************************************* + + Synopsis [Prints the latch dependency matrix.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_bddImagePrintLatchDependency( + DdManager * dd, DdNode * bCare, // the care set + int nParts, DdNode ** pbParts, // the partitions for image computation + int nVars, DdNode ** pbVars ) // the NS and parameter variables (not quantified!) +{ + int i; + DdNode * bVarsCs, * bVarsNs; + + bVarsCs = Cudd_Support( dd, bCare ); Cudd_Ref( bVarsCs ); + bVarsNs = Cudd_bddComputeCube( dd, pbVars, NULL, nVars ); Cudd_Ref( bVarsNs ); + + printf( "The latch dependency matrix:\n" ); + printf( "Partitions = %d Variables: total = %d non-quantifiable = %d\n", + nParts, dd->size, nVars ); + printf( " : " ); + for ( i = 0; i < dd->size; i++ ) + printf( "%d", i % 10 ); + printf( "\n" ); + + for ( i = 0; i < nParts; i++ ) + Extra_bddImagePrintLatchDependencyOne( dd, pbParts[i], bVarsCs, bVarsNs, i ); + Extra_bddImagePrintLatchDependencyOne( dd, bCare, bVarsCs, bVarsNs, nParts ); + + Cudd_RecursiveDeref( dd, bVarsCs ); + Cudd_RecursiveDeref( dd, bVarsNs ); +} + +/**Function************************************************************* + + Synopsis [Prints one row of the latch dependency matrix.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_bddImagePrintLatchDependencyOne( + DdManager * dd, DdNode * bFunc, // the function + DdNode * bVarsCs, DdNode * bVarsNs, // the current/next state vars + int iPart ) +{ + DdNode * bSupport; + int v; + bSupport = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupport ); + printf( " %3d : ", iPart ); + for ( v = 0; v < dd->size; v++ ) + { + if ( Cudd_bddLeq( dd, bSupport, dd->vars[v] ) ) + { + if ( Cudd_bddLeq( dd, bVarsCs, dd->vars[v] ) ) + printf( "c" ); + else if ( Cudd_bddLeq( dd, bVarsNs, dd->vars[v] ) ) + printf( "n" ); + else + printf( "i" ); + } + else + printf( "." ); + } + printf( "\n" ); + Cudd_RecursiveDeref( dd, bSupport ); +} + + +/**Function************************************************************* + + Synopsis [Prints the tree for quenstification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_bddImagePrintTree( Extra_ImageTree_t * pTree ) +{ + printf( "The quantification scheduling tree:\n" ); + Extra_bddImagePrintTree_rec( pTree->pRoot, 1 ); +} + +/**Function************************************************************* + + Synopsis [Prints the tree for quenstification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_bddImagePrintTree_rec( Extra_ImageNode_t * pNode, int Offset ) +{ + DdNode * Cube; + int i; + + Cube = pNode->bCube; + + if ( pNode->pNode1 == NULL ) + { + printf( "<%d> ", pNode->pPart->iPart ); + if ( Cube != NULL ) + { + ABC_PRB( pNode->dd, Cube ); + } + else + printf( "\n" ); + return; + } + + printf( "<*> " ); + if ( Cube != NULL ) + { + ABC_PRB( pNode->dd, Cube ); + } + else + printf( "\n" ); + + for ( i = 0; i < Offset; i++ ) + printf( " " ); + Extra_bddImagePrintTree_rec( pNode->pNode1, Offset + 1 ); + + for ( i = 0; i < Offset; i++ ) + printf( " " ); + Extra_bddImagePrintTree_rec( pNode->pNode2, Offset + 1 ); +} + + + + + +struct Extra_ImageTree2_t_ +{ + DdManager * dd; + DdNode * bRel; + DdNode * bCube; + DdNode * bImage; +}; + +/**Function************************************************************* + + Synopsis [Starts the monolithic image computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Extra_ImageTree2_t * Extra_bddImageStart2( + DdManager * dd, DdNode * bCare, + int nParts, DdNode ** pbParts, + int nVars, DdNode ** pbVars, int fVerbose ) +{ + Extra_ImageTree2_t * pTree; + DdNode * bCubeAll, * bCubeNot, * bTemp; + int i; + + pTree = ABC_ALLOC( Extra_ImageTree2_t, 1 ); + pTree->dd = dd; + pTree->bImage = NULL; + + bCubeAll = Extra_bddComputeCube( dd, dd->vars, dd->size ); Cudd_Ref( bCubeAll ); + bCubeNot = Extra_bddComputeCube( dd, pbVars, nVars ); Cudd_Ref( bCubeNot ); + pTree->bCube = Cudd_bddExistAbstract( dd, bCubeAll, bCubeNot ); Cudd_Ref( pTree->bCube ); + Cudd_RecursiveDeref( dd, bCubeAll ); + Cudd_RecursiveDeref( dd, bCubeNot ); + + // derive the monolithic relation + pTree->bRel = b1; Cudd_Ref( pTree->bRel ); + for ( i = 0; i < nParts; i++ ) + { + pTree->bRel = Cudd_bddAnd( dd, bTemp = pTree->bRel, pbParts[i] ); Cudd_Ref( pTree->bRel ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Extra_bddImageCompute2( pTree, bCare ); + return pTree; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddImageCompute2( Extra_ImageTree2_t * pTree, DdNode * bCare ) +{ + if ( pTree->bImage ) + Cudd_RecursiveDeref( pTree->dd, pTree->bImage ); + pTree->bImage = Cudd_bddAndAbstract( pTree->dd, pTree->bRel, bCare, pTree->bCube ); + Cudd_Ref( pTree->bImage ); + return pTree->bImage; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_bddImageTreeDelete2( Extra_ImageTree2_t * pTree ) +{ + if ( pTree->bRel ) + Cudd_RecursiveDeref( pTree->dd, pTree->bRel ); + if ( pTree->bCube ) + Cudd_RecursiveDeref( pTree->dd, pTree->bCube ); + if ( pTree->bImage ) + Cudd_RecursiveDeref( pTree->dd, pTree->bImage ); + ABC_FREE( pTree ); +} + +/**Function************************************************************* + + Synopsis [Returns the previously computed image.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddImageRead2( Extra_ImageTree2_t * pTree ) +{ + return pTree->bImage; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/extrab/extraBddKmap.c b/src/bdd/extrab/extraBddKmap.c new file mode 100644 index 00000000..aa5efe75 --- /dev/null +++ b/src/bdd/extrab/extraBddKmap.c @@ -0,0 +1,876 @@ +/**CFile**************************************************************** + + FileName [extraBddKmap.c] + + PackageName [extra] + + Synopsis [Visualizing the K-map.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - September 1, 2003.] + + Revision [$Id: extraBddKmap.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $] + +***********************************************************************/ + +/// K-map visualization using pseudo graphics /// +/// Version 1.0. Started - August 20, 2000 /// +/// Version 2.0. Added to EXTRA - July 17, 2001 /// + +#include "extraBdd.h" + +#ifdef WIN32 +#include +#endif + +ABC_NAMESPACE_IMPL_START + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +// the maximum number of variables in the Karnaugh Map +#define MAXVARS 20 + +/* +// single line +#define SINGLE_VERTICAL (char)179 +#define SINGLE_HORIZONTAL (char)196 +#define SINGLE_TOP_LEFT (char)218 +#define SINGLE_TOP_RIGHT (char)191 +#define SINGLE_BOT_LEFT (char)192 +#define SINGLE_BOT_RIGHT (char)217 + +// double line +#define DOUBLE_VERTICAL (char)186 +#define DOUBLE_HORIZONTAL (char)205 +#define DOUBLE_TOP_LEFT (char)201 +#define DOUBLE_TOP_RIGHT (char)187 +#define DOUBLE_BOT_LEFT (char)200 +#define DOUBLE_BOT_RIGHT (char)188 + +// line intersections +#define SINGLES_CROSS (char)197 +#define DOUBLES_CROSS (char)206 +#define S_HOR_CROSS_D_VER (char)215 +#define S_VER_CROSS_D_HOR (char)216 + +// single line joining +#define S_JOINS_S_VER_LEFT (char)180 +#define S_JOINS_S_VER_RIGHT (char)195 +#define S_JOINS_S_HOR_TOP (char)193 +#define S_JOINS_S_HOR_BOT (char)194 + +// double line joining +#define D_JOINS_D_VER_LEFT (char)185 +#define D_JOINS_D_VER_RIGHT (char)204 +#define D_JOINS_D_HOR_TOP (char)202 +#define D_JOINS_D_HOR_BOT (char)203 + +// single line joining double line +#define S_JOINS_D_VER_LEFT (char)182 +#define S_JOINS_D_VER_RIGHT (char)199 +#define S_JOINS_D_HOR_TOP (char)207 +#define S_JOINS_D_HOR_BOT (char)209 +*/ + +// single line +#define SINGLE_VERTICAL (char)'|' +#define SINGLE_HORIZONTAL (char)'-' +#define SINGLE_TOP_LEFT (char)'+' +#define SINGLE_TOP_RIGHT (char)'+' +#define SINGLE_BOT_LEFT (char)'+' +#define SINGLE_BOT_RIGHT (char)'+' + +// double line +#define DOUBLE_VERTICAL (char)'|' +#define DOUBLE_HORIZONTAL (char)'-' +#define DOUBLE_TOP_LEFT (char)'+' +#define DOUBLE_TOP_RIGHT (char)'+' +#define DOUBLE_BOT_LEFT (char)'+' +#define DOUBLE_BOT_RIGHT (char)'+' + +// line intersections +#define SINGLES_CROSS (char)'+' +#define DOUBLES_CROSS (char)'+' +#define S_HOR_CROSS_D_VER (char)'+' +#define S_VER_CROSS_D_HOR (char)'+' + +// single line joining +#define S_JOINS_S_VER_LEFT (char)'+' +#define S_JOINS_S_VER_RIGHT (char)'+' +#define S_JOINS_S_HOR_TOP (char)'+' +#define S_JOINS_S_HOR_BOT (char)'+' + +// double line joining +#define D_JOINS_D_VER_LEFT (char)'+' +#define D_JOINS_D_VER_RIGHT (char)'+' +#define D_JOINS_D_HOR_TOP (char)'+' +#define D_JOINS_D_HOR_BOT (char)'+' + +// single line joining double line +#define S_JOINS_D_VER_LEFT (char)'+' +#define S_JOINS_D_VER_RIGHT (char)'+' +#define S_JOINS_D_HOR_TOP (char)'+' +#define S_JOINS_D_HOR_BOT (char)'+' + + +// other symbols +#define UNDERSCORE (char)95 +//#define SYMBOL_ZERO (char)248 // degree sign +//#define SYMBOL_ZERO (char)'o' +#ifdef WIN32 +#define SYMBOL_ZERO (char)'0' +#else +#define SYMBOL_ZERO (char)' ' +#endif +#define SYMBOL_ONE (char)'1' +#define SYMBOL_DC (char)'-' +#define SYMBOL_OVERLAP (char)'?' + +// full cells and half cells +#define CELL_FREE (char)32 +#define CELL_FULL (char)219 +#define HALF_UPPER (char)223 +#define HALF_LOWER (char)220 +#define HALF_LEFT (char)221 +#define HALF_RIGHT (char)222 + + +/*---------------------------------------------------------------------------*/ +/* Structure declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +// the array of BDD variables used internally +static DdNode * s_XVars[MAXVARS]; + +// flag which determines where the horizontal variable names are printed +static int fHorizontalVarNamesPrintedAbove = 1; + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +// Oleg's way of generating the gray code +static int GrayCode( int BinCode ); +static int BinCode ( int GrayCode ); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Prints the K-map of the function.] + + Description [If the pointer to the array of variables XVars is NULL, + fSuppType determines how the support will be determined. + fSuppType == 0 -- takes the first nVars of the manager + fSuppType == 1 -- takes the topmost nVars of the manager + fSuppType == 2 -- determines support from the on-set and the offset + ] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Extra_PrintKMap( + FILE * Output, /* the output stream */ + DdManager * dd, + DdNode * OnSet, + DdNode * OffSet, + int nVars, + DdNode ** XVars, + int fSuppType, /* the flag which determines how support is computed */ + char ** pVarNames ) +{ + int fPrintTruth = 1; + int d, p, n, s, v, h, w; + int nVarsVer; + int nVarsHor; + int nCellsVer; + int nCellsHor; + int nSkipSpaces; + + // make sure that on-set and off-set do not overlap + if ( !Cudd_bddLeq( dd, OnSet, Cudd_Not(OffSet) ) ) + { + fprintf( Output, "PrintKMap(): The on-set and the off-set overlap\n" ); + return; + } + if ( nVars == 0 ) + { printf( "Function is constant %d.\n", !Cudd_IsComplement(OnSet) ); return; } + + // print truth table for debugging + if ( fPrintTruth ) + { + DdNode * bCube, * bPart; + printf( "Truth table: " ); + if ( nVars == 0 ) + printf( "Constant" ); + else if ( nVars == 1 ) + printf( "1-var function" ); + else + { +// printf( "0x" ); + for ( d = (1<<(nVars-2)) - 1; d >= 0; d-- ) + { + int Value = 0; + for ( s = 0; s < 4; s++ ) + { + bCube = Extra_bddBitsToCube( dd, 4*d+s, nVars, dd->vars, 0 ); Cudd_Ref( bCube ); + bPart = Cudd_Cofactor( dd, OnSet, bCube ); Cudd_Ref( bPart ); + Value |= ((int)(bPart == b1) << s); + Cudd_RecursiveDeref( dd, bPart ); + Cudd_RecursiveDeref( dd, bCube ); + } + if ( Value < 10 ) + fprintf( stdout, "%d", Value ); + else + fprintf( stdout, "%c", 'a' + Value-10 ); + } + } + printf( "\n" ); + } + + +/* + if ( OnSet == b1 ) + { + fprintf( Output, "PrintKMap(): Constant 1\n" ); + return; + } + if ( OffSet == b1 ) + { + fprintf( Output, "PrintKMap(): Constant 0\n" ); + return; + } +*/ + if ( nVars < 0 || nVars > MAXVARS ) + { + fprintf( Output, "PrintKMap(): The number of variables is less than zero or more than %d\n", MAXVARS ); + return; + } + + // determine the support if it is not given + if ( XVars == NULL ) + { + if ( fSuppType == 0 ) + { // assume that the support includes the first nVars of the manager + assert( nVars ); + for ( v = 0; v < nVars; v++ ) + s_XVars[v] = Cudd_bddIthVar( dd, v ); + } + else if ( fSuppType == 1 ) + { // assume that the support includes the topmost nVars of the manager + assert( nVars ); + for ( v = 0; v < nVars; v++ ) + s_XVars[v] = Cudd_bddIthVar( dd, dd->invperm[v] ); + } + else // determine the support + { + DdNode * SuppOn, * SuppOff, * Supp; + int cVars = 0; + DdNode * TempSupp; + + // determine support + SuppOn = Cudd_Support( dd, OnSet ); Cudd_Ref( SuppOn ); + SuppOff = Cudd_Support( dd, OffSet ); Cudd_Ref( SuppOff ); + Supp = Cudd_bddAnd( dd, SuppOn, SuppOff ); Cudd_Ref( Supp ); + Cudd_RecursiveDeref( dd, SuppOn ); + Cudd_RecursiveDeref( dd, SuppOff ); + + nVars = Cudd_SupportSize( dd, Supp ); + if ( nVars > MAXVARS ) + { + fprintf( Output, "PrintKMap(): The number of variables is more than %d\n", MAXVARS ); + Cudd_RecursiveDeref( dd, Supp ); + return; + } + + // assign variables + for ( TempSupp = Supp; TempSupp != dd->one; TempSupp = Cudd_T(TempSupp), cVars++ ) + s_XVars[cVars] = Cudd_bddIthVar( dd, TempSupp->index ); + + Cudd_RecursiveDeref( dd, TempSupp ); + } + } + else + { + // copy variables + assert( XVars ); + for ( v = 0; v < nVars; v++ ) + s_XVars[v] = XVars[v]; + } + + //////////////////////////////////////////////////////////////////// + // determine the Karnaugh map parameters + nVarsVer = nVars/2; + nVarsHor = nVars - nVarsVer; + + nCellsVer = (1< MAXVARS ) + { + fprintf( Output, "PrintKMap(): The number of variables is less than zero or more than %d\n", MAXVARS ); + return; + } + + + //////////////////////////////////////////////////////////////////// + // determine the Karnaugh map parameters + nVarsVer = nXVars; + nVarsHor = nYVars; + nCellsVer = (1<> 1 ); +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int BinCode ( int GrayCode ) +{ + int bc = GrayCode; + while( GrayCode >>= 1 ) bc ^= GrayCode; + return bc; +} + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/extrab/extraBddMisc.c b/src/bdd/extrab/extraBddMisc.c new file mode 100644 index 00000000..a2ba4036 --- /dev/null +++ b/src/bdd/extrab/extraBddMisc.c @@ -0,0 +1,2342 @@ +/**CFile**************************************************************** + + FileName [extraBddMisc.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [extra] + + Synopsis [DD-based utilities.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: extraBddMisc.c,v 1.4 2005/10/04 00:19:54 alanmi Exp $] + +***********************************************************************/ + +#include "extraBdd.h" + +ABC_NAMESPACE_IMPL_START + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +// file "extraDdTransfer.c" +static DdNode * extraTransferPermuteRecur( DdManager * ddS, DdManager * ddD, DdNode * f, st__table * table, int * Permute ); +static DdNode * extraTransferPermute( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute ); +static DdNode * cuddBddPermuteRecur ARGS( ( DdManager * manager, DdHashTable * table, DdNode * node, int *permut ) ); + +static DdNode * extraBddAndPermute( DdHashTable * table, DdManager * ddF, DdNode * bF, DdManager * ddG, DdNode * bG, int * pPermute ); + +// file "cuddUtils.c" +static void ddSupportStep(DdNode *f, int *support); +static void ddClearFlag(DdNode *f); + +static DdNode* extraZddPrimes( DdManager *dd, DdNode* F ); + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Convert a {A,B}DD from a manager to another with variable remapping.] + + Description [Convert a {A,B}DD from a manager to another one. The orders of the + variables in the two managers may be different. Returns a + pointer to the {A,B}DD in the destination manager if successful; NULL + otherwise. The i-th entry in the array Permute tells what is the index + of the i-th variable from the old manager in the new manager.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_TransferPermute( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute ) +{ + DdNode * bRes; + do + { + ddDestination->reordered = 0; + bRes = extraTransferPermute( ddSource, ddDestination, f, Permute ); + } + while ( ddDestination->reordered == 1 ); + return ( bRes ); + +} /* end of Extra_TransferPermute */ + +/**Function******************************************************************** + + Synopsis [Transfers the BDD from one manager into another level by level.] + + Description [Transfers the BDD from one manager into another while + preserving the correspondence between variables level by level.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_TransferLevelByLevel( DdManager * ddSource, DdManager * ddDestination, DdNode * f ) +{ + DdNode * bRes; + int * pPermute; + int nMin, nMax, i; + + nMin = ddMin(ddSource->size, ddDestination->size); + nMax = ddMax(ddSource->size, ddDestination->size); + pPermute = ABC_ALLOC( int, nMax ); + // set up the variable permutation + for ( i = 0; i < nMin; i++ ) + pPermute[ ddSource->invperm[i] ] = ddDestination->invperm[i]; + if ( ddSource->size > ddDestination->size ) + { + for ( ; i < nMax; i++ ) + pPermute[ ddSource->invperm[i] ] = -1; + } + bRes = Extra_TransferPermute( ddSource, ddDestination, f, pPermute ); + ABC_FREE( pPermute ); + return bRes; +} + +/**Function******************************************************************** + + Synopsis [Remaps the function to depend on the topmost variables on the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_bddRemapUp( + DdManager * dd, + DdNode * bF ) +{ + int * pPermute; + DdNode * bSupp, * bTemp, * bRes; + int Counter; + + pPermute = ABC_ALLOC( int, dd->size ); + + // get support + bSupp = Cudd_Support( dd, bF ); Cudd_Ref( bSupp ); + + // create the variable map + // to remap the DD into the upper part of the manager + Counter = 0; + for ( bTemp = bSupp; bTemp != dd->one; bTemp = cuddT(bTemp) ) + pPermute[bTemp->index] = dd->invperm[Counter++]; + + // transfer the BDD and remap it + bRes = Cudd_bddPermute( dd, bF, pPermute ); Cudd_Ref( bRes ); + + // remove support + Cudd_RecursiveDeref( dd, bSupp ); + + // return + Cudd_Deref( bRes ); + ABC_FREE( pPermute ); + return bRes; +} + +/**Function******************************************************************** + + Synopsis [Moves the BDD by the given number of variables up or down.] + + Description [] + + SideEffects [] + + SeeAlso [Extra_bddShift] + +******************************************************************************/ +DdNode * Extra_bddMove( + DdManager * dd, /* the DD manager */ + DdNode * bF, + int nVars) +{ + DdNode * res; + DdNode * bVars; + if ( nVars == 0 ) + return bF; + if ( Cudd_IsConstant(bF) ) + return bF; + assert( nVars <= dd->size ); + if ( nVars > 0 ) + bVars = dd->vars[nVars]; + else + bVars = Cudd_Not(dd->vars[-nVars]); + + do { + dd->reordered = 0; + res = extraBddMove( dd, bF, bVars ); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_bddMove */ + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_StopManager( DdManager * dd ) +{ + int RetValue; + // check for remaining references in the package + RetValue = Cudd_CheckZeroRef( dd ); + if ( RetValue > 10 ) +// if ( RetValue ) + printf( "\nThe number of referenced nodes = %d\n\n", RetValue ); +// Cudd_PrintInfo( dd, stdout ); + Cudd_Quit( dd ); +} + +/**Function******************************************************************** + + Synopsis [Outputs the BDD in a readable format.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +void Extra_bddPrint( DdManager * dd, DdNode * F ) +{ + DdGen * Gen; + int * Cube; + CUDD_VALUE_TYPE Value; + int nVars = dd->size; + int fFirstCube = 1; + int i; + + if ( F == NULL ) + { + printf("NULL"); + return; + } + if ( F == b0 ) + { + printf("Constant 0"); + return; + } + if ( F == b1 ) + { + printf("Constant 1"); + return; + } + + Cudd_ForeachCube( dd, F, Gen, Cube, Value ) + { + if ( fFirstCube ) + fFirstCube = 0; + else +// Output << " + "; + printf( " + " ); + + for ( i = 0; i < nVars; i++ ) + if ( Cube[i] == 0 ) + printf( "[%d]'", i ); +// printf( "%c'", (char)('a'+i) ); + else if ( Cube[i] == 1 ) + printf( "[%d]", i ); +// printf( "%c", (char)('a'+i) ); + } + +// printf("\n"); +} + +/**Function******************************************************************** + + Synopsis [Outputs the BDD in a readable format.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +void Extra_bddPrintSupport( DdManager * dd, DdNode * F ) +{ + DdNode * bSupp; + bSupp = Cudd_Support( dd, F ); Cudd_Ref( bSupp ); + Extra_bddPrint( dd, bSupp ); + Cudd_RecursiveDeref( dd, bSupp ); +} + +/**Function******************************************************************** + + Synopsis [Returns the size of the support.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Extra_bddSuppSize( DdManager * dd, DdNode * bSupp ) +{ + int Counter = 0; + while ( bSupp != b1 ) + { + assert( !Cudd_IsComplement(bSupp) ); + assert( cuddE(bSupp) == b0 ); + + bSupp = cuddT(bSupp); + Counter++; + } + return Counter; +} + +/**Function******************************************************************** + + Synopsis [Returns 1 if the support contains the given BDD variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Extra_bddSuppContainVar( DdManager * dd, DdNode * bS, DdNode * bVar ) +{ + for( ; bS != b1; bS = cuddT(bS) ) + if ( bS->index == bVar->index ) + return 1; + return 0; +} + +/**Function******************************************************************** + + Synopsis [Returns 1 if two supports represented as BDD cubes are overlapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Extra_bddSuppOverlapping( DdManager * dd, DdNode * S1, DdNode * S2 ) +{ + while ( S1->index != CUDD_CONST_INDEX && S2->index != CUDD_CONST_INDEX ) + { + // if the top vars are the same, they intersect + if ( S1->index == S2->index ) + return 1; + // if the top vars are different, skip the one, which is higher + if ( dd->perm[S1->index] < dd->perm[S2->index] ) + S1 = cuddT(S1); + else + S2 = cuddT(S2); + } + return 0; +} + +/**Function******************************************************************** + + Synopsis [Returns the number of different vars in two supports.] + + Description [Counts the number of variables that appear in one support and + does not appear in other support. If the number exceeds DiffMax, returns DiffMax.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Extra_bddSuppDifferentVars( DdManager * dd, DdNode * S1, DdNode * S2, int DiffMax ) +{ + int Result = 0; + while ( S1->index != CUDD_CONST_INDEX && S2->index != CUDD_CONST_INDEX ) + { + // if the top vars are the same, this var is the same + if ( S1->index == S2->index ) + { + S1 = cuddT(S1); + S2 = cuddT(S2); + continue; + } + // the top var is different + Result++; + + if ( Result >= DiffMax ) + return DiffMax; + + // if the top vars are different, skip the one, which is higher + if ( dd->perm[S1->index] < dd->perm[S2->index] ) + S1 = cuddT(S1); + else + S2 = cuddT(S2); + } + + // consider the remaining variables + if ( S1->index != CUDD_CONST_INDEX ) + Result += Extra_bddSuppSize(dd,S1); + else if ( S2->index != CUDD_CONST_INDEX ) + Result += Extra_bddSuppSize(dd,S2); + + if ( Result >= DiffMax ) + return DiffMax; + return Result; +} + + +/**Function******************************************************************** + + Synopsis [Checks the support containment.] + + Description [This function returns 1 if one support is contained in another. + In this case, bLarge (bSmall) is assigned to point to the larger (smaller) support. + If the supports are identical, return 0 and does not assign the supports!] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Extra_bddSuppCheckContainment( DdManager * dd, DdNode * bL, DdNode * bH, DdNode ** bLarge, DdNode ** bSmall ) +{ + DdNode * bSL = bL; + DdNode * bSH = bH; + int fLcontainsH = 1; + int fHcontainsL = 1; + int TopVar; + + if ( bSL == bSH ) + return 0; + + while ( bSL != b1 || bSH != b1 ) + { + if ( bSL == b1 ) + { // Low component has no vars; High components has some vars + fLcontainsH = 0; + if ( fHcontainsL == 0 ) + return 0; + else + break; + } + + if ( bSH == b1 ) + { // similarly + fHcontainsL = 0; + if ( fLcontainsH == 0 ) + return 0; + else + break; + } + + // determine the topmost var of the supports by comparing their levels + if ( dd->perm[bSL->index] < dd->perm[bSH->index] ) + TopVar = bSL->index; + else + TopVar = bSH->index; + + if ( TopVar == bSL->index && TopVar == bSH->index ) + { // they are on the same level + // it does not tell us anything about their containment + // skip this var + bSL = cuddT(bSL); + bSH = cuddT(bSH); + } + else if ( TopVar == bSL->index ) // and TopVar != bSH->index + { // Low components is higher and contains more vars + // it is not possible that High component contains Low + fHcontainsL = 0; + // skip this var + bSL = cuddT(bSL); + } + else // if ( TopVar == bSH->index ) // and TopVar != bSL->index + { // similarly + fLcontainsH = 0; + // skip this var + bSH = cuddT(bSH); + } + + // check the stopping condition + if ( !fHcontainsL && !fLcontainsH ) + return 0; + } + // only one of them can be true at the same time + assert( !fHcontainsL || !fLcontainsH ); + if ( fHcontainsL ) + { + *bLarge = bH; + *bSmall = bL; + } + else // fLcontainsH + { + *bLarge = bL; + *bSmall = bH; + } + return 1; +} + + +/**Function******************************************************************** + + Synopsis [Finds variables on which the DD depends and returns them as am array.] + + Description [Finds the variables on which the DD depends. Returns an array + with entries set to 1 for those variables that belong to the support; + NULL otherwise. The array is allocated by the user and should have at least + as many entries as the maximum number of variables in BDD and ZDD parts of + the manager.] + + SideEffects [None] + + SeeAlso [Cudd_Support Cudd_VectorSupport Cudd_ClassifySupport] + +******************************************************************************/ +int * +Extra_SupportArray( + DdManager * dd, /* manager */ + DdNode * f, /* DD whose support is sought */ + int * support ) /* array allocated by the user */ +{ + int i, size; + + /* Initialize support array for ddSupportStep. */ + size = ddMax(dd->size, dd->sizeZ); + for (i = 0; i < size; i++) + support[i] = 0; + + /* Compute support and clean up markers. */ + ddSupportStep(Cudd_Regular(f),support); + ddClearFlag(Cudd_Regular(f)); + + return(support); + +} /* end of Extra_SupportArray */ + +/**Function******************************************************************** + + Synopsis [Finds the variables on which a set of DDs depends.] + + Description [Finds the variables on which a set of DDs depends. + The set must contain either BDDs and ADDs, or ZDDs. + Returns a BDD consisting of the product of the variables if + successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_Support Cudd_ClassifySupport] + +******************************************************************************/ +int * +Extra_VectorSupportArray( + DdManager * dd, /* manager */ + DdNode ** F, /* array of DDs whose support is sought */ + int n, /* size of the array */ + int * support ) /* array allocated by the user */ +{ + int i, size; + + /* Allocate and initialize support array for ddSupportStep. */ + size = ddMax( dd->size, dd->sizeZ ); + for ( i = 0; i < size; i++ ) + support[i] = 0; + + /* Compute support and clean up markers. */ + for ( i = 0; i < n; i++ ) + ddSupportStep( Cudd_Regular(F[i]), support ); + for ( i = 0; i < n; i++ ) + ddClearFlag( Cudd_Regular(F[i]) ); + + return support; +} + +/**Function******************************************************************** + + Synopsis [Find any cube belonging to the on-set of the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_bddFindOneCube( DdManager * dd, DdNode * bF ) +{ + char * s_Temp; + DdNode * bCube, * bTemp; + int v; + + // get the vector of variables in the cube + s_Temp = ABC_ALLOC( char, dd->size ); + Cudd_bddPickOneCube( dd, bF, s_Temp ); + + // start the cube + bCube = b1; Cudd_Ref( bCube ); + for ( v = 0; v < dd->size; v++ ) + if ( s_Temp[v] == 0 ) + { +// Cube &= !s_XVars[v]; + bCube = Cudd_bddAnd( dd, bTemp = bCube, Cudd_Not(dd->vars[v]) ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + } + else if ( s_Temp[v] == 1 ) + { +// Cube &= s_XVars[v]; + bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[v] ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref(bCube); + ABC_FREE( s_Temp ); + return bCube; +} + +/**Function******************************************************************** + + Synopsis [Returns one cube contained in the given BDD.] + + Description [This function returns the cube with the smallest + bits-to-integer value.] + + SideEffects [] + +******************************************************************************/ +DdNode * Extra_bddGetOneCube( DdManager * dd, DdNode * bFunc ) +{ + DdNode * bFuncR, * bFunc0, * bFunc1; + DdNode * bRes0, * bRes1, * bRes; + + bFuncR = Cudd_Regular(bFunc); + if ( cuddIsConstant(bFuncR) ) + return bFunc; + + // cofactor + if ( Cudd_IsComplement(bFunc) ) + { + bFunc0 = Cudd_Not( cuddE(bFuncR) ); + bFunc1 = Cudd_Not( cuddT(bFuncR) ); + } + else + { + bFunc0 = cuddE(bFuncR); + bFunc1 = cuddT(bFuncR); + } + + // try to find the cube with the negative literal + bRes0 = Extra_bddGetOneCube( dd, bFunc0 ); Cudd_Ref( bRes0 ); + + if ( bRes0 != b0 ) + { + bRes = Cudd_bddAnd( dd, bRes0, Cudd_Not(dd->vars[bFuncR->index]) ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bRes0 ); + } + else + { + Cudd_RecursiveDeref( dd, bRes0 ); + // try to find the cube with the positive literal + bRes1 = Extra_bddGetOneCube( dd, bFunc1 ); Cudd_Ref( bRes1 ); + assert( bRes1 != b0 ); + bRes = Cudd_bddAnd( dd, bRes1, dd->vars[bFuncR->index] ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bRes1 ); + } + + Cudd_Deref( bRes ); + return bRes; +} + +/**Function******************************************************************** + + Synopsis [Performs the reordering-sensitive step of Extra_bddMove().] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_bddComputeRangeCube( DdManager * dd, int iStart, int iStop ) +{ + DdNode * bTemp, * bProd; + int i; + assert( iStart <= iStop ); + assert( iStart >= 0 && iStart <= dd->size ); + assert( iStop >= 0 && iStop <= dd->size ); + bProd = b1; Cudd_Ref( bProd ); + for ( i = iStart; i < iStop; i++ ) + { + bProd = Cudd_bddAnd( dd, bTemp = bProd, dd->vars[i] ); Cudd_Ref( bProd ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bProd ); + return bProd; +} + +/**Function******************************************************************** + + Synopsis [Computes the cube of BDD variables corresponding to bits it the bit-code] + + Description [Returns a bdd composed of elementary bdds found in array BddVars[] such + that the bdd vars encode the number Value of bit length CodeWidth (if fMsbFirst is 1, + the most significant bit is encoded with the first bdd variable). If the variables + BddVars are not specified, takes the first CodeWidth variables of the manager] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_bddBitsToCube( DdManager * dd, int Code, int CodeWidth, DdNode ** pbVars, int fMsbFirst ) +{ + int z; + DdNode * bTemp, * bVar, * bVarBdd, * bResult; + + bResult = b1; Cudd_Ref( bResult ); + for ( z = 0; z < CodeWidth; z++ ) + { + bVarBdd = (pbVars)? pbVars[z]: dd->vars[z]; + if ( fMsbFirst ) + bVar = Cudd_NotCond( bVarBdd, (Code & (1 << (CodeWidth-1-z)))==0 ); + else + bVar = Cudd_NotCond( bVarBdd, (Code & (1 << (z)))==0 ); + bResult = Cudd_bddAnd( dd, bTemp = bResult, bVar ); Cudd_Ref( bResult ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bResult ); + + return bResult; +} /* end of Extra_bddBitsToCube */ + +/**Function******************************************************************** + + Synopsis [Finds the support as a negative polarity cube.] + + Description [Finds the variables on which a DD depends. Returns a BDD + consisting of the product of the variables in the negative polarity + if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_VectorSupport Cudd_Support] + +******************************************************************************/ +DdNode * Extra_bddSupportNegativeCube( DdManager * dd, DdNode * f ) +{ + int *support; + DdNode *res, *tmp, *var; + int i, j; + int size; + + /* Allocate and initialize support array for ddSupportStep. */ + size = ddMax( dd->size, dd->sizeZ ); + support = ABC_ALLOC( int, size ); + if ( support == NULL ) + { + dd->errorCode = CUDD_MEMORY_OUT; + return ( NULL ); + } + for ( i = 0; i < size; i++ ) + { + support[i] = 0; + } + + /* Compute support and clean up markers. */ + ddSupportStep( Cudd_Regular( f ), support ); + ddClearFlag( Cudd_Regular( f ) ); + + /* Transform support from array to cube. */ + do + { + dd->reordered = 0; + res = DD_ONE( dd ); + cuddRef( res ); + for ( j = size - 1; j >= 0; j-- ) + { /* for each level bottom-up */ + i = ( j >= dd->size ) ? j : dd->invperm[j]; + if ( support[i] == 1 ) + { + var = cuddUniqueInter( dd, i, dd->one, Cudd_Not( dd->one ) ); + ////////////////////////////////////////////////////////////////// + var = Cudd_Not(var); + ////////////////////////////////////////////////////////////////// + cuddRef( var ); + tmp = cuddBddAndRecur( dd, res, var ); + if ( tmp == NULL ) + { + Cudd_RecursiveDeref( dd, res ); + Cudd_RecursiveDeref( dd, var ); + res = NULL; + break; + } + cuddRef( tmp ); + Cudd_RecursiveDeref( dd, res ); + Cudd_RecursiveDeref( dd, var ); + res = tmp; + } + } + } + while ( dd->reordered == 1 ); + + ABC_FREE( support ); + if ( res != NULL ) + cuddDeref( res ); + return ( res ); + +} /* end of Extra_SupportNeg */ + +/**Function******************************************************************** + + Synopsis [Returns 1 if the BDD is the BDD of elementary variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Extra_bddIsVar( DdNode * bFunc ) +{ + bFunc = Cudd_Regular( bFunc ); + if ( cuddIsConstant(bFunc) ) + return 0; + return cuddIsConstant( cuddT(bFunc) ) && cuddIsConstant( Cudd_Regular(cuddE(bFunc)) ); +} + +/**Function******************************************************************** + + Synopsis [Creates AND composed of the first nVars of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_bddCreateAnd( DdManager * dd, int nVars ) +{ + DdNode * bFunc, * bTemp; + int i; + bFunc = Cudd_ReadOne(dd); Cudd_Ref( bFunc ); + for ( i = 0; i < nVars; i++ ) + { + bFunc = Cudd_bddAnd( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bFunc ); + return bFunc; +} + +/**Function******************************************************************** + + Synopsis [Creates OR composed of the first nVars of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_bddCreateOr( DdManager * dd, int nVars ) +{ + DdNode * bFunc, * bTemp; + int i; + bFunc = Cudd_ReadLogicZero(dd); Cudd_Ref( bFunc ); + for ( i = 0; i < nVars; i++ ) + { + bFunc = Cudd_bddOr( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bFunc ); + return bFunc; +} + +/**Function******************************************************************** + + Synopsis [Creates EXOR composed of the first nVars of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_bddCreateExor( DdManager * dd, int nVars ) +{ + DdNode * bFunc, * bTemp; + int i; + bFunc = Cudd_ReadLogicZero(dd); Cudd_Ref( bFunc ); + for ( i = 0; i < nVars; i++ ) + { + bFunc = Cudd_bddXor( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bFunc ); + return bFunc; +} + +/**Function******************************************************************** + + Synopsis [Computes the set of primes as a ZDD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_zddPrimes( DdManager * dd, DdNode * F ) +{ + DdNode *res; + do { + dd->reordered = 0; + res = extraZddPrimes(dd, F); + if ( dd->reordered == 1 ) + printf("\nReordering in Extra_zddPrimes()\n"); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_zddPrimes */ + +/**Function******************************************************************** + + Synopsis [Permutes the variables of the array of BDDs.] + + Description [Given a permutation in array permut, creates a new BDD + with permuted variables. There should be an entry in array permut + for each variable in the manager. The i-th entry of permut holds the + index of the variable that is to substitute the i-th variable. + The DDs in the resulting array are already referenced.] + + SideEffects [None] + + SeeAlso [Cudd_addPermute Cudd_bddSwapVariables] + +******************************************************************************/ +void Extra_bddPermuteArray( DdManager * manager, DdNode ** bNodesIn, DdNode ** bNodesOut, int nNodes, int *permut ) +{ + DdHashTable *table; + int i, k; + do + { + manager->reordered = 0; + table = cuddHashTableInit( manager, 1, 2 ); + + /* permute the output functions one-by-one */ + for ( i = 0; i < nNodes; i++ ) + { + bNodesOut[i] = cuddBddPermuteRecur( manager, table, bNodesIn[i], permut ); + if ( bNodesOut[i] == NULL ) + { + /* deref the array of the already computed outputs */ + for ( k = 0; k < i; k++ ) + Cudd_RecursiveDeref( manager, bNodesOut[k] ); + break; + } + cuddRef( bNodesOut[i] ); + } + /* Dispose of local cache. */ + cuddHashTableQuit( table ); + } + while ( manager->reordered == 1 ); +} /* end of Extra_bddPermuteArray */ + + +/**Function******************************************************************** + + Synopsis [Computes the positive polarty cube composed of the first vars in the array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_bddComputeCube( DdManager * dd, DdNode ** bXVars, int nVars ) +{ + DdNode * bRes; + DdNode * bTemp; + int i; + + bRes = b1; Cudd_Ref( bRes ); + for ( i = 0; i < nVars; i++ ) + { + bRes = Cudd_bddAnd( dd, bTemp = bRes, bXVars[i] ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + } + + Cudd_Deref( bRes ); + return bRes; +} + +/**Function******************************************************************** + + Synopsis [Changes the polarity of vars listed in the cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_bddChangePolarity( + DdManager * dd, /* the DD manager */ + DdNode * bFunc, + DdNode * bVars) +{ + DdNode *res; + do { + dd->reordered = 0; + res = extraBddChangePolarity( dd, bFunc, bVars ); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_bddChangePolarity */ + + +/**Function************************************************************* + + Synopsis [Checks if the given variable belongs to the cube.] + + Description [Return -1 if the var does not appear in the cube. + Otherwise, returns polarity (0 or 1) of the var in the cube.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_bddVarIsInCube( DdNode * bCube, int iVar ) +{ + DdNode * bCube0, * bCube1; + while ( Cudd_Regular(bCube)->index != CUDD_CONST_INDEX ) + { + bCube0 = Cudd_NotCond( cuddE(Cudd_Regular(bCube)), Cudd_IsComplement(bCube) ); + bCube1 = Cudd_NotCond( cuddT(Cudd_Regular(bCube)), Cudd_IsComplement(bCube) ); + // make sure it is a cube + assert( (Cudd_IsComplement(bCube0) && Cudd_Regular(bCube0)->index == CUDD_CONST_INDEX) || // bCube0 == 0 + (Cudd_IsComplement(bCube1) && Cudd_Regular(bCube1)->index == CUDD_CONST_INDEX) ); // bCube1 == 0 + // quit if it is the last one + if ( Cudd_Regular(bCube)->index == iVar ) + return (int)(Cudd_IsComplement(bCube0) && Cudd_Regular(bCube0)->index == CUDD_CONST_INDEX); + // get the next cube + if ( (Cudd_IsComplement(bCube0) && Cudd_Regular(bCube0)->index == CUDD_CONST_INDEX) ) + bCube = bCube1; + else + bCube = bCube0; + } + return -1; +} + +/**Function************************************************************* + + Synopsis [Computes the AND of two BDD with different orders.] + + Description [Derives the result of Boolean AND of bF and bG in ddF. + The array pPermute gives the mapping of variables of ddG into that of ddF.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddAndPermute( DdManager * ddF, DdNode * bF, DdManager * ddG, DdNode * bG, int * pPermute ) +{ + DdHashTable * table; + DdNode * bRes; + do + { + ddF->reordered = 0; + table = cuddHashTableInit( ddF, 2, 256 ); + if (table == NULL) return NULL; + bRes = extraBddAndPermute( table, ddF, bF, ddG, bG, pPermute ); + if ( bRes ) cuddRef( bRes ); + cuddHashTableQuit( table ); + if ( bRes ) cuddDeref( bRes ); +//if ( ddF->reordered == 1 ) +//printf( "Reordering happened\n" ); + } + while ( ddF->reordered == 1 ); +//printf( "|F| =%6d |G| =%6d |H| =%6d |F|*|G| =%9d\n", +// Cudd_DagSize(bF), Cudd_DagSize(bG), Cudd_DagSize(bRes), +// Cudd_DagSize(bF) * Cudd_DagSize(bG) ); + return ( bRes ); +} + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Performs the reordering-sensitive step of Extra_bddMove().] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * extraBddMove( + DdManager * dd, /* the DD manager */ + DdNode * bF, + DdNode * bDist) +{ + DdNode * bRes; + + if ( Cudd_IsConstant(bF) ) + return bF; + + if ( (bRes = cuddCacheLookup2(dd, extraBddMove, bF, bDist)) ) + return bRes; + else + { + DdNode * bRes0, * bRes1; + DdNode * bF0, * bF1; + DdNode * bFR = Cudd_Regular(bF); + int VarNew; + + if ( Cudd_IsComplement(bDist) ) + VarNew = bFR->index - Cudd_Not(bDist)->index; + else + VarNew = bFR->index + bDist->index; + assert( VarNew < dd->size ); + + // cofactor the functions + if ( bFR != bF ) // bFunc is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + + bRes0 = extraBddMove( dd, bF0, bDist ); + if ( bRes0 == NULL ) + return NULL; + cuddRef( bRes0 ); + + bRes1 = extraBddMove( dd, bF1, bDist ); + if ( bRes1 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + return NULL; + } + cuddRef( bRes1 ); + + /* only bRes0 and bRes1 are referenced at this point */ + bRes = cuddBddIteRecur( dd, dd->vars[VarNew], bRes1, bRes0 ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + Cudd_RecursiveDeref( dd, bRes1 ); + return NULL; + } + cuddRef( bRes ); + Cudd_RecursiveDeref( dd, bRes0 ); + Cudd_RecursiveDeref( dd, bRes1 ); + + /* insert the result into cache */ + cuddCacheInsert2( dd, extraBddMove, bF, bDist, bRes ); + cuddDeref( bRes ); + return bRes; + } +} /* end of extraBddMove */ + + +/**Function******************************************************************** + + Synopsis [Finds three cofactors of the cover w.r.t. to the topmost variable.] + + Description [Finds three cofactors of the cover w.r.t. to the topmost variable. + Does not check the cover for being a constant. Assumes that ZDD variables encoding + positive and negative polarities are adjacent in the variable order. Is different + from cuddZddGetCofactors3() in that it does not compute the cofactors w.r.t. the + given variable but takes the cofactors with respent to the topmost variable. + This function is more efficient when used in recursive procedures because it does + not require referencing of the resulting cofactors (compare cuddZddProduct() + and extraZddPrimeProduct()).] + + SideEffects [None] + + SeeAlso [cuddZddGetCofactors3] + +******************************************************************************/ +void +extraDecomposeCover( + DdManager* dd, /* the manager */ + DdNode* zC, /* the cover */ + DdNode** zC0, /* the pointer to the negative var cofactor */ + DdNode** zC1, /* the pointer to the positive var cofactor */ + DdNode** zC2 ) /* the pointer to the cofactor without var */ +{ + if ( (zC->index & 1) == 0 ) + { /* the top variable is present in positive polarity and maybe in negative */ + + DdNode *Temp = cuddE( zC ); + *zC1 = cuddT( zC ); + if ( cuddIZ(dd,Temp->index) == cuddIZ(dd,zC->index) + 1 ) + { /* Temp is not a terminal node + * top var is present in negative polarity */ + *zC2 = cuddE( Temp ); + *zC0 = cuddT( Temp ); + } + else + { /* top var is not present in negative polarity */ + *zC2 = Temp; + *zC0 = dd->zero; + } + } + else + { /* the top variable is present only in negative */ + *zC1 = dd->zero; + *zC2 = cuddE( zC ); + *zC0 = cuddT( zC ); + } +} /* extraDecomposeCover */ + + + +/**Function******************************************************************** + + Synopsis [Counts the total number of cubes in the ISOPs of the functions.] + + Description [Returns -1 if the number of cubes exceeds the limit.] + + SideEffects [None] + + SeeAlso [Extra_TransferPermute] + +******************************************************************************/ +static DdNode * extraBddCountCubes( DdManager * dd, DdNode * L, DdNode * U, st__table *table, int * pnCubes, int Limit ) +{ + DdNode *one = DD_ONE(dd); + DdNode *zero = Cudd_Not(one); + int v, top_l, top_u; + DdNode *Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud; + DdNode *Lsuper0, *Usuper0, *Lsuper1, *Usuper1; + DdNode *Isub0, *Isub1, *Id; + DdNode *x; + DdNode *term0, *term1, *sum; + DdNode *Lv, *Uv, *Lnv, *Unv; + DdNode *r; + int index; + int Count0 = 0, Count1 = 0, Count2 = 0; + + statLine(dd); + if (L == zero) + { + *pnCubes = 0; + return(zero); + } + if (U == one) + { + *pnCubes = 1; + return(one); + } + + /* Check cache */ + r = cuddCacheLookup2(dd, cuddBddIsop, L, U); + if (r) + { + int nCubes = 0; + if ( st__lookup( table, (char *)r, (char **)&nCubes ) ) + *pnCubes = nCubes; + else assert( 0 ); + return r; + } + + top_l = dd->perm[Cudd_Regular(L)->index]; + top_u = dd->perm[Cudd_Regular(U)->index]; + v = ddMin(top_l, top_u); + + /* Compute cofactors */ + if (top_l == v) { + index = Cudd_Regular(L)->index; + Lv = Cudd_T(L); + Lnv = Cudd_E(L); + if (Cudd_IsComplement(L)) { + Lv = Cudd_Not(Lv); + Lnv = Cudd_Not(Lnv); + } + } + else { + index = Cudd_Regular(U)->index; + Lv = Lnv = L; + } + + if (top_u == v) { + Uv = Cudd_T(U); + Unv = Cudd_E(U); + if (Cudd_IsComplement(U)) { + Uv = Cudd_Not(Uv); + Unv = Cudd_Not(Unv); + } + } + else { + Uv = Unv = U; + } + + Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv)); + if (Lsub0 == NULL) + return(NULL); + Cudd_Ref(Lsub0); + Usub0 = Unv; + Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv)); + if (Lsub1 == NULL) { + Cudd_RecursiveDeref(dd, Lsub0); + return(NULL); + } + Cudd_Ref(Lsub1); + Usub1 = Uv; + + Isub0 = extraBddCountCubes(dd, Lsub0, Usub0, table, &Count0, Limit); + if (Isub0 == NULL) { + Cudd_RecursiveDeref(dd, Lsub0); + Cudd_RecursiveDeref(dd, Lsub1); + return(NULL); + } + Cudd_Ref(Isub0); + Isub1 = extraBddCountCubes(dd, Lsub1, Usub1, table, &Count1, Limit); + if (Isub1 == NULL) { + Cudd_RecursiveDeref(dd, Lsub0); + Cudd_RecursiveDeref(dd, Lsub1); + Cudd_RecursiveDeref(dd, Isub0); + return(NULL); + } + Cudd_Ref(Isub1); + Cudd_RecursiveDeref(dd, Lsub0); + Cudd_RecursiveDeref(dd, Lsub1); + + Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0)); + if (Lsuper0 == NULL) { + Cudd_RecursiveDeref(dd, Isub0); + Cudd_RecursiveDeref(dd, Isub1); + return(NULL); + } + Cudd_Ref(Lsuper0); + Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1)); + if (Lsuper1 == NULL) { + Cudd_RecursiveDeref(dd, Isub0); + Cudd_RecursiveDeref(dd, Isub1); + Cudd_RecursiveDeref(dd, Lsuper0); + return(NULL); + } + Cudd_Ref(Lsuper1); + Usuper0 = Unv; + Usuper1 = Uv; + + /* Ld = Lsuper0 + Lsuper1 */ + Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1)); + Ld = Cudd_NotCond(Ld, Ld != NULL); + if (Ld == NULL) { + Cudd_RecursiveDeref(dd, Isub0); + Cudd_RecursiveDeref(dd, Isub1); + Cudd_RecursiveDeref(dd, Lsuper0); + Cudd_RecursiveDeref(dd, Lsuper1); + return(NULL); + } + Cudd_Ref(Ld); + Ud = cuddBddAndRecur(dd, Usuper0, Usuper1); + if (Ud == NULL) { + Cudd_RecursiveDeref(dd, Isub0); + Cudd_RecursiveDeref(dd, Isub1); + Cudd_RecursiveDeref(dd, Lsuper0); + Cudd_RecursiveDeref(dd, Lsuper1); + Cudd_RecursiveDeref(dd, Ld); + return(NULL); + } + Cudd_Ref(Ud); + Cudd_RecursiveDeref(dd, Lsuper0); + Cudd_RecursiveDeref(dd, Lsuper1); + + Id = extraBddCountCubes(dd, Ld, Ud, table, &Count2, Limit); + if (Id == NULL) { + Cudd_RecursiveDeref(dd, Isub0); + Cudd_RecursiveDeref(dd, Isub1); + Cudd_RecursiveDeref(dd, Ld); + Cudd_RecursiveDeref(dd, Ud); + return(NULL); + } + Cudd_Ref(Id); + Cudd_RecursiveDeref(dd, Ld); + Cudd_RecursiveDeref(dd, Ud); + + x = cuddUniqueInter(dd, index, one, zero); + if (x == NULL) { + Cudd_RecursiveDeref(dd, Isub0); + Cudd_RecursiveDeref(dd, Isub1); + Cudd_RecursiveDeref(dd, Id); + return(NULL); + } + Cudd_Ref(x); + term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0); + if (term0 == NULL) { + Cudd_RecursiveDeref(dd, Isub0); + Cudd_RecursiveDeref(dd, Isub1); + Cudd_RecursiveDeref(dd, Id); + Cudd_RecursiveDeref(dd, x); + return(NULL); + } + Cudd_Ref(term0); + Cudd_RecursiveDeref(dd, Isub0); + term1 = cuddBddAndRecur(dd, x, Isub1); + if (term1 == NULL) { + Cudd_RecursiveDeref(dd, Isub1); + Cudd_RecursiveDeref(dd, Id); + Cudd_RecursiveDeref(dd, x); + Cudd_RecursiveDeref(dd, term0); + return(NULL); + } + Cudd_Ref(term1); + Cudd_RecursiveDeref(dd, x); + Cudd_RecursiveDeref(dd, Isub1); + /* sum = term0 + term1 */ + sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1)); + sum = Cudd_NotCond(sum, sum != NULL); + if (sum == NULL) { + Cudd_RecursiveDeref(dd, Id); + Cudd_RecursiveDeref(dd, term0); + Cudd_RecursiveDeref(dd, term1); + return(NULL); + } + Cudd_Ref(sum); + Cudd_RecursiveDeref(dd, term0); + Cudd_RecursiveDeref(dd, term1); + /* r = sum + Id */ + r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id)); + r = Cudd_NotCond(r, r != NULL); + if (r == NULL) { + Cudd_RecursiveDeref(dd, Id); + Cudd_RecursiveDeref(dd, sum); + return(NULL); + } + Cudd_Ref(r); + Cudd_RecursiveDeref(dd, sum); + Cudd_RecursiveDeref(dd, Id); + + cuddCacheInsert2(dd, cuddBddIsop, L, U, r); + *pnCubes = Count0 + Count1 + Count2; + if ( st__add_direct( table, (char *)r, (char *)(ABC_PTRINT_T)*pnCubes ) == st__OUT_OF_MEM ) + { + Cudd_RecursiveDeref( dd, r ); + return NULL; + } + if ( *pnCubes > Limit ) + { + Cudd_RecursiveDeref( dd, r ); + return NULL; + } + //printf( "%d ", *pnCubes ); + Cudd_Deref(r); + return r; +} +int Extra_bddCountCubes( DdManager * dd, DdNode ** pFuncs, int nFuncs, int fMode, int nLimit, int * pGuide ) +{ + DdNode * pF0, * pF1; + int i, Count, Count0, Count1, CounterAll = 0; + st__table *table = st__init_table( st__ptrcmp, st__ptrhash ); + unsigned int saveLimit = dd->maxLive; + dd->maxLive = dd->keys - dd->dead + 1000000; // limit on intermediate BDD nodes + for ( i = 0; i < nFuncs; i++ ) + { + if ( !pFuncs[i] ) + continue; + pF1 = pF0 = NULL; + Count0 = Count1 = nLimit; + if ( fMode == -1 || fMode == 1 ) // both or pos + pF1 = extraBddCountCubes( dd, pFuncs[i], pFuncs[i], table, &Count1, nLimit ); + pFuncs[i] = Cudd_Not( pFuncs[i] ); + if ( fMode == -1 || fMode == 0 ) // both or neg + pF0 = extraBddCountCubes( dd, pFuncs[i], pFuncs[i], table, &Count0, Count1 ); + pFuncs[i] = Cudd_Not( pFuncs[i] ); + if ( !pF1 && !pF0 ) + break; + if ( !pF0 ) pGuide[i] = 1, Count = Count1; // use pos + else if ( !pF1 ) pGuide[i] = 0, Count = Count0; // use neg + else if ( Count1 <= Count0 ) pGuide[i] = 1, Count = Count1; // use pos + else pGuide[i] = 0, Count = Count0; // use neg + CounterAll += Count; + //printf( "Output %5d has %5d cubes (%d) (%5d and %5d)\n", nOuts++, Count, pGuide[i], Count1, Count0 ); + } + dd->maxLive = saveLimit; + st__free_table( table ); + return i == nFuncs ? CounterAll : -1; +} /* end of Extra_bddCountCubes */ + +/*---------------------------------------------------------------------------*/ +/* Definition of static Functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Convert a BDD from a manager to another one.] + + Description [Convert a BDD from a manager to another one. Returns a + pointer to the BDD in the destination manager if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Extra_TransferPermute] + +******************************************************************************/ +DdNode * extraTransferPermute( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute ) +{ + DdNode *res; + st__table *table = NULL; + st__generator *gen = NULL; + DdNode *key, *value; + + table = st__init_table( st__ptrcmp, st__ptrhash ); + if ( table == NULL ) + goto failure; + res = extraTransferPermuteRecur( ddS, ddD, f, table, Permute ); + if ( res != NULL ) + cuddRef( res ); + + /* Dereference all elements in the table and dispose of the table. + ** This must be done also if res is NULL to avoid leaks in case of + ** reordering. */ + gen = st__init_gen( table ); + if ( gen == NULL ) + goto failure; + while ( st__gen( gen, ( const char ** ) &key, ( char ** ) &value ) ) + { + Cudd_RecursiveDeref( ddD, value ); + } + st__free_gen( gen ); + gen = NULL; + st__free_table( table ); + table = NULL; + + if ( res != NULL ) + cuddDeref( res ); + return ( res ); + + failure: + if ( table != NULL ) + st__free_table( table ); + if ( gen != NULL ) + st__free_gen( gen ); + return ( NULL ); + +} /* end of extraTransferPermute */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Extra_TransferPermute.] + + Description [Performs the recursive step of Extra_TransferPermute. + Returns a pointer to the result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [extraTransferPermute] + +******************************************************************************/ +static DdNode * +extraTransferPermuteRecur( + DdManager * ddS, + DdManager * ddD, + DdNode * f, + st__table * table, + int * Permute ) +{ + DdNode *ft, *fe, *t, *e, *var, *res; + DdNode *one, *zero; + int index; + int comple = 0; + + statLine( ddD ); + one = DD_ONE( ddD ); + comple = Cudd_IsComplement( f ); + + /* Trivial cases. */ + if ( Cudd_IsConstant( f ) ) + return ( Cudd_NotCond( one, comple ) ); + + + /* Make canonical to increase the utilization of the cache. */ + f = Cudd_NotCond( f, comple ); + /* Now f is a regular pointer to a non-constant node. */ + + /* Check the cache. */ + if ( st__lookup( table, ( char * ) f, ( char ** ) &res ) ) + return ( Cudd_NotCond( res, comple ) ); + + if ( ddS->TimeStop && Abc_Clock() > ddS->TimeStop ) + return NULL; + if ( ddD->TimeStop && Abc_Clock() > ddD->TimeStop ) + return NULL; + + /* Recursive step. */ + if ( Permute ) + index = Permute[f->index]; + else + index = f->index; + + ft = cuddT( f ); + fe = cuddE( f ); + + t = extraTransferPermuteRecur( ddS, ddD, ft, table, Permute ); + if ( t == NULL ) + { + return ( NULL ); + } + cuddRef( t ); + + e = extraTransferPermuteRecur( ddS, ddD, fe, table, Permute ); + if ( e == NULL ) + { + Cudd_RecursiveDeref( ddD, t ); + return ( NULL ); + } + cuddRef( e ); + + zero = Cudd_Not(ddD->one); + var = cuddUniqueInter( ddD, index, one, zero ); + if ( var == NULL ) + { + Cudd_RecursiveDeref( ddD, t ); + Cudd_RecursiveDeref( ddD, e ); + return ( NULL ); + } + res = cuddBddIteRecur( ddD, var, t, e ); + + if ( res == NULL ) + { + Cudd_RecursiveDeref( ddD, t ); + Cudd_RecursiveDeref( ddD, e ); + return ( NULL ); + } + cuddRef( res ); + Cudd_RecursiveDeref( ddD, t ); + Cudd_RecursiveDeref( ddD, e ); + + if ( st__add_direct( table, ( char * ) f, ( char * ) res ) == + st__OUT_OF_MEM ) + { + Cudd_RecursiveDeref( ddD, res ); + return ( NULL ); + } + return ( Cudd_NotCond( res, comple ) ); + +} /* end of extraTransferPermuteRecur */ + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_Support.] + + Description [Performs the recursive step of Cudd_Support. Performs a + DFS from f. The support is accumulated in supp as a side effect. Uses + the LSB of the then pointer as visited flag.] + + SideEffects [None] + + SeeAlso [ddClearFlag] + +******************************************************************************/ +static void +ddSupportStep( + DdNode * f, + int * support) +{ + if (cuddIsConstant(f) || Cudd_IsComplement(f->next)) { + return; + } + + support[f->index] = 1; + ddSupportStep(cuddT(f),support); + ddSupportStep(Cudd_Regular(cuddE(f)),support); + /* Mark as visited. */ + f->next = Cudd_Not(f->next); + return; + +} /* end of ddSupportStep */ + + +/**Function******************************************************************** + + Synopsis [Performs a DFS from f, clearing the LSB of the next + pointers.] + + Description [] + + SideEffects [None] + + SeeAlso [ddSupportStep ddDagInt] + +******************************************************************************/ +static void +ddClearFlag( + DdNode * f) +{ + if (!Cudd_IsComplement(f->next)) { + return; + } + /* Clear visited flag. */ + f->next = Cudd_Regular(f->next); + if (cuddIsConstant(f)) { + return; + } + ddClearFlag(cuddT(f)); + ddClearFlag(Cudd_Regular(cuddE(f))); + return; + +} /* end of ddClearFlag */ + + +/**Function******************************************************************** + + Synopsis [Composed three subcovers into one ZDD.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +extraComposeCover( + DdManager* dd, /* the manager */ + DdNode* zC0, /* the pointer to the negative var cofactor */ + DdNode* zC1, /* the pointer to the positive var cofactor */ + DdNode* zC2, /* the pointer to the cofactor without var */ + int TopVar) /* the index of the positive ZDD var */ +{ + DdNode * zRes, * zTemp; + /* compose with-neg-var and without-var using the neg ZDD var */ + zTemp = cuddZddGetNode( dd, 2*TopVar + 1, zC0, zC2 ); + if ( zTemp == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zC0); + Cudd_RecursiveDerefZdd(dd, zC1); + Cudd_RecursiveDerefZdd(dd, zC2); + return NULL; + } + cuddRef( zTemp ); + cuddDeref( zC0 ); + cuddDeref( zC2 ); + + /* compose with-pos-var and previous result using the pos ZDD var */ + zRes = cuddZddGetNode( dd, 2*TopVar, zC1, zTemp ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zC1); + Cudd_RecursiveDerefZdd(dd, zTemp); + return NULL; + } + cuddDeref( zC1 ); + cuddDeref( zTemp ); + return zRes; +} /* extraComposeCover */ + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of prime computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode* extraZddPrimes( DdManager *dd, DdNode* F ) +{ + DdNode *zRes; + + if ( F == Cudd_Not( dd->one ) ) + return dd->zero; + if ( F == dd->one ) + return dd->one; + + /* check cache */ + zRes = cuddCacheLookup1Zdd(dd, extraZddPrimes, F); + if (zRes) + return(zRes); + { + /* temporary variables */ + DdNode *bF01, *zP0, *zP1; + /* three components of the prime set */ + DdNode *zResE, *zResP, *zResN; + int fIsComp = Cudd_IsComplement( F ); + + /* find cofactors of F */ + DdNode * bF0 = Cudd_NotCond( Cudd_E( F ), fIsComp ); + DdNode * bF1 = Cudd_NotCond( Cudd_T( F ), fIsComp ); + + /* find the intersection of cofactors */ + bF01 = cuddBddAndRecur( dd, bF0, bF1 ); + if ( bF01 == NULL ) return NULL; + cuddRef( bF01 ); + + /* solve the problems for cofactors */ + zP0 = extraZddPrimes( dd, bF0 ); + if ( zP0 == NULL ) + { + Cudd_RecursiveDeref( dd, bF01 ); + return NULL; + } + cuddRef( zP0 ); + + zP1 = extraZddPrimes( dd, bF1 ); + if ( zP1 == NULL ) + { + Cudd_RecursiveDeref( dd, bF01 ); + Cudd_RecursiveDerefZdd( dd, zP0 ); + return NULL; + } + cuddRef( zP1 ); + + /* check for local unateness */ + if ( bF01 == bF0 ) /* unate increasing */ + { + /* intersection is useless */ + cuddDeref( bF01 ); + /* the primes of intersection are the primes of F0 */ + zResE = zP0; + /* there are no primes with negative var */ + zResN = dd->zero; + cuddRef( zResN ); + /* primes with positive var are primes of F1 that are not primes of F01 */ + zResP = cuddZddDiff( dd, zP1, zP0 ); + if ( zResP == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zResE ); + Cudd_RecursiveDerefZdd( dd, zResN ); + Cudd_RecursiveDerefZdd( dd, zP1 ); + return NULL; + } + cuddRef( zResP ); + Cudd_RecursiveDerefZdd( dd, zP1 ); + } + else if ( bF01 == bF1 ) /* unate decreasing */ + { + /* intersection is useless */ + cuddDeref( bF01 ); + /* the primes of intersection are the primes of F1 */ + zResE = zP1; + /* there are no primes with positive var */ + zResP = dd->zero; + cuddRef( zResP ); + /* primes with negative var are primes of F0 that are not primes of F01 */ + zResN = cuddZddDiff( dd, zP0, zP1 ); + if ( zResN == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zResE ); + Cudd_RecursiveDerefZdd( dd, zResP ); + Cudd_RecursiveDerefZdd( dd, zP0 ); + return NULL; + } + cuddRef( zResN ); + Cudd_RecursiveDerefZdd( dd, zP0 ); + } + else /* not unate */ + { + /* primes without the top var are primes of F10 */ + zResE = extraZddPrimes( dd, bF01 ); + if ( zResE == NULL ) + { + Cudd_RecursiveDerefZdd( dd, bF01 ); + Cudd_RecursiveDerefZdd( dd, zP0 ); + Cudd_RecursiveDerefZdd( dd, zP1 ); + return NULL; + } + cuddRef( zResE ); + Cudd_RecursiveDeref( dd, bF01 ); + + /* primes with the negative top var are those of P0 that are not in F10 */ + zResN = cuddZddDiff( dd, zP0, zResE ); + if ( zResN == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zResE ); + Cudd_RecursiveDerefZdd( dd, zP0 ); + Cudd_RecursiveDerefZdd( dd, zP1 ); + return NULL; + } + cuddRef( zResN ); + Cudd_RecursiveDerefZdd( dd, zP0 ); + + /* primes with the positive top var are those of P1 that are not in F10 */ + zResP = cuddZddDiff( dd, zP1, zResE ); + if ( zResP == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zResE ); + Cudd_RecursiveDerefZdd( dd, zResN ); + Cudd_RecursiveDerefZdd( dd, zP1 ); + return NULL; + } + cuddRef( zResP ); + Cudd_RecursiveDerefZdd( dd, zP1 ); + } + + zRes = extraComposeCover( dd, zResN, zResP, zResE, Cudd_Regular(F)->index ); + if ( zRes == NULL ) return NULL; + + /* insert the result into cache */ + cuddCacheInsert1(dd, extraZddPrimes, F, zRes); + return zRes; + } +} /* end of extraZddPrimes */ + +/**Function******************************************************************** + + Synopsis [Implements the recursive step of Cudd_bddPermute.] + + Description [ Recursively puts the BDD in the order given in the array permut. + Checks for trivial cases to terminate recursion, then splits on the + children of this node. Once the solutions for the children are + obtained, it puts into the current position the node from the rest of + the BDD that should be here. Then returns this BDD. + The key here is that the node being visited is NOT put in its proper + place by this instance, but rather is switched when its proper position + is reached in the recursion tree.

+ The DdNode * that is returned is the same BDD as passed in as node, + but in the new order.] + + SideEffects [None] + + SeeAlso [Cudd_bddPermute cuddAddPermuteRecur] + +******************************************************************************/ +static DdNode * +cuddBddPermuteRecur( DdManager * manager /* DD manager */ , + DdHashTable * table /* computed table */ , + DdNode * node /* BDD to be reordered */ , + int *permut /* permutation array */ ) +{ + DdNode *N, *T, *E; + DdNode *res; + int index; + + statLine( manager ); + N = Cudd_Regular( node ); + + /* Check for terminal case of constant node. */ + if ( cuddIsConstant( N ) ) + { + return ( node ); + } + + /* If problem already solved, look up answer and return. */ + if ( N->ref != 1 && ( res = cuddHashTableLookup1( table, N ) ) != NULL ) + { + return ( Cudd_NotCond( res, N != node ) ); + } + + /* Split and recur on children of this node. */ + T = cuddBddPermuteRecur( manager, table, cuddT( N ), permut ); + if ( T == NULL ) + return ( NULL ); + cuddRef( T ); + E = cuddBddPermuteRecur( manager, table, cuddE( N ), permut ); + if ( E == NULL ) + { + Cudd_IterDerefBdd( manager, T ); + return ( NULL ); + } + cuddRef( E ); + + /* Move variable that should be in this position to this position + ** by retrieving the single var BDD for that variable, and calling + ** cuddBddIteRecur with the T and E we just created. + */ + index = permut[N->index]; + res = cuddBddIteRecur( manager, manager->vars[index], T, E ); + if ( res == NULL ) + { + Cudd_IterDerefBdd( manager, T ); + Cudd_IterDerefBdd( manager, E ); + return ( NULL ); + } + cuddRef( res ); + Cudd_IterDerefBdd( manager, T ); + Cudd_IterDerefBdd( manager, E ); + + /* Do not keep the result if the reference count is only 1, since + ** it will not be visited again. + */ + if ( N->ref != 1 ) + { + ptrint fanout = ( ptrint ) N->ref; + cuddSatDec( fanout ); + if ( !cuddHashTableInsert1( table, N, res, fanout ) ) + { + Cudd_IterDerefBdd( manager, res ); + return ( NULL ); + } + } + cuddDeref( res ); + return ( Cudd_NotCond( res, N != node ) ); + +} /* end of cuddBddPermuteRecur */ + + +/**Function******************************************************************** + + Synopsis [Performs the reordering-sensitive step of Extra_bddChangePolarity().] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * extraBddChangePolarity( + DdManager * dd, /* the DD manager */ + DdNode * bFunc, + DdNode * bVars) +{ + DdNode * bRes; + + if ( bVars == b1 ) + return bFunc; + if ( Cudd_IsConstant(bFunc) ) + return bFunc; + + if ( (bRes = cuddCacheLookup2(dd, extraBddChangePolarity, bFunc, bVars)) ) + return bRes; + else + { + DdNode * bFR = Cudd_Regular(bFunc); + int LevelF = dd->perm[bFR->index]; + int LevelV = dd->perm[bVars->index]; + + if ( LevelV < LevelF ) + bRes = extraBddChangePolarity( dd, bFunc, cuddT(bVars) ); + else // if ( LevelF <= LevelV ) + { + DdNode * bRes0, * bRes1; + DdNode * bF0, * bF1; + DdNode * bVarsNext; + + // cofactor the functions + if ( bFR != bFunc ) // bFunc is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + + if ( LevelF == LevelV ) + bVarsNext = cuddT(bVars); + else + bVarsNext = bVars; + + bRes0 = extraBddChangePolarity( dd, bF0, bVarsNext ); + if ( bRes0 == NULL ) + return NULL; + cuddRef( bRes0 ); + + bRes1 = extraBddChangePolarity( dd, bF1, bVarsNext ); + if ( bRes1 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + return NULL; + } + cuddRef( bRes1 ); + + if ( LevelF == LevelV ) + { // swap the cofactors + DdNode * bTemp; + bTemp = bRes0; + bRes0 = bRes1; + bRes1 = bTemp; + } + + /* only aRes0 and aRes1 are referenced at this point */ + + /* consider the case when Res0 and Res1 are the same node */ + if ( bRes0 == bRes1 ) + bRes = bRes1; + /* consider the case when Res1 is complemented */ + else if ( Cudd_IsComplement(bRes1) ) + { + bRes = cuddUniqueInter(dd, bFR->index, Cudd_Not(bRes1), Cudd_Not(bRes0)); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref(dd,bRes0); + Cudd_RecursiveDeref(dd,bRes1); + return NULL; + } + bRes = Cudd_Not(bRes); + } + else + { + bRes = cuddUniqueInter( dd, bFR->index, bRes1, bRes0 ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref(dd,bRes0); + Cudd_RecursiveDeref(dd,bRes1); + return NULL; + } + } + cuddDeref( bRes0 ); + cuddDeref( bRes1 ); + } + + /* insert the result into cache */ + cuddCacheInsert2(dd, extraBddChangePolarity, bFunc, bVars, bRes); + return bRes; + } +} /* end of extraBddChangePolarity */ + + + +static int Counter = 0; + +/**Function************************************************************* + + Synopsis [Computes the AND of two BDD with different orders.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * extraBddAndPermute( DdHashTable * table, DdManager * ddF, DdNode * bF, DdManager * ddG, DdNode * bG, int * pPermute ) +{ + DdNode * bF0, * bF1, * bG0, * bG1, * bRes0, * bRes1, * bRes, * bVar; + int LevF, LevG, Lev; + + // if F == 0, return 0 + if ( bF == Cudd_Not(ddF->one) ) + return Cudd_Not(ddF->one); + // if G == 0, return 0 + if ( bG == Cudd_Not(ddG->one) ) + return Cudd_Not(ddF->one); + // if G == 1, return F + if ( bG == ddG->one ) + return bF; + // cannot use F == 1, because the var order of G has to be changed + + // check cache + if ( //(Cudd_Regular(bF)->ref != 1 || Cudd_Regular(bG)->ref != 1) && + (bRes = cuddHashTableLookup2(table, bF, bG)) ) + return bRes; + Counter++; + + if ( ddF->TimeStop && Abc_Clock() > ddF->TimeStop ) + return NULL; + if ( ddG->TimeStop && Abc_Clock() > ddG->TimeStop ) + return NULL; + + // find the topmost variable in F and G using var order of F + LevF = cuddI( ddF, Cudd_Regular(bF)->index ); + LevG = cuddI( ddF, pPermute ? pPermute[Cudd_Regular(bG)->index] : Cudd_Regular(bG)->index ); + Lev = Abc_MinInt( LevF, LevG ); + assert( Lev < ddF->size ); + bVar = ddF->vars[ddF->invperm[Lev]]; + + // cofactor + bF0 = (Lev < LevF) ? bF : Cudd_NotCond( cuddE(Cudd_Regular(bF)), Cudd_IsComplement(bF) ); + bF1 = (Lev < LevF) ? bF : Cudd_NotCond( cuddT(Cudd_Regular(bF)), Cudd_IsComplement(bF) ); + bG0 = (Lev < LevG) ? bG : Cudd_NotCond( cuddE(Cudd_Regular(bG)), Cudd_IsComplement(bG) ); + bG1 = (Lev < LevG) ? bG : Cudd_NotCond( cuddT(Cudd_Regular(bG)), Cudd_IsComplement(bG) ); + + // call for cofactors + bRes0 = extraBddAndPermute( table, ddF, bF0, ddG, bG0, pPermute ); + if ( bRes0 == NULL ) + return NULL; + cuddRef( bRes0 ); + // call for cofactors + bRes1 = extraBddAndPermute( table, ddF, bF1, ddG, bG1, pPermute ); + if ( bRes1 == NULL ) + { + Cudd_IterDerefBdd( ddF, bRes0 ); + return NULL; + } + cuddRef( bRes1 ); + + // compose the result + bRes = cuddBddIteRecur( ddF, bVar, bRes1, bRes0 ); + if ( bRes == NULL ) + { + Cudd_IterDerefBdd( ddF, bRes0 ); + Cudd_IterDerefBdd( ddF, bRes1 ); + return NULL; + } + cuddRef( bRes ); + Cudd_IterDerefBdd( ddF, bRes0 ); + Cudd_IterDerefBdd( ddF, bRes1 ); + + // cache the result +// if ( Cudd_Regular(bF)->ref != 1 || Cudd_Regular(bG)->ref != 1 ) + { + ptrint fanout = (ptrint)Cudd_Regular(bF)->ref * Cudd_Regular(bG)->ref; + cuddSatDec(fanout); + cuddHashTableInsert2( table, bF, bG, bRes, fanout ); + } + cuddDeref( bRes ); + return bRes; +} + +/**Function************************************************************* + + Synopsis [Testbench.] + + Description [This procedure takes BDD manager ddF and two BDDs + in this manager (bF and bG). It creates a new manager ddG, + transfers bG into it and then reorders it, resulting in bG2. + Then it tries to compute the product of bF and bG2 in ddF.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_TestAndPerm( DdManager * ddF, DdNode * bF, DdNode * bG ) +{ + DdManager * ddG; + DdNode * bG2, * bRes1, * bRes2; + abctime clk; + // disable variable ordering in ddF + Cudd_AutodynDisable( ddF ); + + // create new BDD manager + ddG = Cudd_Init( ddF->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + // transfer BDD into it + Cudd_ShuffleHeap( ddG, ddF->invperm ); + bG2 = Extra_TransferLevelByLevel( ddF, ddG, bG ); Cudd_Ref( bG2 ); + // reorder the new manager + Cudd_ReduceHeap( ddG, CUDD_REORDER_SYMM_SIFT, 1 ); + + // compute the result +clk = Abc_Clock(); + bRes1 = Cudd_bddAnd( ddF, bF, bG ); Cudd_Ref( bRes1 ); +Abc_PrintTime( 1, "Runtime of Cudd_bddAnd ", Abc_Clock() - clk ); + + // compute the result +Counter = 0; +clk = Abc_Clock(); + bRes2 = Extra_bddAndPermute( ddF, bF, ddG, bG2, NULL ); Cudd_Ref( bRes2 ); +Abc_PrintTime( 1, "Runtime of new procedure", Abc_Clock() - clk ); +printf( "Recursive calls = %d\n", Counter ); +printf( "|F| =%6d |G| =%6d |H| =%6d |F|*|G| =%9d ", + Cudd_DagSize(bF), Cudd_DagSize(bG), Cudd_DagSize(bRes2), + Cudd_DagSize(bF) * Cudd_DagSize(bG) ); + + if ( bRes1 == bRes2 ) + printf( "Result verified.\n\n" ); + else + printf( "Result is incorrect.\n\n" ); + + Cudd_RecursiveDeref( ddF, bRes1 ); + Cudd_RecursiveDeref( ddF, bRes2 ); + // quit the new manager + Cudd_RecursiveDeref( ddG, bG2 ); + Extra_StopManager( ddG ); + + // re-enable variable ordering in ddF + Cudd_AutodynEnable( ddF, CUDD_REORDER_SYMM_SIFT ); +} + +/**Function************************************************************* + + Synopsis [Writes ZDD into a PLA file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_zddDumpPla( DdManager * dd, DdNode * F, int nVars, char * pFileName ) +{ + DdGen *gen; + char * pCube; + int * pPath, i; + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for writing.\n", pFileName ); + return; + } + fprintf( pFile, "# PLA file dumped by Extra_zddDumpPla() in ABC\n" ); + fprintf( pFile, ".i %d\n", nVars ); + fprintf( pFile, ".o 1\n" ); + pCube = ABC_CALLOC( char, dd->sizeZ ); + Cudd_zddForeachPath( dd, F, gen, pPath ) + { + for ( i = 0; i < nVars; i++ ) + pCube[i] = '-'; + for ( i = 0; i < nVars; i++ ) + if ( pPath[2*i] == 1 || pPath[2*i+1] == 1 ) + pCube[i] = '0' + (pPath[2*i] == 1); + fprintf( pFile, "%s 1\n", pCube ); + } + fprintf( pFile, ".e\n\n" ); + fclose( pFile ); + ABC_FREE( pCube ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/extrab/extraBddSymm.c b/src/bdd/extrab/extraBddSymm.c new file mode 100644 index 00000000..9dd2c8e5 --- /dev/null +++ b/src/bdd/extrab/extraBddSymm.c @@ -0,0 +1,1474 @@ +/**CFile**************************************************************** + + FileName [extraBddSymm.c] + + PackageName [extra] + + Synopsis [Efficient methods to compute the information about + symmetric variables using the algorithm presented in the paper: + A. Mishchenko. Fast Computation of Symmetries in Boolean Functions. + Transactions on CAD, Nov. 2003.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - September 1, 2003.] + + Revision [$Id: extraBddSymm.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "extraBdd.h" + +ABC_NAMESPACE_IMPL_START + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +#define DD_GET_SYMM_VARS_TAG 0x0a /* former DD_BDD_XOR_EXIST_ABSTRACT_TAG */ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Computes the classical symmetry information for the function.] + + Description [Returns the symmetry information in the form of Extra_SymmInfo_t structure.] + + SideEffects [If the ZDD variables are not derived from BDD variables with + multiplicity 2, this function may derive them in a wrong way.] + + SeeAlso [] + +******************************************************************************/ +Extra_SymmInfo_t * Extra_SymmPairsCompute( + DdManager * dd, /* the manager */ + DdNode * bFunc) /* the function whose symmetries are computed */ +{ + DdNode * bSupp; + DdNode * zRes; + Extra_SymmInfo_t * p; + + bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); + zRes = Extra_zddSymmPairsCompute( dd, bFunc, bSupp ); Cudd_Ref( zRes ); + + p = Extra_SymmPairsCreateFromZdd( dd, zRes, bSupp ); + + Cudd_RecursiveDeref( dd, bSupp ); + Cudd_RecursiveDerefZdd( dd, zRes ); + + return p; + +} /* end of Extra_SymmPairsCompute */ + + +/**Function******************************************************************** + + Synopsis [Computes the classical symmetry information as a ZDD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_zddSymmPairsCompute( + DdManager * dd, /* the DD manager */ + DdNode * bF, + DdNode * bVars) +{ + DdNode * res; + do { + dd->reordered = 0; + res = extraZddSymmPairsCompute( dd, bF, bVars ); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_zddSymmPairsCompute */ + +/**Function******************************************************************** + + Synopsis [Returns a singleton-set ZDD containing all variables that are symmetric with the given one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_zddGetSymmetricVars( + DdManager * dd, /* the DD manager */ + DdNode * bF, /* the first function - originally, the positive cofactor */ + DdNode * bG, /* the second fucntion - originally, the negative cofactor */ + DdNode * bVars) /* the set of variables, on which F and G depend */ +{ + DdNode * res; + do { + dd->reordered = 0; + res = extraZddGetSymmetricVars( dd, bF, bG, bVars ); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_zddGetSymmetricVars */ + + +/**Function******************************************************************** + + Synopsis [Converts a set of variables into a set of singleton subsets.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_zddGetSingletons( + DdManager * dd, /* the DD manager */ + DdNode * bVars) /* the set of variables */ +{ + DdNode * res; + do { + dd->reordered = 0; + res = extraZddGetSingletons( dd, bVars ); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_zddGetSingletons */ + +/**Function******************************************************************** + + Synopsis [Filters the set of variables using the support of the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_bddReduceVarSet( + DdManager * dd, /* the DD manager */ + DdNode * bVars, /* the set of variables to be reduced */ + DdNode * bF) /* the function whose support is used for reduction */ +{ + DdNode * res; + do { + dd->reordered = 0; + res = extraBddReduceVarSet( dd, bVars, bF ); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_bddReduceVarSet */ + + +/**Function******************************************************************** + + Synopsis [Allocates symmetry information structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +Extra_SymmInfo_t * Extra_SymmPairsAllocate( int nVars ) +{ + int i; + Extra_SymmInfo_t * p; + + // allocate and clean the storage for symmetry info + p = ABC_ALLOC( Extra_SymmInfo_t, 1 ); + memset( p, 0, sizeof(Extra_SymmInfo_t) ); + p->nVars = nVars; + p->pVars = ABC_ALLOC( int, nVars ); + p->pSymms = ABC_ALLOC( char *, nVars ); + p->pSymms[0] = ABC_ALLOC( char , nVars * nVars ); + memset( p->pSymms[0], 0, nVars * nVars * sizeof(char) ); + + for ( i = 1; i < nVars; i++ ) + p->pSymms[i] = p->pSymms[i-1] + nVars; + + return p; +} /* end of Extra_SymmPairsAllocate */ + +/**Function******************************************************************** + + Synopsis [Deallocates symmetry information structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Extra_SymmPairsDissolve( Extra_SymmInfo_t * p ) +{ + ABC_FREE( p->pVars ); + ABC_FREE( p->pSymms[0] ); + ABC_FREE( p->pSymms ); + ABC_FREE( p ); +} /* end of Extra_SymmPairsDissolve */ + +/**Function******************************************************************** + + Synopsis [Allocates symmetry information structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Extra_SymmPairsPrint( Extra_SymmInfo_t * p ) +{ + int i, k; + printf( "\n" ); + for ( i = 0; i < p->nVars; i++ ) + { + for ( k = 0; k <= i; k++ ) + printf( " " ); + for ( k = i+1; k < p->nVars; k++ ) + if ( p->pSymms[i][k] ) + printf( "1" ); + else + printf( "." ); + printf( "\n" ); + } +} /* end of Extra_SymmPairsPrint */ + + +/**Function******************************************************************** + + Synopsis [Creates the symmetry information structure from ZDD.] + + Description [ZDD representation of symmetries is the set of cubes, each + of which has two variables in the positive polarity. These variables correspond + to the symmetric variable pair.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +Extra_SymmInfo_t * Extra_SymmPairsCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bSupp ) +{ + int i; + int nSuppSize; + Extra_SymmInfo_t * p; + int * pMapVars2Nums; + DdNode * bTemp; + DdNode * zSet, * zCube, * zTemp; + int iVar1, iVar2; + + nSuppSize = Extra_bddSuppSize( dd, bSupp ); + + // allocate and clean the storage for symmetry info + p = Extra_SymmPairsAllocate( nSuppSize ); + + // allocate the storage for the temporary map + pMapVars2Nums = ABC_ALLOC( int, dd->size ); + memset( pMapVars2Nums, 0, dd->size * sizeof(int) ); + + // assign the variables + p->nVarsMax = dd->size; +// p->nNodes = Cudd_DagSize( zPairs ); + p->nNodes = 0; + for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ ) + { + p->pVars[i] = bTemp->index; + pMapVars2Nums[bTemp->index] = i; + } + + // write the symmetry info into the structure + zSet = zPairs; Cudd_Ref( zSet ); + while ( zSet != z0 ) + { + // get the next cube + zCube = Extra_zddSelectOneSubset( dd, zSet ); Cudd_Ref( zCube ); + + // add these two variables to the data structure + assert( cuddT( cuddT(zCube) ) == z1 ); + iVar1 = zCube->index/2; + iVar2 = cuddT(zCube)->index/2; + if ( pMapVars2Nums[iVar1] < pMapVars2Nums[iVar2] ) + p->pSymms[ pMapVars2Nums[iVar1] ][ pMapVars2Nums[iVar2] ] = 1; + else + p->pSymms[ pMapVars2Nums[iVar2] ][ pMapVars2Nums[iVar1] ] = 1; + // count the symmetric pairs + p->nSymms ++; + + // update the cuver and deref the cube + zSet = Cudd_zddDiff( dd, zTemp = zSet, zCube ); Cudd_Ref( zSet ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zCube ); + + } // for each cube + Cudd_RecursiveDerefZdd( dd, zSet ); + + ABC_FREE( pMapVars2Nums ); + return p; + +} /* end of Extra_SymmPairsCreateFromZdd */ + + +/**Function******************************************************************** + + Synopsis [Checks the possibility of two variables being symmetric.] + + Description [Returns 0 if vars are not symmetric. Return 1 if vars can be symmetric.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Extra_bddCheckVarsSymmetric( + DdManager * dd, /* the DD manager */ + DdNode * bF, + int iVar1, + int iVar2) +{ + DdNode * bVars; + int Res; + +// return 1; + + assert( iVar1 != iVar2 ); + assert( iVar1 < dd->size ); + assert( iVar2 < dd->size ); + + bVars = Cudd_bddAnd( dd, dd->vars[iVar1], dd->vars[iVar2] ); Cudd_Ref( bVars ); + + Res = (int)( extraBddCheckVarsSymmetric( dd, bF, bVars ) == b1 ); + + Cudd_RecursiveDeref( dd, bVars ); + + return Res; +} /* end of Extra_bddCheckVarsSymmetric */ + + +/**Function******************************************************************** + + Synopsis [Computes the classical symmetry information for the function.] + + Description [Uses the naive way of comparing cofactors.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +Extra_SymmInfo_t * Extra_SymmPairsComputeNaive( DdManager * dd, DdNode * bFunc ) +{ + DdNode * bSupp, * bTemp; + int nSuppSize; + Extra_SymmInfo_t * p; + int i, k; + + // compute the support + bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); + nSuppSize = Extra_bddSuppSize( dd, bSupp ); +//printf( "Support = %d. ", nSuppSize ); +//Extra_bddPrint( dd, bSupp ); +//printf( "%d ", nSuppSize ); + + // allocate the storage for symmetry info + p = Extra_SymmPairsAllocate( nSuppSize ); + + // assign the variables + p->nVarsMax = dd->size; + for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ ) + p->pVars[i] = bTemp->index; + + // go through the candidate pairs and check using Idea1 + for ( i = 0; i < nSuppSize; i++ ) + for ( k = i+1; k < nSuppSize; k++ ) + { + p->pSymms[k][i] = p->pSymms[i][k] = Extra_bddCheckVarsSymmetricNaive( dd, bFunc, p->pVars[i], p->pVars[k] ); + if ( p->pSymms[i][k] ) + p->nSymms++; + } + + Cudd_RecursiveDeref( dd, bSupp ); + return p; + +} /* end of Extra_SymmPairsComputeNaive */ + +/**Function******************************************************************** + + Synopsis [Checks if the two variables are symmetric.] + + Description [Returns 0 if vars are not symmetric. Return 1 if vars are symmetric.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Extra_bddCheckVarsSymmetricNaive( + DdManager * dd, /* the DD manager */ + DdNode * bF, + int iVar1, + int iVar2) +{ + DdNode * bCube1, * bCube2; + DdNode * bCof01, * bCof10; + int Res; + + assert( iVar1 != iVar2 ); + assert( iVar1 < dd->size ); + assert( iVar2 < dd->size ); + + bCube1 = Cudd_bddAnd( dd, Cudd_Not( dd->vars[iVar1] ), dd->vars[iVar2] ); Cudd_Ref( bCube1 ); + bCube2 = Cudd_bddAnd( dd, Cudd_Not( dd->vars[iVar2] ), dd->vars[iVar1] ); Cudd_Ref( bCube2 ); + + bCof01 = Cudd_Cofactor( dd, bF, bCube1 ); Cudd_Ref( bCof01 ); + bCof10 = Cudd_Cofactor( dd, bF, bCube2 ); Cudd_Ref( bCof10 ); + + Res = (int)( bCof10 == bCof01 ); + + Cudd_RecursiveDeref( dd, bCof01 ); + Cudd_RecursiveDeref( dd, bCof10 ); + Cudd_RecursiveDeref( dd, bCube1 ); + Cudd_RecursiveDeref( dd, bCube2 ); + + return Res; +} /* end of Extra_bddCheckVarsSymmetricNaive */ + + +/**Function******************************************************************** + + Synopsis [Builds ZDD representing the set of fixed-size variable tuples.] + + Description [Creates ZDD of all combinations of variables in Support that + is represented by a BDD.] + + SideEffects [New ZDD variables are created if indices of the variables + present in the combination are larger than the currently + allocated number of ZDD variables.] + + SeeAlso [] + +******************************************************************************/ +DdNode* Extra_zddTuplesFromBdd( + DdManager * dd, /* the DD manager */ + int K, /* the number of variables in tuples */ + DdNode * bVarsN) /* the set of all variables represented as a BDD */ +{ + DdNode *zRes; + int autoDynZ; + + autoDynZ = dd->autoDynZ; + dd->autoDynZ = 0; + + do { + /* transform the numeric arguments (K) into a DdNode* argument; + * this allows us to use the standard internal CUDD cache */ + DdNode *bVarSet = bVarsN, *bVarsK = bVarsN; + int nVars = 0, i; + + /* determine the number of variables in VarSet */ + while ( bVarSet != b1 ) + { + nVars++; + /* make sure that the VarSet is a cube */ + if ( cuddE( bVarSet ) != b0 ) + return NULL; + bVarSet = cuddT( bVarSet ); + } + /* make sure that the number of variables in VarSet is less or equal + that the number of variables that should be present in the tuples + */ + if ( K > nVars ) + return NULL; + + /* the second argument in the recursive call stannds for ; + * reate the first argument, which stands for + * as when we are talking about the tuple of out of */ + for ( i = 0; i < nVars-K; i++ ) + bVarsK = cuddT( bVarsK ); + + dd->reordered = 0; + zRes = extraZddTuplesFromBdd(dd, bVarsK, bVarsN ); + + } while (dd->reordered == 1); + dd->autoDynZ = autoDynZ; + return zRes; + +} /* end of Extra_zddTuplesFromBdd */ + +/**Function******************************************************************** + + Synopsis [Selects one subset from the set of subsets represented by a ZDD.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode* Extra_zddSelectOneSubset( + DdManager * dd, /* the DD manager */ + DdNode * zS) /* the ZDD */ +{ + DdNode *res; + do { + dd->reordered = 0; + res = extraZddSelectOneSubset(dd, zS); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_zddSelectOneSubset */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Performs a recursive step of Extra_SymmPairsCompute.] + + Description [Returns the set of symmetric variable pairs represented as a set + of two-literal ZDD cubes. Both variables always appear in the positive polarity + in the cubes. This function works without building new BDD nodes. Some relatively + small number of ZDD nodes may be built to ensure proper bookkeeping of the + symmetry information.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * +extraZddSymmPairsCompute( + DdManager * dd, /* the manager */ + DdNode * bFunc, /* the function whose symmetries are computed */ + DdNode * bVars ) /* the set of variables on which this function depends */ +{ + DdNode * zRes; + DdNode * bFR = Cudd_Regular(bFunc); + + if ( cuddIsConstant(bFR) ) + { + int nVars, i; + + // determine how many vars are in the bVars + nVars = Extra_bddSuppSize( dd, bVars ); + if ( nVars < 2 ) + return z0; + else + { + DdNode * bVarsK; + + // create the BDD bVarsK corresponding to K = 2; + bVarsK = bVars; + for ( i = 0; i < nVars-2; i++ ) + bVarsK = cuddT( bVarsK ); + return extraZddTuplesFromBdd( dd, bVarsK, bVars ); + } + } + assert( bVars != b1 ); + + if ( (zRes = cuddCacheLookup2Zdd(dd, extraZddSymmPairsCompute, bFunc, bVars)) ) + return zRes; + else + { + DdNode * zRes0, * zRes1; + DdNode * zTemp, * zPlus, * zSymmVars; + DdNode * bF0, * bF1; + DdNode * bVarsNew; + int nVarsExtra; + int LevelF; + + // every variable in bF should be also in bVars, therefore LevelF cannot be above LevelV + // if LevelF is below LevelV, scroll through the vars in bVars to the same level as F + // count how many extra vars are there in bVars + nVarsExtra = 0; + LevelF = dd->perm[bFR->index]; + for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) ) + nVarsExtra++; + // the indexes (level) of variables should be synchronized now + assert( bFR->index == bVarsNew->index ); + + // cofactor the function + if ( bFR != bFunc ) // bFunc is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + + // solve subproblems + zRes0 = extraZddSymmPairsCompute( dd, bF0, cuddT(bVarsNew) ); + if ( zRes0 == NULL ) + return NULL; + cuddRef( zRes0 ); + + // if there is no symmetries in the negative cofactor + // there is no need to test the positive cofactor + if ( zRes0 == z0 ) + zRes = zRes0; // zRes takes reference + else + { + zRes1 = extraZddSymmPairsCompute( dd, bF1, cuddT(bVarsNew) ); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + return NULL; + } + cuddRef( zRes1 ); + + // only those variables are pair-wise symmetric + // that are pair-wise symmetric in both cofactors + // therefore, intersect the solutions + zRes = cuddZddIntersect( dd, zRes0, zRes1 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + } + + // consider the current top-most variable and find all the vars + // that are pairwise symmetric with it + // these variables are returned as a set of ZDD singletons + zSymmVars = extraZddGetSymmetricVars( dd, bF1, bF0, cuddT(bVarsNew) ); + if ( zSymmVars == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( zSymmVars ); + + // attach the topmost variable to the set, to get the variable pairs + // use the positive polarity ZDD variable for the purpose + + // there is no need to do so, if zSymmVars is empty + if ( zSymmVars == z0 ) + Cudd_RecursiveDerefZdd( dd, zSymmVars ); + else + { + zPlus = cuddZddGetNode( dd, 2*bFR->index, zSymmVars, z0 ); + if ( zPlus == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + Cudd_RecursiveDerefZdd( dd, zSymmVars ); + return NULL; + } + cuddRef( zPlus ); + cuddDeref( zSymmVars ); + + // add these variable pairs to the result + zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + } + + // only zRes is referenced at this point + + // if we skipped some variables, these variables cannot be symmetric with + // any variables that are currently in the support of bF, but they can be + // symmetric with the variables that are in bVars but not in the support of bF + if ( nVarsExtra ) + { + // it is possible to improve this step: + // (1) there is no need to enter here, if nVarsExtra < 2 + + // create the set of topmost nVarsExtra in bVars + DdNode * bVarsExtra; + int nVars; + + // remove from bVars all the variable that are in the support of bFunc + bVarsExtra = extraBddReduceVarSet( dd, bVars, bFunc ); + if ( bVarsExtra == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( bVarsExtra ); + + // determine how many vars are in the bVarsExtra + nVars = Extra_bddSuppSize( dd, bVarsExtra ); + if ( nVars < 2 ) + { + Cudd_RecursiveDeref( dd, bVarsExtra ); + } + else + { + int i; + DdNode * bVarsK; + + // create the BDD bVarsK corresponding to K = 2; + bVarsK = bVarsExtra; + for ( i = 0; i < nVars-2; i++ ) + bVarsK = cuddT( bVarsK ); + + // create the 2 variable tuples + zPlus = extraZddTuplesFromBdd( dd, bVarsK, bVarsExtra ); + if ( zPlus == NULL ) + { + Cudd_RecursiveDeref( dd, bVarsExtra ); + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( zPlus ); + Cudd_RecursiveDeref( dd, bVarsExtra ); + + // add these to the result + zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + } + } + cuddDeref( zRes ); + + + /* insert the result into cache */ + cuddCacheInsert2(dd, extraZddSymmPairsCompute, bFunc, bVars, zRes); + return zRes; + } +} /* end of extraZddSymmPairsCompute */ + +/**Function******************************************************************** + + Synopsis [Performs a recursive step of Extra_zddGetSymmetricVars.] + + Description [Returns the set of ZDD singletons, containing those positive + ZDD variables that correspond to BDD variables x, for which it is true + that bF(x=0) == bG(x=1).] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * extraZddGetSymmetricVars( + DdManager * dd, /* the DD manager */ + DdNode * bF, /* the first function - originally, the positive cofactor */ + DdNode * bG, /* the second function - originally, the negative cofactor */ + DdNode * bVars) /* the set of variables, on which F and G depend */ +{ + DdNode * zRes; + DdNode * bFR = Cudd_Regular(bF); + DdNode * bGR = Cudd_Regular(bG); + + if ( cuddIsConstant(bFR) && cuddIsConstant(bGR) ) + { + if ( bF == bG ) + return extraZddGetSingletons( dd, bVars ); + else + return z0; + } + assert( bVars != b1 ); + + if ( (zRes = cuddCacheLookupZdd(dd, DD_GET_SYMM_VARS_TAG, bF, bG, bVars)) ) + return zRes; + else + { + DdNode * zRes0, * zRes1; + DdNode * zPlus, * zTemp; + DdNode * bF0, * bF1; + DdNode * bG0, * bG1; + DdNode * bVarsNew; + + int LevelF = cuddI(dd,bFR->index); + int LevelG = cuddI(dd,bGR->index); + int LevelFG; + + if ( LevelF < LevelG ) + LevelFG = LevelF; + else + LevelFG = LevelG; + + // at least one of the arguments is not a constant + assert( LevelFG < dd->size ); + + // every variable in bF and bG should be also in bVars, therefore LevelFG cannot be above LevelV + // if LevelFG is below LevelV, scroll through the vars in bVars to the same level as LevelFG + for ( bVarsNew = bVars; LevelFG > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) ); + assert( LevelFG == dd->perm[bVarsNew->index] ); + + // cofactor the functions + if ( LevelF == LevelFG ) + { + if ( bFR != bF ) // bF is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + } + else + bF0 = bF1 = bF; + + if ( LevelG == LevelFG ) + { + if ( bGR != bG ) // bG is complemented + { + bG0 = Cudd_Not( cuddE(bGR) ); + bG1 = Cudd_Not( cuddT(bGR) ); + } + else + { + bG0 = cuddE(bGR); + bG1 = cuddT(bGR); + } + } + else + bG0 = bG1 = bG; + + // solve subproblems + zRes0 = extraZddGetSymmetricVars( dd, bF0, bG0, cuddT(bVarsNew) ); + if ( zRes0 == NULL ) + return NULL; + cuddRef( zRes0 ); + + // if there is not symmetries in the negative cofactor + // there is no need to test the positive cofactor + if ( zRes0 == z0 ) + zRes = zRes0; // zRes takes reference + else + { + zRes1 = extraZddGetSymmetricVars( dd, bF1, bG1, cuddT(bVarsNew) ); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + return NULL; + } + cuddRef( zRes1 ); + + // only those variables should belong to the resulting set + // for which the property is true for both cofactors + zRes = cuddZddIntersect( dd, zRes0, zRes1 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + } + + // add one more singleton if the property is true for this variable + if ( bF0 == bG1 ) + { + zPlus = cuddZddGetNode( dd, 2*bVarsNew->index, z1, z0 ); + if ( zPlus == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( zPlus ); + + // add these variable pairs to the result + zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + } + + if ( bF == bG && bVars != bVarsNew ) + { + // if the functions are equal, so are their cofactors + // add those variables from V that are above F and G + + DdNode * bVarsExtra; + + assert( LevelFG > dd->perm[bVars->index] ); + + // create the BDD of the extra variables + bVarsExtra = cuddBddExistAbstractRecur( dd, bVars, bVarsNew ); + if ( bVarsExtra == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( bVarsExtra ); + + zPlus = extraZddGetSingletons( dd, bVarsExtra ); + if ( zPlus == NULL ) + { + Cudd_RecursiveDeref( dd, bVarsExtra ); + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( zPlus ); + Cudd_RecursiveDeref( dd, bVarsExtra ); + + // add these to the result + zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + } + cuddDeref( zRes ); + + cuddCacheInsert( dd, DD_GET_SYMM_VARS_TAG, bF, bG, bVars, zRes ); + return zRes; + } +} /* end of extraZddGetSymmetricVars */ + + +/**Function******************************************************************** + + Synopsis [Performs a recursive step of Extra_zddGetSingletons.] + + Description [Returns the set of ZDD singletons, containing those positive + polarity ZDD variables that correspond to the BDD variables in bVars.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * extraZddGetSingletons( + DdManager * dd, /* the DD manager */ + DdNode * bVars) /* the set of variables */ +{ + DdNode * zRes; + + if ( bVars == b1 ) +// if ( bVars == b0 ) // bug fixed by Jin Zhang, Jan 23, 2004 + return z1; + + if ( (zRes = cuddCacheLookup1Zdd(dd, extraZddGetSingletons, bVars)) ) + return zRes; + else + { + DdNode * zTemp, * zPlus; + + // solve subproblem + zRes = extraZddGetSingletons( dd, cuddT(bVars) ); + if ( zRes == NULL ) + return NULL; + cuddRef( zRes ); + + zPlus = cuddZddGetNode( dd, 2*bVars->index, z1, z0 ); + if ( zPlus == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( zPlus ); + + // add these to the result + zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + cuddDeref( zRes ); + + cuddCacheInsert1( dd, extraZddGetSingletons, bVars, zRes ); + return zRes; + } +} /* end of extraZddGetSingletons */ + + +/**Function******************************************************************** + + Synopsis [Performs a recursive step of Extra_bddReduceVarSet.] + + Description [Returns the set of all variables in the given set that are not in the + support of the given function.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * extraBddReduceVarSet( + DdManager * dd, /* the DD manager */ + DdNode * bVars, /* the set of variables to be reduced */ + DdNode * bF) /* the function whose support is used for reduction */ +{ + DdNode * bRes; + DdNode * bFR = Cudd_Regular(bF); + + if ( cuddIsConstant(bFR) || bVars == b1 ) + return bVars; + + if ( (bRes = cuddCacheLookup2(dd, extraBddReduceVarSet, bVars, bF)) ) + return bRes; + else + { + DdNode * bF0, * bF1; + DdNode * bVarsThis, * bVarsLower, * bTemp; + int LevelF; + + // if LevelF is below LevelV, scroll through the vars in bVars + LevelF = dd->perm[bFR->index]; + for ( bVarsThis = bVars; LevelF > cuddI(dd,bVarsThis->index); bVarsThis = cuddT(bVarsThis) ); + // scroll also through the current var, because it should be not be added + if ( LevelF == cuddI(dd,bVarsThis->index) ) + bVarsLower = cuddT(bVarsThis); + else + bVarsLower = bVarsThis; + + // cofactor the function + if ( bFR != bF ) // bFunc is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + + // solve subproblems + bRes = extraBddReduceVarSet( dd, bVarsLower, bF0 ); + if ( bRes == NULL ) + return NULL; + cuddRef( bRes ); + + bRes = extraBddReduceVarSet( dd, bTemp = bRes, bF1 ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref( dd, bTemp ); + return NULL; + } + cuddRef( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + + // the current var should not be added + // add the skipped vars + if ( bVarsThis != bVars ) + { + DdNode * bVarsExtra; + + // extract the skipped variables + bVarsExtra = cuddBddExistAbstractRecur( dd, bVars, bVarsThis ); + if ( bVarsExtra == NULL ) + { + Cudd_RecursiveDeref( dd, bRes ); + return NULL; + } + cuddRef( bVarsExtra ); + + // add these variables + bRes = cuddBddAndRecur( dd, bTemp = bRes, bVarsExtra ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bVarsExtra ); + return NULL; + } + cuddRef( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bVarsExtra ); + } + cuddDeref( bRes ); + + cuddCacheInsert2( dd, extraBddReduceVarSet, bVars, bF, bRes ); + return bRes; + } +} /* end of extraBddReduceVarSet */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Extra_bddCheckVarsSymmetric().] + + Description [Returns b0 if the variables are not symmetric. Returns b1 if the + variables can be symmetric. The variables are represented in the form of a + two-variable cube. In case the cube contains one variable (below Var1 level), + the cube's pointer is complemented if the variable Var1 occurred on the + current path; otherwise, the cube's pointer is regular. Uses additional + complemented bit (Hash_Not) to mark the result if in the BDD rooted that this + node there is a branch passing though the node labeled with Var2.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * extraBddCheckVarsSymmetric( + DdManager * dd, /* the DD manager */ + DdNode * bF, + DdNode * bVars) +{ + DdNode * bRes; + + if ( bF == b0 ) + return b1; + + assert( bVars != b1 ); + + if ( (bRes = cuddCacheLookup2(dd, extraBddCheckVarsSymmetric, bF, bVars)) ) + return bRes; + else + { + DdNode * bRes0, * bRes1; + DdNode * bF0, * bF1; + DdNode * bFR = Cudd_Regular(bF); + int LevelF = cuddI(dd,bFR->index); + + DdNode * bVarsR = Cudd_Regular(bVars); + int fVar1Pres; + int iLev1; + int iLev2; + + if ( bVarsR != bVars ) // cube's pointer is complemented + { + assert( cuddT(bVarsR) == b1 ); + fVar1Pres = 1; // the first var is present on the path + iLev1 = -1; // we are already below the first var level + iLev2 = dd->perm[bVarsR->index]; // the level of the second var + } + else // cube's pointer is NOT complemented + { + fVar1Pres = 0; // the first var is absent on the path + if ( cuddT(bVars) == b1 ) + { + iLev1 = -1; // we are already below the first var level + iLev2 = dd->perm[bVars->index]; // the level of the second var + } + else + { + assert( cuddT(cuddT(bVars)) == b1 ); + iLev1 = dd->perm[bVars->index]; // the level of the first var + iLev2 = dd->perm[cuddT(bVars)->index]; // the level of the second var + } + } + + // cofactor the function + // the cofactors are needed only if we are above the second level + if ( LevelF < iLev2 ) + { + if ( bFR != bF ) // bFunc is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + } + else + bF0 = bF1 = NULL; + + // consider five cases: + // (1) F is above iLev1 + // (2) F is on the level iLev1 + // (3) F is between iLev1 and iLev2 + // (4) F is on the level iLev2 + // (5) F is below iLev2 + + // (1) F is above iLev1 + if ( LevelF < iLev1 ) + { + // the returned result cannot have the hash attribute + // because we still did not reach the level of Var1; + // the attribute never travels above the level of Var1 + bRes0 = extraBddCheckVarsSymmetric( dd, bF0, bVars ); +// assert( !Hash_IsComplement( bRes0 ) ); + assert( bRes0 != z0 ); + if ( bRes0 == b0 ) + bRes = b0; + else + bRes = extraBddCheckVarsSymmetric( dd, bF1, bVars ); +// assert( !Hash_IsComplement( bRes ) ); + assert( bRes != z0 ); + } + // (2) F is on the level iLev1 + else if ( LevelF == iLev1 ) + { + bRes0 = extraBddCheckVarsSymmetric( dd, bF0, Cudd_Not( cuddT(bVars) ) ); + if ( bRes0 == b0 ) + bRes = b0; + else + { + bRes1 = extraBddCheckVarsSymmetric( dd, bF1, Cudd_Not( cuddT(bVars) ) ); + if ( bRes1 == b0 ) + bRes = b0; + else + { +// if ( Hash_IsComplement( bRes0 ) || Hash_IsComplement( bRes1 ) ) + if ( bRes0 == z0 || bRes1 == z0 ) + bRes = b1; + else + bRes = b0; + } + } + } + // (3) F is between iLev1 and iLev2 + else if ( LevelF < iLev2 ) + { + bRes0 = extraBddCheckVarsSymmetric( dd, bF0, bVars ); + if ( bRes0 == b0 ) + bRes = b0; + else + { + bRes1 = extraBddCheckVarsSymmetric( dd, bF1, bVars ); + if ( bRes1 == b0 ) + bRes = b0; + else + { +// if ( Hash_IsComplement( bRes0 ) || Hash_IsComplement( bRes1 ) ) +// bRes = Hash_Not( b1 ); + if ( bRes0 == z0 || bRes1 == z0 ) + bRes = z0; + else + bRes = b1; + } + } + } + // (4) F is on the level iLev2 + else if ( LevelF == iLev2 ) + { + // this is the only place where the hash attribute (Hash_Not) can be added + // to the result; it can be added only if the path came through the node + // lebeled with Var1; therefore, the hash attribute cannot be returned + // to the caller function + if ( fVar1Pres ) +// bRes = Hash_Not( b1 ); + bRes = z0; + else + bRes = b0; + } + // (5) F is below iLev2 + else // if ( LevelF > iLev2 ) + { + // it is possible that the path goes through the node labeled by Var1 + // and still everything is okay; we do not label with Hash_Not here + // because the path does not go through node labeled by Var2 + bRes = b1; + } + + cuddCacheInsert2(dd, extraBddCheckVarsSymmetric, bF, bVars, bRes); + return bRes; + } +} /* end of extraBddCheckVarsSymmetric */ + +/**Function******************************************************************** + + Synopsis [Performs the reordering-sensitive step of Extra_zddTupleFromBdd().] + + Description [Generates in a bottom-up fashion ZDD for all combinations + composed of k variables out of variables belonging to Support.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode* extraZddTuplesFromBdd( + DdManager * dd, /* the DD manager */ + DdNode * bVarsK, /* the number of variables in tuples */ + DdNode * bVarsN) /* the set of all variables */ +{ + DdNode *zRes, *zRes0, *zRes1; + statLine(dd); + + /* terminal cases */ +/* if ( k < 0 || k > n ) + * return dd->zero; + * if ( n == 0 ) + * return dd->one; + */ + if ( cuddI( dd, bVarsK->index ) < cuddI( dd, bVarsN->index ) ) + return z0; + if ( bVarsN == b1 ) + return z1; + + /* check cache */ + zRes = cuddCacheLookup2Zdd(dd, extraZddTuplesFromBdd, bVarsK, bVarsN); + if (zRes) + return(zRes); + + /* ZDD in which this variable is 0 */ +/* zRes0 = extraZddTuplesFromBdd( dd, k, n-1 ); */ + zRes0 = extraZddTuplesFromBdd( dd, bVarsK, cuddT(bVarsN) ); + if ( zRes0 == NULL ) + return NULL; + cuddRef( zRes0 ); + + /* ZDD in which this variable is 1 */ +/* zRes1 = extraZddTuplesFromBdd( dd, k-1, n-1 ); */ + if ( bVarsK == b1 ) + { + zRes1 = z0; + cuddRef( zRes1 ); + } + else + { + zRes1 = extraZddTuplesFromBdd( dd, cuddT(bVarsK), cuddT(bVarsN) ); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + return NULL; + } + cuddRef( zRes1 ); + } + + /* compose Res0 and Res1 with the given ZDD variable */ + zRes = cuddZddGetNode( dd, 2*bVarsN->index, zRes1, zRes0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + return NULL; + } + cuddDeref( zRes0 ); + cuddDeref( zRes1 ); + + /* insert the result into cache */ + cuddCacheInsert2(dd, extraZddTuplesFromBdd, bVarsK, bVarsN, zRes); + return zRes; + +} /* end of extraZddTuplesFromBdd */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Extra_zddSelectOneSubset.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * extraZddSelectOneSubset( + DdManager * dd, + DdNode * zS ) +// selects one subset from the ZDD zS +// returns z0 if and only if zS is an empty set of cubes +{ + DdNode * zRes; + + if ( zS == z0 ) return z0; + if ( zS == z1 ) return z1; + + // check cache + if ( (zRes = cuddCacheLookup1Zdd( dd, extraZddSelectOneSubset, zS )) ) + return zRes; + else + { + DdNode * zS0, * zS1, * zTemp; + + zS0 = cuddE(zS); + zS1 = cuddT(zS); + + if ( zS0 != z0 ) + { + zRes = extraZddSelectOneSubset( dd, zS0 ); + if ( zRes == NULL ) + return NULL; + } + else // if ( zS0 == z0 ) + { + assert( zS1 != z0 ); + zRes = extraZddSelectOneSubset( dd, zS1 ); + if ( zRes == NULL ) + return NULL; + cuddRef( zRes ); + + zRes = cuddZddGetNode( dd, zS->index, zTemp = zRes, z0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + return NULL; + } + cuddDeref( zTemp ); + } + + // insert the result into cache + cuddCacheInsert1( dd, extraZddSelectOneSubset, zS, zRes ); + return zRes; + } +} /* end of extraZddSelectOneSubset */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static Functions */ +/*---------------------------------------------------------------------------*/ +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/extrab/extraBddTime.c b/src/bdd/extrab/extraBddTime.c new file mode 100644 index 00000000..dc9ff147 --- /dev/null +++ b/src/bdd/extrab/extraBddTime.c @@ -0,0 +1,660 @@ +/**CFile**************************************************************** + + FileName [extraBddTime.c] + + PackageName [extra] + + Synopsis [Procedures to control runtime in BDD operators.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - September 1, 2003.] + + Revision [$Id: extraBddTime.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $] + +***********************************************************************/ + +#include "extraBdd.h" + +ABC_NAMESPACE_IMPL_START + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#define CHECK_FACTOR 10 + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + + + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static DdNode * cuddBddAndRecurTime( DdManager * manager, DdNode * f, DdNode * g, int * pRecCalls, int TimeOut ); +static DdNode * cuddBddAndAbstractRecurTime( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube, int * pRecCalls, int TimeOut ); +static DdNode * extraTransferPermuteTime( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute, int TimeOut ); +static DdNode * extraTransferPermuteRecurTime( DdManager * ddS, DdManager * ddD, DdNode * f, st__table * table, int * Permute, int TimeOut ); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Computes the conjunction of two BDDs f and g.] + + Description [Computes the conjunction of two BDDs f and g. Returns a + pointer to the resulting BDD if successful; NULL if the intermediate + result blows up.] + + SideEffects [None] + + SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAndAbstract Cudd_bddIntersect + Cudd_bddOr Cudd_bddNand Cudd_bddNor Cudd_bddXor Cudd_bddXnor] + +******************************************************************************/ +DdNode * +Extra_bddAndTime( + DdManager * dd, + DdNode * f, + DdNode * g, + int TimeOut) +{ + DdNode *res; + int Counter = 0; + + do { + dd->reordered = 0; + res = cuddBddAndRecurTime(dd,f,g, &Counter, TimeOut); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_bddAndTime */ + +/**Function******************************************************************** + + Synopsis [Takes the AND of two BDDs and simultaneously abstracts the + variables in cube.] + + Description [Takes the AND of two BDDs and simultaneously abstracts + the variables in cube. The variables are existentially abstracted. + Returns a pointer to the result is successful; NULL otherwise. + Cudd_bddAndAbstract implements the semiring matrix multiplication + algorithm for the boolean semiring.] + + SideEffects [None] + + SeeAlso [Cudd_addMatrixMultiply Cudd_addTriangle Cudd_bddAnd] + +******************************************************************************/ +DdNode * +Extra_bddAndAbstractTime( + DdManager * manager, + DdNode * f, + DdNode * g, + DdNode * cube, + int TimeOut) +{ + DdNode *res; + int Counter = 0; + + do { + manager->reordered = 0; + res = cuddBddAndAbstractRecurTime(manager, f, g, cube, &Counter, TimeOut); + } while (manager->reordered == 1); + return(res); + +} /* end of Extra_bddAndAbstractTime */ + +/**Function******************************************************************** + + Synopsis [Convert a {A,B}DD from a manager to another with variable remapping.] + + Description [Convert a {A,B}DD from a manager to another one. The orders of the + variables in the two managers may be different. Returns a + pointer to the {A,B}DD in the destination manager if successful; NULL + otherwise. The i-th entry in the array Permute tells what is the index + of the i-th variable from the old manager in the new manager.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_TransferPermuteTime( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute, int TimeOut ) +{ + DdNode * bRes; + do + { + ddDestination->reordered = 0; + bRes = extraTransferPermuteTime( ddSource, ddDestination, f, Permute, TimeOut ); + } + while ( ddDestination->reordered == 1 ); + return ( bRes ); + +} /* end of Extra_TransferPermuteTime */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Implements the recursive step of Cudd_bddAnd.] + + Description [Implements the recursive step of Cudd_bddAnd by taking + the conjunction of two BDDs. Returns a pointer to the result is + successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddAnd] + +******************************************************************************/ +DdNode * +cuddBddAndRecurTime( + DdManager * manager, + DdNode * f, + DdNode * g, + int * pRecCalls, + int TimeOut) +{ + DdNode *F, *fv, *fnv, *G, *gv, *gnv; + DdNode *one, *r, *t, *e; + unsigned int topf, topg, index; + + statLine(manager); + one = DD_ONE(manager); + + /* Terminal cases. */ + F = Cudd_Regular(f); + G = Cudd_Regular(g); + if (F == G) { + if (f == g) return(f); + else return(Cudd_Not(one)); + } + if (F == one) { + if (f == one) return(g); + else return(f); + } + if (G == one) { + if (g == one) return(f); + else return(g); + } + + /* At this point f and g are not constant. */ + if (f > g) { /* Try to increase cache efficiency. */ + DdNode *tmp = f; + f = g; + g = tmp; + F = Cudd_Regular(f); + G = Cudd_Regular(g); + } + + /* Check cache. */ + if (F->ref != 1 || G->ref != 1) { + r = cuddCacheLookup2(manager, Cudd_bddAnd, f, g); + if (r != NULL) return(r); + } + +// if ( TimeOut && ((*pRecCalls)++ % CHECK_FACTOR) == 0 && TimeOut < Abc_Clock() ) + if ( TimeOut && Abc_Clock() > TimeOut ) + return NULL; + + /* Here we can skip the use of cuddI, because the operands are known + ** to be non-constant. + */ + topf = manager->perm[F->index]; + topg = manager->perm[G->index]; + + /* Compute cofactors. */ + if (topf <= topg) { + index = F->index; + fv = cuddT(F); + fnv = cuddE(F); + if (Cudd_IsComplement(f)) { + fv = Cudd_Not(fv); + fnv = Cudd_Not(fnv); + } + } else { + index = G->index; + fv = fnv = f; + } + + if (topg <= topf) { + gv = cuddT(G); + gnv = cuddE(G); + if (Cudd_IsComplement(g)) { + gv = Cudd_Not(gv); + gnv = Cudd_Not(gnv); + } + } else { + gv = gnv = g; + } + + t = cuddBddAndRecurTime(manager, fv, gv, pRecCalls, TimeOut); + if (t == NULL) return(NULL); + cuddRef(t); + + e = cuddBddAndRecurTime(manager, fnv, gnv, pRecCalls, TimeOut); + if (e == NULL) { + Cudd_IterDerefBdd(manager, t); + return(NULL); + } + cuddRef(e); + + if (t == e) { + r = t; + } else { + if (Cudd_IsComplement(t)) { + r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); + if (r == NULL) { + Cudd_IterDerefBdd(manager, t); + Cudd_IterDerefBdd(manager, e); + return(NULL); + } + r = Cudd_Not(r); + } else { + r = cuddUniqueInter(manager,(int)index,t,e); + if (r == NULL) { + Cudd_IterDerefBdd(manager, t); + Cudd_IterDerefBdd(manager, e); + return(NULL); + } + } + } + cuddDeref(e); + cuddDeref(t); + if (F->ref != 1 || G->ref != 1) + cuddCacheInsert2(manager, Cudd_bddAnd, f, g, r); + return(r); + +} /* end of cuddBddAndRecur */ + + +/**Function******************************************************************** + + Synopsis [Takes the AND of two BDDs and simultaneously abstracts the + variables in cube.] + + Description [Takes the AND of two BDDs and simultaneously abstracts + the variables in cube. The variables are existentially abstracted. + Returns a pointer to the result is successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddAndAbstract] + +******************************************************************************/ +DdNode * +cuddBddAndAbstractRecurTime( + DdManager * manager, + DdNode * f, + DdNode * g, + DdNode * cube, + int * pRecCalls, + int TimeOut) +{ + DdNode *F, *ft, *fe, *G, *gt, *ge; + DdNode *one, *zero, *r, *t, *e; + unsigned int topf, topg, topcube, top, index; + + statLine(manager); + one = DD_ONE(manager); + zero = Cudd_Not(one); + + /* Terminal cases. */ + if (f == zero || g == zero || f == Cudd_Not(g)) return(zero); + if (f == one && g == one) return(one); + + if (cube == one) { + return(cuddBddAndRecurTime(manager, f, g, pRecCalls, TimeOut)); + } + if (f == one || f == g) { + return(cuddBddExistAbstractRecur(manager, g, cube)); + } + if (g == one) { + return(cuddBddExistAbstractRecur(manager, f, cube)); + } + /* At this point f, g, and cube are not constant. */ + + if (f > g) { /* Try to increase cache efficiency. */ + DdNode *tmp = f; + f = g; + g = tmp; + } + + /* Here we can skip the use of cuddI, because the operands are known + ** to be non-constant. + */ + F = Cudd_Regular(f); + G = Cudd_Regular(g); + topf = manager->perm[F->index]; + topg = manager->perm[G->index]; + top = ddMin(topf, topg); + topcube = manager->perm[cube->index]; + + while (topcube < top) { + cube = cuddT(cube); + if (cube == one) { + return(cuddBddAndRecurTime(manager, f, g, pRecCalls, TimeOut)); + } + topcube = manager->perm[cube->index]; + } + /* Now, topcube >= top. */ + + /* Check cache. */ + if (F->ref != 1 || G->ref != 1) { + r = cuddCacheLookup(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube); + if (r != NULL) { + return(r); + } + } + +// if ( TimeOut && ((*pRecCalls)++ % CHECK_FACTOR) == 0 && TimeOut < Abc_Clock() ) + if ( TimeOut && Abc_Clock() > TimeOut ) + return NULL; + + if (topf == top) { + index = F->index; + ft = cuddT(F); + fe = cuddE(F); + if (Cudd_IsComplement(f)) { + ft = Cudd_Not(ft); + fe = Cudd_Not(fe); + } + } else { + index = G->index; + ft = fe = f; + } + + if (topg == top) { + gt = cuddT(G); + ge = cuddE(G); + if (Cudd_IsComplement(g)) { + gt = Cudd_Not(gt); + ge = Cudd_Not(ge); + } + } else { + gt = ge = g; + } + + if (topcube == top) { /* quantify */ + DdNode *Cube = cuddT(cube); + t = cuddBddAndAbstractRecurTime(manager, ft, gt, Cube, pRecCalls, TimeOut); + if (t == NULL) return(NULL); + /* Special case: 1 OR anything = 1. Hence, no need to compute + ** the else branch if t is 1. Likewise t + t * anything == t. + ** Notice that t == fe implies that fe does not depend on the + ** variables in Cube. Likewise for t == ge. + */ + if (t == one || t == fe || t == ge) { + if (F->ref != 1 || G->ref != 1) + cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG, + f, g, cube, t); + return(t); + } + cuddRef(t); + /* Special case: t + !t * anything == t + anything. */ + if (t == Cudd_Not(fe)) { + e = cuddBddExistAbstractRecur(manager, ge, Cube); + } else if (t == Cudd_Not(ge)) { + e = cuddBddExistAbstractRecur(manager, fe, Cube); + } else { + e = cuddBddAndAbstractRecurTime(manager, fe, ge, Cube, pRecCalls, TimeOut); + } + if (e == NULL) { + Cudd_IterDerefBdd(manager, t); + return(NULL); + } + if (t == e) { + r = t; + cuddDeref(t); + } else { + cuddRef(e); + r = cuddBddAndRecurTime(manager, Cudd_Not(t), Cudd_Not(e), pRecCalls, TimeOut); + if (r == NULL) { + Cudd_IterDerefBdd(manager, t); + Cudd_IterDerefBdd(manager, e); + return(NULL); + } + r = Cudd_Not(r); + cuddRef(r); + Cudd_DelayedDerefBdd(manager, t); + Cudd_DelayedDerefBdd(manager, e); + cuddDeref(r); + } + } else { + t = cuddBddAndAbstractRecurTime(manager, ft, gt, cube, pRecCalls, TimeOut); + if (t == NULL) return(NULL); + cuddRef(t); + e = cuddBddAndAbstractRecurTime(manager, fe, ge, cube, pRecCalls, TimeOut); + if (e == NULL) { + Cudd_IterDerefBdd(manager, t); + return(NULL); + } + if (t == e) { + r = t; + cuddDeref(t); + } else { + cuddRef(e); + if (Cudd_IsComplement(t)) { + r = cuddUniqueInter(manager, (int) index, + Cudd_Not(t), Cudd_Not(e)); + if (r == NULL) { + Cudd_IterDerefBdd(manager, t); + Cudd_IterDerefBdd(manager, e); + return(NULL); + } + r = Cudd_Not(r); + } else { + r = cuddUniqueInter(manager,(int)index,t,e); + if (r == NULL) { + Cudd_IterDerefBdd(manager, t); + Cudd_IterDerefBdd(manager, e); + return(NULL); + } + } + cuddDeref(e); + cuddDeref(t); + } + } + + if (F->ref != 1 || G->ref != 1) + cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube, r); + return (r); + +} /* end of cuddBddAndAbstractRecur */ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Convert a BDD from a manager to another one.] + + Description [Convert a BDD from a manager to another one. Returns a + pointer to the BDD in the destination manager if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Extra_TransferPermute] + +******************************************************************************/ +DdNode * extraTransferPermuteTime( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute, int TimeOut ) +{ + DdNode *res; + st__table *table = NULL; + st__generator *gen = NULL; + DdNode *key, *value; + + table = st__init_table( st__ptrcmp, st__ptrhash ); + if ( table == NULL ) + goto failure; + res = extraTransferPermuteRecurTime( ddS, ddD, f, table, Permute, TimeOut ); + if ( res != NULL ) + cuddRef( res ); + + /* Dereference all elements in the table and dispose of the table. + ** This must be done also if res is NULL to avoid leaks in case of + ** reordering. */ + gen = st__init_gen( table ); + if ( gen == NULL ) + goto failure; + while ( st__gen( gen, ( const char ** ) &key, ( char ** ) &value ) ) + { + Cudd_RecursiveDeref( ddD, value ); + } + st__free_gen( gen ); + gen = NULL; + st__free_table( table ); + table = NULL; + + if ( res != NULL ) + cuddDeref( res ); + return ( res ); + + failure: + if ( table != NULL ) + st__free_table( table ); + if ( gen != NULL ) + st__free_gen( gen ); + return ( NULL ); + +} /* end of extraTransferPermuteTime */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Extra_TransferPermute.] + + Description [Performs the recursive step of Extra_TransferPermute. + Returns a pointer to the result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [extraTransferPermuteTime] + +******************************************************************************/ +static DdNode * +extraTransferPermuteRecurTime( + DdManager * ddS, + DdManager * ddD, + DdNode * f, + st__table * table, + int * Permute, + int TimeOut ) +{ + DdNode *ft, *fe, *t, *e, *var, *res; + DdNode *one, *zero; + int index; + int comple = 0; + + statLine( ddD ); + one = DD_ONE( ddD ); + comple = Cudd_IsComplement( f ); + + /* Trivial cases. */ + if ( Cudd_IsConstant( f ) ) + return ( Cudd_NotCond( one, comple ) ); + + + /* Make canonical to increase the utilization of the cache. */ + f = Cudd_NotCond( f, comple ); + /* Now f is a regular pointer to a non-constant node. */ + + /* Check the cache. */ + if ( st__lookup( table, ( char * ) f, ( char ** ) &res ) ) + return ( Cudd_NotCond( res, comple ) ); + + if ( TimeOut && Abc_Clock() > TimeOut ) + return NULL; + + /* Recursive step. */ + if ( Permute ) + index = Permute[f->index]; + else + index = f->index; + + ft = cuddT( f ); + fe = cuddE( f ); + + t = extraTransferPermuteRecurTime( ddS, ddD, ft, table, Permute, TimeOut ); + if ( t == NULL ) + { + return ( NULL ); + } + cuddRef( t ); + + e = extraTransferPermuteRecurTime( ddS, ddD, fe, table, Permute, TimeOut ); + if ( e == NULL ) + { + Cudd_RecursiveDeref( ddD, t ); + return ( NULL ); + } + cuddRef( e ); + + zero = Cudd_Not(ddD->one); + var = cuddUniqueInter( ddD, index, one, zero ); + if ( var == NULL ) + { + Cudd_RecursiveDeref( ddD, t ); + Cudd_RecursiveDeref( ddD, e ); + return ( NULL ); + } + res = cuddBddIteRecur( ddD, var, t, e ); + + if ( res == NULL ) + { + Cudd_RecursiveDeref( ddD, t ); + Cudd_RecursiveDeref( ddD, e ); + return ( NULL ); + } + cuddRef( res ); + Cudd_RecursiveDeref( ddD, t ); + Cudd_RecursiveDeref( ddD, e ); + + if ( st__add_direct( table, ( char * ) f, ( char * ) res ) == + st__OUT_OF_MEM ) + { + Cudd_RecursiveDeref( ddD, res ); + return ( NULL ); + } + return ( Cudd_NotCond( res, comple ) ); + +} /* end of extraTransferPermuteRecurTime */ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/extrab/extraBddUnate.c b/src/bdd/extrab/extraBddUnate.c new file mode 100644 index 00000000..9ebdd4e5 --- /dev/null +++ b/src/bdd/extrab/extraBddUnate.c @@ -0,0 +1,646 @@ +/**CFile**************************************************************** + + FileName [extraBddUnate.c] + + PackageName [extra] + + Synopsis [Efficient methods to compute the information about + unate variables using an algorithm that is conceptually similar to + the algorithm for two-variable symmetry computation presented in: + A. Mishchenko. Fast Computation of Symmetries in Boolean Functions. + Transactions on CAD, Nov. 2003.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - September 1, 2003.] + + Revision [$Id: extraBddUnate.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "extraBdd.h" + +ABC_NAMESPACE_IMPL_START + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Computes the classical symmetry information for the function.] + + Description [Returns the symmetry information in the form of Extra_UnateInfo_t structure.] + + SideEffects [If the ZDD variables are not derived from BDD variables with + multiplicity 2, this function may derive them in a wrong way.] + + SeeAlso [] + +******************************************************************************/ +Extra_UnateInfo_t * Extra_UnateComputeFast( + DdManager * dd, /* the manager */ + DdNode * bFunc) /* the function whose symmetries are computed */ +{ + DdNode * bSupp; + DdNode * zRes; + Extra_UnateInfo_t * p; + + bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); + zRes = Extra_zddUnateInfoCompute( dd, bFunc, bSupp ); Cudd_Ref( zRes ); + + p = Extra_UnateInfoCreateFromZdd( dd, zRes, bSupp ); + + Cudd_RecursiveDeref( dd, bSupp ); + Cudd_RecursiveDerefZdd( dd, zRes ); + + return p; + +} /* end of Extra_UnateInfoCompute */ + + +/**Function******************************************************************** + + Synopsis [Computes the classical symmetry information as a ZDD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_zddUnateInfoCompute( + DdManager * dd, /* the DD manager */ + DdNode * bF, + DdNode * bVars) +{ + DdNode * res; + do { + dd->reordered = 0; + res = extraZddUnateInfoCompute( dd, bF, bVars ); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_zddUnateInfoCompute */ + + +/**Function******************************************************************** + + Synopsis [Converts a set of variables into a set of singleton subsets.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_zddGetSingletonsBoth( + DdManager * dd, /* the DD manager */ + DdNode * bVars) /* the set of variables */ +{ + DdNode * res; + do { + dd->reordered = 0; + res = extraZddGetSingletonsBoth( dd, bVars ); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_zddGetSingletonsBoth */ + +/**Function******************************************************************** + + Synopsis [Allocates unateness information structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +Extra_UnateInfo_t * Extra_UnateInfoAllocate( int nVars ) +{ + Extra_UnateInfo_t * p; + // allocate and clean the storage for unateness info + p = ABC_ALLOC( Extra_UnateInfo_t, 1 ); + memset( p, 0, sizeof(Extra_UnateInfo_t) ); + p->nVars = nVars; + p->pVars = ABC_ALLOC( Extra_UnateVar_t, nVars ); + memset( p->pVars, 0, nVars * sizeof(Extra_UnateVar_t) ); + return p; +} /* end of Extra_UnateInfoAllocate */ + +/**Function******************************************************************** + + Synopsis [Deallocates symmetry information structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Extra_UnateInfoDissolve( Extra_UnateInfo_t * p ) +{ + ABC_FREE( p->pVars ); + ABC_FREE( p ); +} /* end of Extra_UnateInfoDissolve */ + +/**Function******************************************************************** + + Synopsis [Allocates symmetry information structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Extra_UnateInfoPrint( Extra_UnateInfo_t * p ) +{ + char * pBuffer; + int i; + pBuffer = ABC_ALLOC( char, p->nVarsMax+1 ); + memset( pBuffer, ' ', p->nVarsMax ); + pBuffer[p->nVarsMax] = 0; + for ( i = 0; i < p->nVars; i++ ) + if ( p->pVars[i].Neg ) + pBuffer[ p->pVars[i].iVar ] = 'n'; + else if ( p->pVars[i].Pos ) + pBuffer[ p->pVars[i].iVar ] = 'p'; + else + pBuffer[ p->pVars[i].iVar ] = '.'; + printf( "%s\n", pBuffer ); + ABC_FREE( pBuffer ); +} /* end of Extra_UnateInfoPrint */ + + +/**Function******************************************************************** + + Synopsis [Creates the symmetry information structure from ZDD.] + + Description [ZDD representation of symmetries is the set of cubes, each + of which has two variables in the positive polarity. These variables correspond + to the symmetric variable pair.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +Extra_UnateInfo_t * Extra_UnateInfoCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bSupp ) +{ + Extra_UnateInfo_t * p; + DdNode * bTemp, * zSet, * zCube, * zTemp; + int * pMapVars2Nums; + int i, nSuppSize; + + nSuppSize = Extra_bddSuppSize( dd, bSupp ); + + // allocate and clean the storage for symmetry info + p = Extra_UnateInfoAllocate( nSuppSize ); + + // allocate the storage for the temporary map + pMapVars2Nums = ABC_ALLOC( int, dd->size ); + memset( pMapVars2Nums, 0, dd->size * sizeof(int) ); + + // assign the variables + p->nVarsMax = dd->size; + for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ ) + { + p->pVars[i].iVar = bTemp->index; + pMapVars2Nums[bTemp->index] = i; + } + + // write the symmetry info into the structure + zSet = zPairs; Cudd_Ref( zSet ); +// Cudd_zddPrintCover( dd, zPairs ); printf( "\n" ); + while ( zSet != z0 ) + { + // get the next cube + zCube = Extra_zddSelectOneSubset( dd, zSet ); Cudd_Ref( zCube ); + + // add this var to the data structure + assert( cuddT(zCube) == z1 && cuddE(zCube) == z0 ); + if ( zCube->index & 1 ) // neg + p->pVars[ pMapVars2Nums[zCube->index/2] ].Neg = 1; + else + p->pVars[ pMapVars2Nums[zCube->index/2] ].Pos = 1; + // count the unate vars + p->nUnate++; + + // update the cuver and deref the cube + zSet = Cudd_zddDiff( dd, zTemp = zSet, zCube ); Cudd_Ref( zSet ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zCube ); + + } // for each cube + Cudd_RecursiveDerefZdd( dd, zSet ); + ABC_FREE( pMapVars2Nums ); + return p; + +} /* end of Extra_UnateInfoCreateFromZdd */ + + + +/**Function******************************************************************** + + Synopsis [Computes the classical unateness information for the function.] + + Description [Uses the naive way of comparing cofactors.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +Extra_UnateInfo_t * Extra_UnateComputeSlow( DdManager * dd, DdNode * bFunc ) +{ + int nSuppSize; + DdNode * bSupp, * bTemp; + Extra_UnateInfo_t * p; + int i, Res; + + // compute the support + bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); + nSuppSize = Extra_bddSuppSize( dd, bSupp ); +//printf( "Support = %d. ", nSuppSize ); +//Extra_bddPrint( dd, bSupp ); +//printf( "%d ", nSuppSize ); + + // allocate the storage for symmetry info + p = Extra_UnateInfoAllocate( nSuppSize ); + + // assign the variables + p->nVarsMax = dd->size; + for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ ) + { + Res = Extra_bddCheckUnateNaive( dd, bFunc, bTemp->index ); + p->pVars[i].iVar = bTemp->index; + if ( Res == -1 ) + p->pVars[i].Neg = 1; + else if ( Res == 1 ) + p->pVars[i].Pos = 1; + p->nUnate += (Res != 0); + } + Cudd_RecursiveDeref( dd, bSupp ); + return p; + +} /* end of Extra_UnateComputeSlow */ + +/**Function******************************************************************** + + Synopsis [Checks if the two variables are symmetric.] + + Description [Returns 0 if vars are not unate. Return -1/+1 if the var is neg/pos unate.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Extra_bddCheckUnateNaive( + DdManager * dd, /* the DD manager */ + DdNode * bF, + int iVar) +{ + DdNode * bCof0, * bCof1; + int Res; + + assert( iVar < dd->size ); + + bCof0 = Cudd_Cofactor( dd, bF, Cudd_Not(Cudd_bddIthVar(dd,iVar)) ); Cudd_Ref( bCof0 ); + bCof1 = Cudd_Cofactor( dd, bF, Cudd_bddIthVar(dd,iVar) ); Cudd_Ref( bCof1 ); + + if ( Cudd_bddLeq( dd, bCof0, bCof1 ) ) + Res = 1; + else if ( Cudd_bddLeq( dd, bCof1, bCof0 ) ) + Res =-1; + else + Res = 0; + + Cudd_RecursiveDeref( dd, bCof0 ); + Cudd_RecursiveDeref( dd, bCof1 ); + return Res; +} /* end of Extra_bddCheckUnateNaive */ + + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Performs a recursive step of Extra_UnateInfoCompute.] + + Description [Returns the set of symmetric variable pairs represented as a set + of two-literal ZDD cubes. Both variables always appear in the positive polarity + in the cubes. This function works without building new BDD nodes. Some relatively + small number of ZDD nodes may be built to ensure proper bookkeeping of the + symmetry information.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * +extraZddUnateInfoCompute( + DdManager * dd, /* the manager */ + DdNode * bFunc, /* the function whose symmetries are computed */ + DdNode * bVars ) /* the set of variables on which this function depends */ +{ + DdNode * zRes; + DdNode * bFR = Cudd_Regular(bFunc); + + if ( cuddIsConstant(bFR) ) + { + if ( cuddIsConstant(bVars) ) + return z0; + return extraZddGetSingletonsBoth( dd, bVars ); + } + assert( bVars != b1 ); + + if ( (zRes = cuddCacheLookup2Zdd(dd, extraZddUnateInfoCompute, bFunc, bVars)) ) + return zRes; + else + { + DdNode * zRes0, * zRes1; + DdNode * zTemp, * zPlus; + DdNode * bF0, * bF1; + DdNode * bVarsNew; + int nVarsExtra; + int LevelF; + int AddVar; + + // every variable in bF should be also in bVars, therefore LevelF cannot be above LevelV + // if LevelF is below LevelV, scroll through the vars in bVars to the same level as F + // count how many extra vars are there in bVars + nVarsExtra = 0; + LevelF = dd->perm[bFR->index]; + for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) ) + nVarsExtra++; + // the indexes (level) of variables should be synchronized now + assert( bFR->index == bVarsNew->index ); + + // cofactor the function + if ( bFR != bFunc ) // bFunc is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + + // solve subproblems + zRes0 = extraZddUnateInfoCompute( dd, bF0, cuddT(bVarsNew) ); + if ( zRes0 == NULL ) + return NULL; + cuddRef( zRes0 ); + + // if there is no symmetries in the negative cofactor + // there is no need to test the positive cofactor + if ( zRes0 == z0 ) + zRes = zRes0; // zRes takes reference + else + { + zRes1 = extraZddUnateInfoCompute( dd, bF1, cuddT(bVarsNew) ); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + return NULL; + } + cuddRef( zRes1 ); + + // only those variables are pair-wise symmetric + // that are pair-wise symmetric in both cofactors + // therefore, intersect the solutions + zRes = cuddZddIntersect( dd, zRes0, zRes1 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + } + + // consider the current top-most variable + AddVar = -1; + if ( Cudd_bddLeq( dd, bF0, bF1 ) ) // pos + AddVar = 0; + else if ( Cudd_bddLeq( dd, bF1, bF0 ) ) // neg + AddVar = 1; + if ( AddVar >= 0 ) + { + // create the singleton + zPlus = cuddZddGetNode( dd, 2*bFR->index + AddVar, z1, z0 ); + if ( zPlus == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( zPlus ); + + // add these to the result + zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + } + // only zRes is referenced at this point + + // if we skipped some variables, these variables cannot be symmetric with + // any variables that are currently in the support of bF, but they can be + // symmetric with the variables that are in bVars but not in the support of bF + for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) ) + { + // create the negative singleton + zPlus = cuddZddGetNode( dd, 2*bVarsNew->index+1, z1, z0 ); + if ( zPlus == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( zPlus ); + + // add these to the result + zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + + + // create the positive singleton + zPlus = cuddZddGetNode( dd, 2*bVarsNew->index, z1, z0 ); + if ( zPlus == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( zPlus ); + + // add these to the result + zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + } + cuddDeref( zRes ); + + /* insert the result into cache */ + cuddCacheInsert2(dd, extraZddUnateInfoCompute, bFunc, bVars, zRes); + return zRes; + } +} /* end of extraZddUnateInfoCompute */ + + +/**Function******************************************************************** + + Synopsis [Performs a recursive step of Extra_zddGetSingletons.] + + Description [Returns the set of ZDD singletons, containing those pos/neg + polarity ZDD variables that correspond to the BDD variables in bVars.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * extraZddGetSingletonsBoth( + DdManager * dd, /* the DD manager */ + DdNode * bVars) /* the set of variables */ +{ + DdNode * zRes; + + if ( bVars == b1 ) + return z1; + + if ( (zRes = cuddCacheLookup1Zdd(dd, extraZddGetSingletonsBoth, bVars)) ) + return zRes; + else + { + DdNode * zTemp, * zPlus; + + // solve subproblem + zRes = extraZddGetSingletonsBoth( dd, cuddT(bVars) ); + if ( zRes == NULL ) + return NULL; + cuddRef( zRes ); + + + // create the negative singleton + zPlus = cuddZddGetNode( dd, 2*bVars->index+1, z1, z0 ); + if ( zPlus == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( zPlus ); + + // add these to the result + zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + + + // create the positive singleton + zPlus = cuddZddGetNode( dd, 2*bVars->index, z1, z0 ); + if ( zPlus == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( zPlus ); + + // add these to the result + zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + + cuddDeref( zRes ); + cuddCacheInsert1( dd, extraZddGetSingletonsBoth, bVars, zRes ); + return zRes; + } +} /* end of extraZddGetSingletonsBoth */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static Functions */ +/*---------------------------------------------------------------------------*/ +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/extrab/module.make b/src/bdd/extrab/module.make new file mode 100644 index 00000000..38cdddb6 --- /dev/null +++ b/src/bdd/extrab/module.make @@ -0,0 +1,8 @@ +SRC += src/bdd/extrab/extraBddAuto.c \ + src/bdd/extrab/extraBddCas.c \ + src/bdd/extrab/extraBddImage.c \ + src/bdd/extrab/extraBddKmap.c \ + src/bdd/extrab/extraBddMisc.c \ + src/bdd/extrab/extraBddSymm.c \ + src/bdd/extrab/extraBddTime.c \ + src/bdd/extrab/extraBddUnate.c diff --git a/src/bdd/llb/llb.c b/src/bdd/llb/llb.c new file mode 100644 index 00000000..348c0622 --- /dev/null +++ b/src/bdd/llb/llb.c @@ -0,0 +1,52 @@ +/**CFile**************************************************************** + + FileName [llb.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb.h b/src/bdd/llb/llb.h new file mode 100644 index 00000000..f465359d --- /dev/null +++ b/src/bdd/llb/llb.h @@ -0,0 +1,96 @@ +/**CFile**************************************************************** + + FileName [llb.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD-based reachability.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 8, 2010.] + + Revision [$Id: llb.h,v 1.00 2010/05/08 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__llb__llb_h +#define ABC__aig__llb__llb_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Gia_ParLlb_t_ Gia_ParLlb_t; +struct Gia_ParLlb_t_ +{ + int nBddMax; // maximum BDD size + int nIterMax; // maximum iteration count + int nClusterMax; // maximum cluster size + int nHintDepth; // the number of times to cofactor + int HintFirst; // the number of first hint to use + int fUseFlow; // use flow computation + int nVolumeMax; // the largest volume + int nVolumeMin; // the smallest volume + int nPartValue; // partitioning value + int fBackward; // enable backward reachability + int fReorder; // enable dynamic variable reordering + int fIndConstr; // extract inductive constraints + int fUsePivots; // use internal pivot variables + int fCluster; // use partition clustering + int fSchedule; // use cluster scheduling + int fDumpReached; // dump reached states into a file + int fVerbose; // print verbose information + int fVeryVerbose; // print dependency matrices + int fSilent; // do not print any infomation + int fSkipReach; // skip reachability (preparation phase only) + int fSkipOutCheck; // does not check the property output + int TimeLimit; // time limit for one reachability run + int TimeLimitGlo; // time limit for all reachability runs + // internal parameters + abctime TimeTarget; // the time to stop + int iFrame; // explored up to this frame +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== llbCore.c ==========================================================*/ +extern void Llb_ManSetDefaultParams( Gia_ParLlb_t * pPars ); +/*=== llb4Nonlin.c ==========================================================*/ +extern int Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/bdd/llb/llb1Cluster.c b/src/bdd/llb/llb1Cluster.c new file mode 100644 index 00000000..1356e484 --- /dev/null +++ b/src/bdd/llb/llb1Cluster.c @@ -0,0 +1,356 @@ +/**CFile**************************************************************** + + FileName [llb1Cluster.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Clustering algorithm.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Cluster.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManComputeCommonQuant( Llb_Mtr_t * p, int iCol1, int iCol2 ) +{ + int iVar, Weight = 0; + for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ ) + { + // count each removed variable as 2 + if ( p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 1 && p->pRowSums[iVar] == 2 ) + Weight += 2; + // count each added variale as -1 + else if ( (p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 0) || + (p->pMatrix[iCol1][iVar] == 0 && p->pMatrix[iCol2][iVar] == 1) ) + Weight--; + } + return Weight; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManComputeBestQuant( Llb_Mtr_t * p ) +{ + int i, k, WeightBest = -100000, WeightCur, RetValue = -1; + for ( i = 1; i < p->nCols-1; i++ ) + for ( k = i+1; k < p->nCols-1; k++ ) + { + if ( p->pColSums[i] == 0 || p->pColSums[i] > p->pMan->pPars->nClusterMax ) + continue; + if ( p->pColSums[k] == 0 || p->pColSums[k] > p->pMan->pPars->nClusterMax ) + continue; + + WeightCur = Llb_ManComputeCommonQuant( p, i, k ); + if ( WeightCur <= 0 ) + continue; + if ( WeightBest < WeightCur ) + { + WeightBest = WeightCur; + RetValue = (i << 16) | k; + } + } +// printf( "Choosing best quant Weight %4d\n", WeightCur ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float ** Llb_ManComputeQuant( Llb_Mtr_t * p ) +{ + float ** pCosts; + int i, k; + // alloc and clean + pCosts = (float **)Extra_ArrayAlloc( p->nCols, p->nCols, sizeof(float) ); + for ( i = 0; i < p->nCols; i++ ) + for ( k = 0; k < p->nCols; k++ ) + pCosts[i][i] = 0.0; + // fill up + for ( i = 1; i < p->nCols-1; i++ ) + for ( k = i+1; k < p->nCols-1; k++ ) + pCosts[i][k] = pCosts[k][i] = Llb_ManComputeCommonQuant( p, i, k ); + return pCosts; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Llb_ManComputeCommonAttr( Llb_Mtr_t * p, int iCol1, int iCol2 ) +{ + int iVar, CountComm = 0, CountDiff = 0; + for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ ) + { + if ( p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 1 ) + CountComm++; + else if ( p->pMatrix[iCol1][iVar] == 1 || p->pMatrix[iCol2][iVar] == 1 ) + CountDiff++; + } +/* + printf( "Attr cost for %4d and %4d: %4d %4d (%5.2f)\n", + iCol1, iCol2, + CountDiff, CountComm, + -1.0 * CountDiff / ( CountComm + CountDiff ) ); +*/ + return -1.0 * CountDiff / ( CountComm + CountDiff ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManComputeBestAttr( Llb_Mtr_t * p ) +{ + float WeightBest = -100000, WeightCur; + int i, k, RetValue = -1; + for ( i = 1; i < p->nCols-1; i++ ) + for ( k = i+1; k < p->nCols-1; k++ ) + { + if ( p->pColSums[i] == 0 || p->pColSums[i] > p->pMan->pPars->nClusterMax ) + continue; + if ( p->pColSums[k] == 0 || p->pColSums[k] > p->pMan->pPars->nClusterMax ) + continue; + WeightCur = Llb_ManComputeCommonAttr( p, i, k ); + if ( WeightBest < WeightCur ) + { + WeightBest = WeightCur; + RetValue = (i << 16) | k; + } + } + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float ** Llb_ManComputeAttr( Llb_Mtr_t * p ) +{ + float ** pCosts; + int i, k; + // alloc and clean + pCosts = (float **)Extra_ArrayAlloc( p->nCols, p->nCols, sizeof(float) ); + for ( i = 0; i < p->nCols; i++ ) + for ( k = 0; k < p->nCols; k++ ) + pCosts[i][i] = 0.0; + // fill up + for ( i = 1; i < p->nCols-1; i++ ) + for ( k = i+1; k < p->nCols-1; k++ ) + pCosts[i][k] = pCosts[k][i] = Llb_ManComputeCommonAttr( p, i, k ); + return pCosts; +} + + +/**Function************************************************************* + + Synopsis [Returns the number of variables that will be saved.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrCombineSelectedColumns( Llb_Mtr_t * p, int iGrp1, int iGrp2 ) +{ + int iVar; + assert( iGrp1 >= 1 && iGrp1 < p->nCols - 1 ); + assert( iGrp2 >= 1 && iGrp2 < p->nCols - 1 ); + assert( p->pColGrps[iGrp1] != NULL ); + assert( p->pColGrps[iGrp2] != NULL ); + for ( iVar = 0; iVar < p->nRows; iVar++ ) + { + if ( p->pMatrix[iGrp1][iVar] == 1 && p->pMatrix[iGrp2][iVar] == 1 ) + p->pRowSums[iVar]--; + if ( p->pMatrix[iGrp1][iVar] == 0 && p->pMatrix[iGrp2][iVar] == 1 ) + { + p->pMatrix[iGrp1][iVar] = 1; + p->pColSums[iGrp1]++; + } + if ( p->pMatrix[iGrp2][iVar] == 1 ) + p->pMatrix[iGrp2][iVar] = 0; + } + p->pColSums[iGrp2] = 0; +} + + +/**Function************************************************************* + + Synopsis [Combines one pair of columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManClusterOne( Llb_Mtr_t * p, int iCol1, int iCol2 ) +{ + int fVerbose = 0; + Llb_Grp_t * pGrp; + int iVar; + + if ( fVerbose ) + { + printf( "Combining %d and %d\n", iCol1, iCol2 ); + for ( iVar = 0; iVar < p->nRows; iVar++ ) + { + if ( p->pMatrix[iCol1][iVar] == 0 && p->pMatrix[iCol2][iVar] == 0 ) + continue; + printf( "%3d : %c%c\n", iVar, + p->pMatrix[iCol1][iVar]? '*':' ', + p->pMatrix[iCol2][iVar]? '*':' ' ); + } + } + pGrp = Llb_ManGroupsCombine( p->pColGrps[iCol1], p->pColGrps[iCol2] ); + Llb_MtrCombineSelectedColumns( p, iCol1, iCol2 ); + p->pColGrps[iCol1] = pGrp; + p->pColGrps[iCol2] = NULL; +} + +/**Function************************************************************* + + Synopsis [Removes empty columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManClusterCompress( Llb_Mtr_t * p ) +{ + int i, k = 0; + for ( i = 0; i < p->nCols; i++ ) + { + if ( p->pColGrps[i] == NULL ) + { + assert( p->pColSums[i] == 0 ); + assert( p->pMatrix[i] != NULL ); + ABC_FREE( p->pMatrix[i] ); + continue; + } + p->pMatrix[k] = p->pMatrix[i]; + p->pColGrps[k] = p->pColGrps[i]; + p->pColSums[k] = p->pColSums[i]; + k++; + } + p->nCols = k; +} + +/**Function************************************************************* + + Synopsis [Combines one pair of columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManCluster( Llb_Mtr_t * p ) +{ + int RetValue; + do + { + do { + RetValue = Llb_ManComputeBestQuant( p ); + if ( RetValue > 0 ) + Llb_ManClusterOne( p, RetValue >> 16, RetValue & 0xffff ); + } + while ( RetValue > 0 ); + + RetValue = Llb_ManComputeBestAttr( p ); + if ( RetValue > 0 ) + Llb_ManClusterOne( p, RetValue >> 16, RetValue & 0xffff ); + + Llb_MtrVerifyMatrix( p ); + } + while ( RetValue > 0 ); + + Llb_ManClusterCompress( p ); + + Llb_MtrVerifyMatrix( p ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb1Constr.c b/src/bdd/llb/llb1Constr.c new file mode 100644 index 00000000..1ef4ce14 --- /dev/null +++ b/src/bdd/llb/llb1Constr.c @@ -0,0 +1,313 @@ +/**CFile**************************************************************** + + FileName [llb1Constr.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Computing inductive constraints.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Constr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the array of constraint candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManCountEntries( Vec_Int_t * vCands ) +{ + int i, Entry, Counter = 0; + Vec_IntForEachEntry( vCands, Entry, i ) + Counter += ((Entry == 0) || (Entry == 1)); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns the array of constraint candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrintEntries( Aig_Man_t * p, Vec_Int_t * vCands ) +{ + int i, Entry; + if ( vCands == NULL ) + { + printf( "There is no hints.\n" ); + return; + } + Entry = Llb_ManCountEntries(vCands); + printf( "\n*** Using %d hint%s:\n", Entry, (Entry != 1 ? "s":"") ); + Vec_IntForEachEntry( vCands, Entry, i ) + { + if ( Entry != 0 && Entry != 1 ) + continue; + printf( "%c", Entry ? '+' : '-' ); + printf( "%-6d : ", i ); + Aig_ObjPrint( p, Aig_ManObj(p, i) ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Dereference BDD nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManDerefenceBdds( Aig_Man_t * p, DdManager * dd ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachObj( p, pObj, i ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); +} + +/**Function************************************************************* + + Synopsis [Returns the array of constraint candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManComputeIndCase_rec( Aig_Man_t * p, Aig_Obj_t * pObj, DdManager * dd, Vec_Ptr_t * vBdds ) +{ + DdNode * bBdd0, * bBdd1; + DdNode * bFunc = (DdNode *)Vec_PtrEntry( vBdds, Aig_ObjId(pObj) ); + if ( bFunc != NULL ) + return bFunc; + assert( Aig_ObjIsNode(pObj) ); + bBdd0 = Llb_ManComputeIndCase_rec( p, Aig_ObjFanin0(pObj), dd, vBdds ); + bBdd1 = Llb_ManComputeIndCase_rec( p, Aig_ObjFanin1(pObj), dd, vBdds ); + bBdd0 = Cudd_NotCond( bBdd0, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( bBdd1, Aig_ObjFaninC1(pObj) ); + bFunc = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bFunc ); + Vec_PtrWriteEntry( vBdds, Aig_ObjId(pObj), bFunc ); + return bFunc; +} + +/**Function************************************************************* + + Synopsis [Returns the array of constraint candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManComputeIndCase( Aig_Man_t * p, DdManager * dd, Vec_Int_t * vNodes ) +{ + Vec_Ptr_t * vBdds; + Aig_Obj_t * pObj; + DdNode * bFunc; + int i, Entry; + vBdds = Vec_PtrStart( Aig_ManObjNumMax(p) ); + bFunc = Cudd_ReadOne(dd); Cudd_Ref( bFunc ); + Vec_PtrWriteEntry( vBdds, Aig_ObjId(Aig_ManConst1(p)), bFunc ); + Saig_ManForEachPi( p, pObj, i ) + { + bFunc = Cudd_bddIthVar( dd, Aig_ManCiNum(p) + i ); Cudd_Ref( bFunc ); + Vec_PtrWriteEntry( vBdds, Aig_ObjId(pObj), bFunc ); + } + Saig_ManForEachLi( p, pObj, i ) + { + bFunc = (DdNode *)pObj->pData; Cudd_Ref( bFunc ); + Vec_PtrWriteEntry( vBdds, Aig_ObjId(Saig_ObjLiToLo(p, pObj)), bFunc ); + } + Vec_IntForEachEntry( vNodes, Entry, i ) + { + if ( Entry != 0 && Entry != 1 ) + continue; + pObj = Aig_ManObj( p, i ); + bFunc = Llb_ManComputeIndCase_rec( p, pObj, dd, vBdds ); + if ( Entry == 0 ) + { +// Extra_bddPrint( dd, Cudd_Not(pObj->pData) ); printf( "\n" ); +// Extra_bddPrint( dd, Cudd_Not(bFunc) ); printf( "\n" ); + if ( !Cudd_bddLeq( dd, Cudd_Not(pObj->pData), Cudd_Not(bFunc) ) ) + Vec_IntWriteEntry( vNodes, i, -1 ); + } + else if ( Entry == 1 ) + { +// Extra_bddPrint( dd, pObj->pData ); printf( "\n" ); +// Extra_bddPrint( dd, bFunc ); printf( "\n" ); + if ( !Cudd_bddLeq( dd, (DdNode *)pObj->pData, bFunc ) ) + Vec_IntWriteEntry( vNodes, i, -1 ); + } + } + Vec_PtrForEachEntry( DdNode *, vBdds, bFunc, i ) + if ( bFunc ) + Cudd_RecursiveDeref( dd, bFunc ); + Vec_PtrFree( vBdds ); +} + +/**Function************************************************************* + + Synopsis [Returns the array of constraint candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_ManComputeBaseCase( Aig_Man_t * p, DdManager * dd ) +{ + Vec_Int_t * vNodes; + Aig_Obj_t * pObj, * pRoot; + int i; + pRoot = Aig_ManCo( p, 0 ); + vNodes = Vec_IntStartFull( Aig_ManObjNumMax(p) ); + Aig_ManForEachObj( p, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) ) + continue; + if ( Cudd_bddLeq( dd, (DdNode *)pObj->pData, Cudd_Not(pRoot->pData) ) ) + Vec_IntWriteEntry( vNodes, i, 1 ); + else if ( Cudd_bddLeq( dd, Cudd_Not((DdNode *)pObj->pData), Cudd_Not(pRoot->pData) ) ) + Vec_IntWriteEntry( vNodes, i, 0 ); + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Constructs global BDDs for each object in the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdManager * Llb_ManConstructGlobalBdds( Aig_Man_t * p ) +{ + DdManager * dd; + DdNode * bBdd0, * bBdd1; + Aig_Obj_t * pObj; + int i; + dd = Cudd_Init( Aig_ManCiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + pObj = Aig_ManConst1(p); + pObj->pData = Cudd_ReadOne(dd); Cudd_Ref( (DdNode *)pObj->pData ); + Aig_ManForEachCi( p, pObj, i ) + { + pObj->pData = Cudd_bddIthVar(dd, i); Cudd_Ref( (DdNode *)pObj->pData ); + } + Aig_ManForEachNode( p, pObj, i ) + { + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); + pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData ); + } + Aig_ManForEachCo( p, pObj, i ) + { + pObj->pData = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); Cudd_Ref( (DdNode *)pObj->pData ); + } + return dd; +} + +/**Function************************************************************* + + Synopsis [Derives inductive constraints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_ManDeriveConstraints( Aig_Man_t * p ) +{ + DdManager * dd; + Vec_Int_t * vNodes; + if ( Saig_ManPoNum(p) != 1 ) + { + printf( "The AIG has %d property outputs.\n", Saig_ManPoNum(p) ); + return NULL; + } + assert( Saig_ManPoNum(p) == 1 ); + dd = Llb_ManConstructGlobalBdds( p ); + vNodes = Llb_ManComputeBaseCase( p, dd ); + if ( Llb_ManCountEntries(vNodes) > 0 ) + Llb_ManComputeIndCase( p, dd, vNodes ); + if ( Llb_ManCountEntries(vNodes) == 0 ) + Vec_IntFreeP( &vNodes ); + Llb_ManDerefenceBdds( p, dd ); + Extra_StopManager( dd ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Tests derived constraints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManConstrTest( Aig_Man_t * p ) +{ + Vec_Int_t * vNodes; + vNodes = Llb_ManDeriveConstraints( p ); + Llb_ManPrintEntries( p, vNodes ); + Vec_IntFreeP( &vNodes ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb1Core.c b/src/bdd/llb/llb1Core.c new file mode 100644 index 00000000..213f2cd9 --- /dev/null +++ b/src/bdd/llb/llb1Core.c @@ -0,0 +1,222 @@ +/**CFile**************************************************************** + + FileName [llb1Core.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Top-level procedure.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Core.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" +#include "aig/gia/gia.h" +#include "aig/gia/giaAig.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManSetDefaultParams( Gia_ParLlb_t * p ) +{ + memset( p, 0, sizeof(Gia_ParLlb_t) ); + p->nBddMax = 10000000; + p->nIterMax = 10000000; + p->nClusterMax = 20; + p->nHintDepth = 0; + p->HintFirst = 0; + p->fUseFlow = 0; // use flow + p->nVolumeMax = 100; // max volume + p->nVolumeMin = 30; // min volume + p->nPartValue = 5; // partitioning value + p->fBackward = 0; // forward by default + p->fReorder = 1; + p->fIndConstr = 0; + p->fUsePivots = 0; + p->fCluster = 0; + p->fSchedule = 0; + p->fDumpReached = 0; + p->fVerbose = 0; + p->fVeryVerbose = 0; + p->fSilent = 0; + p->TimeLimit = 0; +// p->TimeLimit = 0; + p->TimeLimitGlo = 0; + p->TimeTarget = 0; + p->iFrame = -1; +} + + +/**Function************************************************************* + + Synopsis [Prints statistics about MFFCs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrintAig( Llb_Man_t * p ) +{ + Abc_Print( 1, "pi =%3d ", Saig_ManPiNum(p->pAig) ); + Abc_Print( 1, "po =%3d ", Saig_ManPoNum(p->pAig) ); + Abc_Print( 1, "ff =%3d ", Saig_ManRegNum(p->pAig) ); + Abc_Print( 1, "int =%5d ", Vec_IntSize(p->vVar2Obj)-Aig_ManCiNum(p->pAig)-Saig_ManRegNum(p->pAig) ); + Abc_Print( 1, "var =%5d ", Vec_IntSize(p->vVar2Obj) ); + Abc_Print( 1, "part =%5d ", Vec_PtrSize(p->vGroups)-2 ); + Abc_Print( 1, "and =%5d ", Aig_ManNodeNum(p->pAig) ); + Abc_Print( 1, "lev =%4d ", Aig_ManLevelNum(p->pAig) ); +// Abc_Print( 1, "cut =%4d ", Llb_ManCrossCut(p->pAig) ); + Abc_Print( 1, "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManModelCheckAig( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars, Vec_Int_t * vHints, DdManager ** pddGlo ) +{ + Llb_Man_t * p = NULL; + Aig_Man_t * pAig; + int RetValue = -1; + abctime clk = Abc_Clock(); + + if ( pPars->fIndConstr ) + { + assert( vHints == NULL ); + vHints = Llb_ManDeriveConstraints( pAigGlo ); + } + + // derive AIG for hints + if ( vHints == NULL ) + pAig = Aig_ManDupSimple( pAigGlo ); + else + { + if ( pPars->fVerbose ) + Llb_ManPrintEntries( pAigGlo, vHints ); + pAig = Aig_ManDupSimpleWithHints( pAigGlo, vHints ); + } + + + if ( pPars->fUseFlow ) + { +// p = Llb_ManStartFlow( pAigGlo, pAig, pPars ); + } + else + { + p = Llb_ManStart( pAigGlo, pAig, pPars ); + if ( pPars->fVerbose ) + { + Llb_ManPrintAig( p ); + printf( "Original matrix: " ); + Llb_MtrPrintMatrixStats( p->pMatrix ); + if ( pPars->fVeryVerbose ) + Llb_MtrPrint( p->pMatrix, 1 ); + } + if ( pPars->fCluster ) + { + Llb_ManCluster( p->pMatrix ); + if ( pPars->fVerbose ) + { + printf( "Matrix after clustering: " ); + Llb_MtrPrintMatrixStats( p->pMatrix ); + if ( pPars->fVeryVerbose ) + Llb_MtrPrint( p->pMatrix, 1 ); + } + } + if ( pPars->fSchedule ) + { + Llb_MtrSchedule( p->pMatrix ); + if ( pPars->fVerbose ) + { + printf( "Matrix after scheduling: " ); + Llb_MtrPrintMatrixStats( p->pMatrix ); + if ( pPars->fVeryVerbose ) + Llb_MtrPrint( p->pMatrix, 1 ); + } + } + } + + if ( !p->pPars->fSkipReach ) + RetValue = Llb_ManReachability( p, vHints, pddGlo ); + Llb_ManStop( p ); + + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + + if ( pPars->fIndConstr ) + Vec_IntFreeP( &vHints ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManModelCheckGia( Gia_Man_t * pGia, Gia_ParLlb_t * pPars ) +{ + Gia_Man_t * pGia2; + Aig_Man_t * pAig; + int RetValue = -1; + pGia2 = Gia_ManDupDfs( pGia ); + pAig = Gia_ManToAigSimple( pGia2 ); + Gia_ManStop( pGia2 ); +//Aig_ManShow( pAig, 0, NULL ); + + if ( pPars->nHintDepth == 0 ) + RetValue = Llb_ManModelCheckAig( pAig, pPars, NULL, NULL ); + else + RetValue = Llb_ManModelCheckAigWithHints( pAig, pPars ); + pGia->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL; + Aig_ManStop( pAig ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb1Group.c b/src/bdd/llb/llb1Group.c new file mode 100644 index 00000000..1099b2cd --- /dev/null +++ b/src/bdd/llb/llb1Group.c @@ -0,0 +1,474 @@ +/**CFile**************************************************************** + + FileName [llb1Group.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Initial partition computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Group.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Grp_t * Llb_ManGroupAlloc( Llb_Man_t * pMan ) +{ + Llb_Grp_t * p; + p = ABC_CALLOC( Llb_Grp_t, 1 ); + p->pMan = pMan; + p->vIns = Vec_PtrAlloc( 8 ); + p->vOuts = Vec_PtrAlloc( 8 ); + p->Id = Vec_PtrSize( pMan->vGroups ); + Vec_PtrPush( pMan->vGroups, p ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManGroupStop( Llb_Grp_t * p ) +{ + if ( p == NULL ) + return; + Vec_PtrWriteEntry( p->pMan->vGroups, p->Id, NULL ); + Vec_PtrFreeP( &p->vIns ); + Vec_PtrFreeP( &p->vOuts ); + Vec_PtrFreeP( &p->vNodes ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManGroupCollect_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return; + Aig_ObjSetTravIdCurrent(pAig, pObj); + if ( Aig_ObjIsConst1(pObj) ) + return; + if ( Aig_ObjIsCo(pObj) ) + { + Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin0(pObj), vNodes ); + return; + } + assert( Aig_ObjIsAnd(pObj) ); + Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin0(pObj), vNodes ); + Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin1(pObj), vNodes ); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Collects the support of MFFC.] + + Description [Returns the number of internal nodes in the MFFC.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManGroupCollect( Llb_Grp_t * pGroup ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + vNodes = Vec_PtrAlloc( 100 ); + Aig_ManIncrementTravId( pGroup->pMan->pAig ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) + Aig_ObjSetTravIdCurrent( pGroup->pMan->pAig, pObj ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + Aig_ObjSetTravIdPrevious( pGroup->pMan->pAig, pObj ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + Llb_ManGroupCollect_rec( pGroup->pMan->pAig, pObj, vNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManGroupCreate_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vSupp ) +{ + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return; + Aig_ObjSetTravIdCurrent(pAig, pObj); + if ( Aig_ObjIsConst1(pObj) ) + return; + if ( pObj->fMarkA ) + { + Vec_PtrPush( vSupp, pObj ); + return; + } + assert( Aig_ObjIsAnd(pObj) ); + Llb_ManGroupCreate_rec( pAig, Aig_ObjFanin0(pObj), vSupp ); + Llb_ManGroupCreate_rec( pAig, Aig_ObjFanin1(pObj), vSupp ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Grp_t * Llb_ManGroupCreate( Llb_Man_t * pMan, Aig_Obj_t * pObj ) +{ + Llb_Grp_t * p; + assert( pObj->fMarkA == 1 ); + // derive group + p = Llb_ManGroupAlloc( pMan ); + Vec_PtrPush( p->vOuts, pObj ); + Aig_ManIncrementTravId( pMan->pAig ); + if ( Aig_ObjIsCo(pObj) ) + Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin0(pObj), p->vIns ); + else + { + Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin0(pObj), p->vIns ); + Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin1(pObj), p->vIns ); + } + // derive internal objects + assert( p->vNodes == NULL ); + p->vNodes = Llb_ManGroupCollect( p ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Grp_t * Llb_ManGroupCreateFirst( Llb_Man_t * pMan ) +{ + Llb_Grp_t * p; + Aig_Obj_t * pObj; + int i; + p = Llb_ManGroupAlloc( pMan ); + Saig_ManForEachLo( pMan->pAig, pObj, i ) + Vec_PtrPush( p->vOuts, pObj ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Grp_t * Llb_ManGroupCreateLast( Llb_Man_t * pMan ) +{ + Llb_Grp_t * p; + Aig_Obj_t * pObj; + int i; + p = Llb_ManGroupAlloc( pMan ); + Saig_ManForEachLi( pMan->pAig, pObj, i ) + Vec_PtrPush( p->vIns, pObj ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Grp_t * Llb_ManGroupsCombine( Llb_Grp_t * p1, Llb_Grp_t * p2 ) +{ + Llb_Grp_t * p; + Aig_Obj_t * pObj; + int i; + p = Llb_ManGroupAlloc( p1->pMan ); + // create inputs + Vec_PtrForEachEntry( Aig_Obj_t *, p1->vIns, pObj, i ) + Vec_PtrPush( p->vIns, pObj ); + Vec_PtrForEachEntry( Aig_Obj_t *, p2->vIns, pObj, i ) + Vec_PtrPushUnique( p->vIns, pObj ); + // create outputs + Vec_PtrForEachEntry( Aig_Obj_t *, p1->vOuts, pObj, i ) + Vec_PtrPush( p->vOuts, pObj ); + Vec_PtrForEachEntry( Aig_Obj_t *, p2->vOuts, pObj, i ) + Vec_PtrPushUnique( p->vOuts, pObj ); + + // derive internal objects + assert( p->vNodes == NULL ); + p->vNodes = Llb_ManGroupCollect( p ); + return p; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManGroupMarkNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + if ( Aig_ObjIsTravIdPrevious(p, pObj) ) + { + Aig_ObjSetTravIdCurrent(p, pObj); + return; + } + Aig_ObjSetTravIdCurrent(p, pObj); + assert( Aig_ObjIsNode(pObj) ); + Llb_ManGroupMarkNodes_rec( p, Aig_ObjFanin0(pObj) ); + Llb_ManGroupMarkNodes_rec( p, Aig_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Creates group from two cuts derived by the flow computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Grp_t * Llb_ManGroupCreateFromCuts( Llb_Man_t * pMan, Vec_Int_t * vCut1, Vec_Int_t * vCut2 ) +{ + Llb_Grp_t * p; + Aig_Obj_t * pObj; + int i; + p = Llb_ManGroupAlloc( pMan ); + + // mark Cut1 + Aig_ManIncrementTravId( pMan->pAig ); + Aig_ManForEachObjVec( vCut1, pMan->pAig, pObj, i ) + Aig_ObjSetTravIdCurrent( pMan->pAig, pObj ); + // collect unmarked Cut2 + Aig_ManForEachObjVec( vCut2, pMan->pAig, pObj, i ) + if ( !Aig_ObjIsTravIdCurrent( pMan->pAig, pObj ) ) + Vec_PtrPush( p->vOuts, pObj ); + + // mark nodes reachable from Cut2 + Aig_ManIncrementTravId( pMan->pAig ); + Aig_ManForEachObjVec( vCut2, pMan->pAig, pObj, i ) + Llb_ManGroupMarkNodes_rec( pMan->pAig, pObj ); + // collect marked Cut1 + Aig_ManForEachObjVec( vCut1, pMan->pAig, pObj, i ) + if ( Aig_ObjIsTravIdCurrent( pMan->pAig, pObj ) ) + Vec_PtrPush( p->vIns, pObj ); + + // derive internal objects + assert( p->vNodes == NULL ); + p->vNodes = Llb_ManGroupCollect( p ); + return p; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrepareGroups( Llb_Man_t * pMan ) +{ + Aig_Obj_t * pObj; + int i; + assert( pMan->vGroups == NULL ); + pMan->vGroups = Vec_PtrAlloc( 1000 ); + Llb_ManGroupCreateFirst( pMan ); + Aig_ManForEachNode( pMan->pAig, pObj, i ) + { + if ( pObj->fMarkA ) + Llb_ManGroupCreate( pMan, pObj ); + } + Saig_ManForEachLi( pMan->pAig, pObj, i ) + { + if ( pObj->fMarkA ) + Llb_ManGroupCreate( pMan, pObj ); + } + Llb_ManGroupCreateLast( pMan ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrintSpan( Llb_Man_t * p ) +{ + Llb_Grp_t * pGroup; + Aig_Obj_t * pVar; + int i, k, Span = 0, SpanMax = 0; + Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGroup, i ) + { + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) + if ( Vec_IntEntry(p->vVarBegs, pVar->Id) == i ) + Span++; + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) + if ( Vec_IntEntry(p->vVarBegs, pVar->Id) == i ) + Span++; + + SpanMax = Abc_MaxInt( SpanMax, Span ); +printf( "%d ", Span ); + + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) + if ( Vec_IntEntry(p->vVarEnds, pVar->Id) == i ) + Span--; + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) + if ( Vec_IntEntry(p->vVarEnds, pVar->Id) == i ) + Span--; + } +printf( "\n" ); +printf( "Max = %d\n", SpanMax ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManGroupHasVar( Llb_Man_t * p, int iGroup, int iVar ) +{ + Llb_Grp_t * pGroup = (Llb_Grp_t *)Vec_PtrEntry( p->vGroups, iGroup ); + Aig_Obj_t * pObj; + int i; + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) + if ( pObj->Id == iVar ) + return 1; + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + if ( pObj->Id == iVar ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrintHisto( Llb_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, k; + Aig_ManForEachObj( p->pAig, pObj, i ) + { + if ( Vec_IntEntry(p->vObj2Var, i) < 0 ) + continue; + printf( "%3d :", i ); + for ( k = 0; k < Vec_IntEntry(p->vVarBegs, i); k++ ) + printf( " " ); + for ( ; k <= Vec_IntEntry(p->vVarEnds, i); k++ ) + printf( "%c", Llb_ManGroupHasVar(p, k, i)? '*':'-' ); + printf( "\n" ); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb1Hint.c b/src/bdd/llb/llb1Hint.c new file mode 100644 index 00000000..353b4c69 --- /dev/null +++ b/src/bdd/llb/llb1Hint.c @@ -0,0 +1,226 @@ +/**CFile**************************************************************** + + FileName [llb1Hint.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Cofactors the circuit w.r.t. the high-fanout variables.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Hint.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns CI index with the largest number of fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManMaxFanoutCi( Aig_Man_t * pAig ) +{ + Aig_Obj_t * pObj; + int i, WeightMax = -ABC_INFINITY, iInput = -1; + Aig_ManForEachCi( pAig, pObj, i ) + if ( WeightMax < Aig_ObjRefs(pObj) ) + { + WeightMax = Aig_ObjRefs(pObj); + iInput = i; + } + assert( iInput >= 0 ); + return iInput; +} + +/**Function************************************************************* + + Synopsis [Derives AIG whose PI is substituted by a constant.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Llb_ManPerformHints( Aig_Man_t * pAig, int nHintDepth ) +{ + Aig_Man_t * pNew, * pTemp; + int i, iInput; + pNew = Aig_ManDupDfs( pAig ); + for ( i = 0; i < nHintDepth; i++ ) + { + iInput = Llb_ManMaxFanoutCi( pNew ); + Abc_Print( 1, "%d %3d\n", i, iInput ); + pNew = Aig_ManDupCof( pTemp = pNew, iInput, 1 ); + Aig_ManStop( pTemp ); + } + return pNew; +} + +/**Function************************************************************* + + Synopsis [Returns CI index with the largest number of fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_ManCollectHighFanoutObjects( Aig_Man_t * pAig, int nCandMax, int fCisOnly ) +{ + Vec_Int_t * vFanouts, * vResult; + Aig_Obj_t * pObj; + int i, fChanges, PivotValue; +// int Entry; + // collect fanout counts + vFanouts = Vec_IntAlloc( 100 ); + Aig_ManForEachObj( pAig, pObj, i ) + { +// if ( !Aig_ObjIsCi(pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) + if ( !Saig_ObjIsLo(pAig,pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) + continue; + Vec_IntPush( vFanouts, Aig_ObjRefs(pObj) ); + } + Vec_IntSort( vFanouts, 1 ); + // pick the separator + nCandMax = Abc_MinInt( nCandMax, Vec_IntSize(vFanouts) - 1 ); + PivotValue = Vec_IntEntry( vFanouts, nCandMax ); + Vec_IntFree( vFanouts ); + // collect obj satisfying the constraints + vResult = Vec_IntAlloc( 100 ); + Aig_ManForEachObj( pAig, pObj, i ) + { +// if ( !Aig_ObjIsCi(pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) + if ( !Saig_ObjIsLo(pAig,pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) + continue; + if ( Aig_ObjRefs(pObj) < PivotValue ) + continue; + Vec_IntPush( vResult, Aig_ObjId(pObj) ); + } + assert( Vec_IntSize(vResult) >= nCandMax ); + // order in the decreasing order of fanouts + do + { + fChanges = 0; + for ( i = 0; i < Vec_IntSize(vResult) - 1; i++ ) + if ( Aig_ObjRefs(Aig_ManObj(pAig, Vec_IntEntry(vResult, i))) < + Aig_ObjRefs(Aig_ManObj(pAig, Vec_IntEntry(vResult, i+1))) ) + { + int Temp = Vec_IntEntry( vResult, i ); + Vec_IntWriteEntry( vResult, i, Vec_IntEntry(vResult, i+1) ); + Vec_IntWriteEntry( vResult, i+1, Temp ); + fChanges = 1; + } + } + while ( fChanges ); +/* + Vec_IntForEachEntry( vResult, Entry, i ) + printf( "%d ", Aig_ObjRefs(Aig_ManObj(pAig, Entry)) ); +printf( "\n" ); +*/ + return vResult; +} + +/**Function************************************************************* + + Synopsis [Derives AIG whose PI is substituted by a constant.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManModelCheckAigWithHints( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars ) +{ + DdManager * ddGlo = NULL; + Vec_Int_t * vHints; + Vec_Int_t * vHFCands; + int i, Entry, RetValue = -1; + abctime clk = Abc_Clock(); + assert( pPars->nHintDepth > 0 ); +/* + // perform reachability without hints + RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, NULL, NULL ); + if ( RetValue >= 0 ) + return RetValue; +*/ + // create hints representation + vHFCands = Llb_ManCollectHighFanoutObjects( pAigGlo, pPars->nHintDepth+pPars->HintFirst, 1 ); + vHints = Vec_IntStartFull( Aig_ManObjNumMax(pAigGlo) ); + // add one hint at a time till the problem is solved + Vec_IntForEachEntryStart( vHFCands, Entry, i, pPars->HintFirst ) + { + Vec_IntWriteEntry( vHints, Entry, 1 ); // change to 1 to start from zero cof!!! + // solve under hints + RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, vHints, &ddGlo ); + if ( RetValue == 0 ) + goto Finish; + if ( RetValue == 1 ) + break; + } + if ( RetValue == -1 ) + goto Finish; + // undo the hints one at a time + for ( ; i >= pPars->HintFirst; i-- ) + { + Entry = Vec_IntEntry( vHFCands, i ); + Vec_IntWriteEntry( vHints, Entry, -1 ); + // solve under relaxed hints + RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, vHints, &ddGlo ); + if ( RetValue == 0 ) + goto Finish; + if ( RetValue == 1 ) + continue; + break; + } +Finish: + if ( ddGlo ) + { + if ( ddGlo->bFunc ) + Cudd_RecursiveDeref( ddGlo, ddGlo->bFunc ); + Extra_StopManager( ddGlo ); + } + Vec_IntFreeP( &vHFCands ); + Vec_IntFreeP( &vHints ); + if ( pPars->fVerbose ) + Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clk ); + return RetValue; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb1Man.c b/src/bdd/llb/llb1Man.c new file mode 100644 index 00000000..f5de25e0 --- /dev/null +++ b/src/bdd/llb/llb1Man.c @@ -0,0 +1,218 @@ +/**CFile**************************************************************** + + FileName [llb1Man.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Reachability manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Man.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrepareVarMap( Llb_Man_t * p ) +{ + Aig_Obj_t * pObjLi, * pObjLo; + int i, iVarLi, iVarLo; + assert( p->vNs2Glo == NULL ); + assert( p->vCs2Glo == NULL ); + assert( p->vGlo2Cs == NULL ); + assert( p->vGlo2Ns == NULL ); + p->vNs2Glo = Vec_IntStartFull( Vec_IntSize(p->vVar2Obj) ); + p->vCs2Glo = Vec_IntStartFull( Vec_IntSize(p->vVar2Obj) ); + p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); + p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); + Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) + { + iVarLi = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLi)); + iVarLo = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLo)); + assert( iVarLi >= 0 && iVarLi < Vec_IntSize(p->vVar2Obj) ); + assert( iVarLo >= 0 && iVarLo < Vec_IntSize(p->vVar2Obj) ); + Vec_IntWriteEntry( p->vNs2Glo, iVarLi, i ); + Vec_IntWriteEntry( p->vCs2Glo, iVarLo, i ); + Vec_IntWriteEntry( p->vGlo2Cs, i, iVarLo ); + Vec_IntWriteEntry( p->vGlo2Ns, i, iVarLi ); + } + // add mapping of the PIs + Saig_ManForEachPi( p->pAig, pObjLo, i ) + { + iVarLo = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLo)); + Vec_IntWriteEntry( p->vCs2Glo, iVarLo, Aig_ManRegNum(p->pAig)+i ); + Vec_IntWriteEntry( p->vNs2Glo, iVarLo, Aig_ManRegNum(p->pAig)+i ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManPrepareVarLimits( Llb_Man_t * p ) +{ + Llb_Grp_t * pGroup; + Aig_Obj_t * pVar; + int i, k; + assert( p->vVarBegs == NULL ); + assert( p->vVarEnds == NULL ); + p->vVarEnds = Vec_IntStart( Aig_ManObjNumMax(p->pAig) ); + p->vVarBegs = Vec_IntStart( Aig_ManObjNumMax(p->pAig) ); + Vec_IntFill( p->vVarBegs, Aig_ManObjNumMax(p->pAig), p->pMatrix->nCols ); + + for ( i = 0; i < p->pMatrix->nCols; i++ ) + { + pGroup = p->pMatrix->pColGrps[i]; + + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) + if ( Vec_IntEntry(p->vVarBegs, pVar->Id) > i ) + Vec_IntWriteEntry( p->vVarBegs, pVar->Id, i ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) + if ( Vec_IntEntry(p->vVarBegs, pVar->Id) > i ) + Vec_IntWriteEntry( p->vVarBegs, pVar->Id, i ); + + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) + if ( Vec_IntEntry(p->vVarEnds, pVar->Id) < i ) + Vec_IntWriteEntry( p->vVarEnds, pVar->Id, i ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) + if ( Vec_IntEntry(p->vVarEnds, pVar->Id) < i ) + Vec_IntWriteEntry( p->vVarEnds, pVar->Id, i ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManStop( Llb_Man_t * p ) +{ + Llb_Grp_t * pGrp; + DdNode * bTemp; + int i; + +// Vec_IntFreeP( &p->vMem ); +// Vec_PtrFreeP( &p->vTops ); +// Vec_PtrFreeP( &p->vBots ); +// Vec_VecFreeP( (Vec_Vec_t **)&p->vCuts ); + + if ( p->pMatrix ) + Llb_MtrFree( p->pMatrix ); + Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGrp, i ) + Llb_ManGroupStop( pGrp ); + if ( p->dd ) + { +// printf( "Manager dd\n" ); + Extra_StopManager( p->dd ); + } + if ( p->ddG ) + { +// printf( "Manager ddG\n" ); + if ( p->ddG->bFunc ) + Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc ); + Extra_StopManager( p->ddG ); + } + if ( p->ddR ) + { +// printf( "Manager ddR\n" ); + if ( p->ddR->bFunc ) + Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc ); + Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i ) + Cudd_RecursiveDeref( p->ddR, bTemp ); + Extra_StopManager( p->ddR ); + } + Aig_ManStop( p->pAig ); + Vec_PtrFreeP( &p->vGroups ); + Vec_IntFreeP( &p->vVar2Obj ); + Vec_IntFreeP( &p->vObj2Var ); + Vec_IntFreeP( &p->vVarBegs ); + Vec_IntFreeP( &p->vVarEnds ); + Vec_PtrFreeP( &p->vRings ); + Vec_IntFreeP( &p->vNs2Glo ); + Vec_IntFreeP( &p->vCs2Glo ); + Vec_IntFreeP( &p->vGlo2Cs ); + Vec_IntFreeP( &p->vGlo2Ns ); +// Vec_IntFreeP( &p->vHints ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Man_t * Llb_ManStart( Aig_Man_t * pAigGlo, Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) +{ + Llb_Man_t * p; + Aig_ManCleanMarkA( pAig ); + p = ABC_CALLOC( Llb_Man_t, 1 ); + p->pAigGlo = pAigGlo; + p->pPars = pPars; + p->pAig = pAig; + p->vVar2Obj = Llb_ManMarkPivotNodes( p->pAig, pPars->fUsePivots ); + p->vObj2Var = Vec_IntInvert( p->vVar2Obj, -1 ); + p->vRings = Vec_PtrAlloc( 100 ); + Llb_ManPrepareVarMap( p ); + Llb_ManPrepareGroups( p ); + Aig_ManCleanMarkA( pAig ); + p->pMatrix = Llb_MtrCreate( p ); + p->pMatrix->pMan = p; + return p; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb1Matrix.c b/src/bdd/llb/llb1Matrix.c new file mode 100644 index 00000000..7aa9c744 --- /dev/null +++ b/src/bdd/llb/llb1Matrix.c @@ -0,0 +1,430 @@ +/**CFile**************************************************************** + + FileName [llb1Matrix.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Partition clustering as a matrix problem.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Matrix.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// 0123 nCols +// +---------------------> +// pi 0 | 111 row0 pRowSums[0] +// pi 1 | 1 11 row1 pRowSums[1] +// pi 2 | 1 11 row2 pRowSums[2] +// CS |1 1 +// CS |1 111 +// CS |111 111 +// int | 11111 +// int | 111 +// int | 111 +// int | 111 +// NS | 11 11 +// NS | 11 1 +// NS | 111 +// nRows | +// v +// cccc pColSums[0] +// oooo pColSums[1] +// llll pColSums[2] +// 0123 pColSums[3] + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Verify columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrVerifyRowsAll( Llb_Mtr_t * p ) +{ + int iRow, iCol, Counter; + for ( iCol = 0; iCol < p->nCols; iCol++ ) + { + Counter = 0; + for ( iRow = 0; iRow < p->nRows; iRow++ ) + if ( p->pMatrix[iCol][iRow] == 1 ) + Counter++; + assert( Counter == p->pColSums[iCol] ); + } +} + +/**Function************************************************************* + + Synopsis [Verify columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrVerifyColumnsAll( Llb_Mtr_t * p ) +{ + int iRow, iCol, Counter; + for ( iRow = 0; iRow < p->nRows; iRow++ ) + { + Counter = 0; + for ( iCol = 0; iCol < p->nCols; iCol++ ) + if ( p->pMatrix[iCol][iRow] == 1 ) + Counter++; + assert( Counter == p->pRowSums[iRow] ); + } +} + +/**Function************************************************************* + + Synopsis [Verify columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrVerifyMatrix( Llb_Mtr_t * p ) +{ + Llb_MtrVerifyRowsAll( p ); + Llb_MtrVerifyColumnsAll( p ); +} + +/**Function************************************************************* + + Synopsis [Sort variables in the order of removal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Llb_MtrFindVarOrder( Llb_Mtr_t * p ) +{ + int * pOrder, * pLast; + int i, k, fChanges, Temp; + pOrder = ABC_CALLOC( int, p->nRows ); + pLast = ABC_CALLOC( int, p->nRows ); + for ( i = 0; i < p->nRows; i++ ) + { + pOrder[i] = i; + for ( k = p->nCols - 1; k >= 0; k-- ) + if ( p->pMatrix[k][i] ) + { + pLast[i] = k; + break; + } + } + do + { + fChanges = 0; + for ( i = 0; i < p->nRows - 1; i++ ) + if ( pLast[i] > pLast[i+1] ) + { + Temp = pOrder[i]; + pOrder[i] = pOrder[i+1]; + pOrder[i+1] = Temp; + + Temp = pLast[i]; + pLast[i] = pLast[i+1]; + pLast[i+1] = Temp; + + fChanges = 1; + } + } + while ( fChanges ); + ABC_FREE( pLast ); + return pOrder; +} + +/**Function************************************************************* + + Synopsis [Returns type of a variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Llb_MtrVarName( Llb_Mtr_t * p, int iVar ) +{ + static char Buffer[10]; + if ( iVar < p->nPis ) + strcpy( Buffer, "pi" ); + else if ( iVar < p->nPis + p->nFfs ) + strcpy( Buffer, "CS" ); + else if ( iVar >= p->nRows - p->nFfs ) + strcpy( Buffer, "NS" ); + else + strcpy( Buffer, "int" ); + return Buffer; +} + +/**Function************************************************************* + + Synopsis [Creates one column with vars in the array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrPrint( Llb_Mtr_t * p, int fOrder ) +{ + int * pOrder = NULL; + int i, iRow, iCol; + if ( fOrder ) + pOrder = Llb_MtrFindVarOrder( p ); + for ( i = 0; i < p->nRows; i++ ) + { + iRow = pOrder ? pOrder[i] : i; + printf( "%3d : ", iRow ); + printf( "%3d ", p->pRowSums[iRow] ); + printf( "%3s ", Llb_MtrVarName(p, iRow) ); + for ( iCol = 0; iCol < p->nCols; iCol++ ) + printf( "%c", p->pMatrix[iCol][iRow] ? '*' : ' ' ); + printf( "\n" ); + } + ABC_FREE( pOrder ); +} + +/**Function************************************************************* + + Synopsis [Verify columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrPrintMatrixStats( Llb_Mtr_t * p ) +{ + int iVar, iGrp, iGrp1, iGrp2, Span = 0, nCutSize = 0, nCutSizeMax = 0; + int * pGrp1 = ABC_CALLOC( int, p->nRows ); + int * pGrp2 = ABC_CALLOC( int, p->nRows ); + for ( iVar = 0; iVar < p->nRows; iVar++ ) + { + if ( p->pRowSums[iVar] == 0 ) + continue; + for ( iGrp1 = 0; iGrp1 < p->nCols; iGrp1++ ) + if ( p->pMatrix[iGrp1][iVar] == 1 ) + break; + for ( iGrp2 = p->nCols - 1; iGrp2 >= 0; iGrp2-- ) + if ( p->pMatrix[iGrp2][iVar] == 1 ) + break; + assert( iGrp1 <= iGrp2 ); + pGrp1[iVar] = iGrp1; + pGrp2[iVar] = iGrp2; + Span += iGrp2 - iGrp1; + } + // compute span + for ( iGrp = 0; iGrp < p->nCols; iGrp++ ) + { + for ( iVar = 0; iVar < p->nRows; iVar++ ) + if ( pGrp1[iVar] == iGrp ) + nCutSize++; + if ( nCutSizeMax < nCutSize ) + nCutSizeMax = nCutSize; + for ( iVar = 0; iVar < p->nRows; iVar++ ) + if ( pGrp2[iVar] == iGrp ) + nCutSize--; + } + ABC_FREE( pGrp1 ); + ABC_FREE( pGrp2 ); + printf( "[%4d x %4d] Life-span =%6.2f Max-cut =%5d\n", + p->nCols, p->nRows, 1.0*Span/p->nRows, nCutSizeMax ); + if ( nCutSize ) + Abc_Print( -1, "Cut size is not zero (%d).\n", nCutSize ); +} + + + +/**Function************************************************************* + + Synopsis [Starts the matrix representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Mtr_t * Llb_MtrAlloc( int nPis, int nFfs, int nCols, int nRows ) +{ + Llb_Mtr_t * p; + int i; + p = ABC_CALLOC( Llb_Mtr_t, 1 ); + p->nPis = nPis; + p->nFfs = nFfs; + p->nRows = nRows; + p->nCols = nCols; + p->pRowSums = ABC_CALLOC( int, nRows ); + p->pColSums = ABC_CALLOC( int, nCols ); + p->pColGrps = ABC_CALLOC( Llb_Grp_t *, nCols ); + p->pMatrix = ABC_CALLOC( char *, nCols ); + for ( i = 0; i < nCols; i++ ) + p->pMatrix[i] = ABC_CALLOC( char, nRows ); + // partial product + p->pProdVars = ABC_CALLOC( char, nRows ); // variables in the partial product + p->pProdNums = ABC_CALLOC( int, nRows ); // var counts in the remaining partitions + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the matrix representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrFree( Llb_Mtr_t * p ) +{ + int i; + ABC_FREE( p->pProdVars ); + ABC_FREE( p->pProdNums ); + for ( i = 0; i < p->nCols; i++ ) + ABC_FREE( p->pMatrix[i] ); + ABC_FREE( p->pRowSums ); + ABC_FREE( p->pColSums ); + ABC_FREE( p->pMatrix ); + ABC_FREE( p->pColGrps ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Creates one column with vars in the array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrAddColumn( Llb_Mtr_t * p, Llb_Grp_t * pGrp ) +{ + Aig_Obj_t * pVar; + int i, iRow, iCol = pGrp->Id; + assert( iCol >= 0 && iCol < p->nCols ); + p->pColGrps[iCol] = pGrp; + Vec_PtrForEachEntry( Aig_Obj_t *, pGrp->vIns, pVar, i ) + { + iRow = Vec_IntEntry( pGrp->pMan->vObj2Var, Aig_ObjId(pVar) ); + assert( iRow >= 0 && iRow < p->nRows ); + p->pMatrix[iCol][iRow] = 1; + p->pColSums[iCol]++; + p->pRowSums[iRow]++; + } + Vec_PtrForEachEntry( Aig_Obj_t *, pGrp->vOuts, pVar, i ) + { + iRow = Vec_IntEntry( pGrp->pMan->vObj2Var, Aig_ObjId(pVar) ); + assert( iRow >= 0 && iRow < p->nRows ); + p->pMatrix[iCol][iRow] = 1; + p->pColSums[iCol]++; + p->pRowSums[iRow]++; + } +} + +/**Function************************************************************* + + Synopsis [Matrix reduce.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrRemoveSingletonRows( Llb_Mtr_t * p ) +{ + int i, k; + for ( i = 0; i < p->nRows; i++ ) + if ( p->pRowSums[i] < 2 ) + { + p->pRowSums[i] = 0; + for ( k = 0; k < p->nCols; k++ ) + { + if ( p->pMatrix[k][i] == 1 ) + { + p->pMatrix[k][i] = 0; + p->pColSums[k]--; + } + } + } +} + +/**Function************************************************************* + + Synopsis [Matrix reduce.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Mtr_t * Llb_MtrCreate( Llb_Man_t * p ) +{ + Llb_Mtr_t * pMatrix; + Llb_Grp_t * pGroup; + int i; + pMatrix = Llb_MtrAlloc( Saig_ManPiNum(p->pAig), Saig_ManRegNum(p->pAig), + Vec_PtrSize(p->vGroups), Vec_IntSize(p->vVar2Obj) ); + Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGroup, i ) + Llb_MtrAddColumn( pMatrix, pGroup ); +// Llb_MtrRemoveSingletonRows( pMatrix ); + return pMatrix; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb1Pivot.c b/src/bdd/llb/llb1Pivot.c new file mode 100644 index 00000000..7a5bb66f --- /dev/null +++ b/src/bdd/llb/llb1Pivot.c @@ -0,0 +1,254 @@ +/**CFile**************************************************************** + + FileName [llb1Pivot.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Determining pivot variables.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Pivot.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManTracePaths_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pPivot ) +{ + Aig_Obj_t * pFanout; + int k, iFan = -1; + if ( Aig_ObjIsTravIdPrevious(p, pObj) ) + return 0; + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return 1; + if ( Saig_ObjIsLi(p, pObj) ) + return 0; + if ( Saig_ObjIsPo(p, pObj) ) + return 0; + if ( pObj == pPivot ) + return 1; + assert( Aig_ObjIsCand(pObj) ); + Aig_ObjForEachFanout( p, pObj, pFanout, iFan, k ) + if ( !Llb_ManTracePaths_rec( p, pFanout, pPivot ) ) + { + Aig_ObjSetTravIdPrevious(p, pObj); + return 0; + } + Aig_ObjSetTravIdCurrent(p, pObj); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManTracePaths( Aig_Man_t * p, Aig_Obj_t * pPivot ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + Aig_ManIncrementTravId( p ); // prev = visited with path to LI (value 0) + Aig_ManIncrementTravId( p ); // cur = visited w/o path to LI (value 1) + Saig_ManForEachLo( p, pObj, i ) + Counter += Llb_ManTracePaths_rec( p, pObj, pPivot ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManTestCuts( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, Count; + Aig_ManFanoutStart( p ); + Aig_ManForEachNode( p, pObj, i ) + { + if ( Aig_ObjRefs(pObj) <= 1 ) + continue; + Count = Llb_ManTracePaths( p, pObj ); + printf( "Obj =%5d. Lev =%3d. Fanout =%5d. Count = %3d.\n", + i, Aig_ObjLevel(pObj), Aig_ObjRefs(pObj), Count ); + } + Aig_ManFanoutStop( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManLabelLiCones_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + if ( pObj->fMarkB ) + return; + pObj->fMarkB = 1; + assert( Aig_ObjIsNode(pObj) ); + Llb_ManLabelLiCones_rec( p, Aig_ObjFanin0(pObj) ); + Llb_ManLabelLiCones_rec( p, Aig_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Determine starting cut-points.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManLabelLiCones( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + // mark const and PIs + Aig_ManConst1(p)->fMarkB = 1; + Aig_ManForEachCi( p, pObj, i ) + pObj->fMarkB = 1; + // mark cones + Saig_ManForEachLi( p, pObj, i ) + Llb_ManLabelLiCones_rec( p, Aig_ObjFanin0(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Determine starting cut-points.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManMarkInternalPivots( Aig_Man_t * p ) +{ + Vec_Ptr_t * vMuxes; + Aig_Obj_t * pObj; + int i, Counter = 0; + + // remove refs due to MUXes + vMuxes = Aig_ManMuxesCollect( p ); + Aig_ManMuxesDeref( p, vMuxes ); + + // mark nodes feeding into LIs + Aig_ManCleanMarkB( p ); + Llb_ManLabelLiCones( p ); + + // mark internal nodes + Aig_ManFanoutStart( p ); + Aig_ManForEachNode( p, pObj, i ) + if ( pObj->fMarkB && pObj->nRefs > 1 ) + { + if ( Llb_ManTracePaths(p, pObj) > 0 ) + pObj->fMarkA = 1; + Counter++; + } + Aig_ManFanoutStop( p ); +// printf( "TracePath tried = %d.\n", Counter ); + + // mark nodes feeding into LIs + Aig_ManCleanMarkB( p ); + + // add refs due to MUXes + Aig_ManMuxesRef( p, vMuxes ); + Vec_PtrFree( vMuxes ); +} + +/**Function************************************************************* + + Synopsis [Determine starting cut-points.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_ManMarkPivotNodes( Aig_Man_t * p, int fUseInternal ) +{ + Vec_Int_t * vVar2Obj; + Aig_Obj_t * pObj; + int i; + // mark inputs/outputs + Aig_ManForEachCi( p, pObj, i ) + pObj->fMarkA = 1; + Saig_ManForEachLi( p, pObj, i ) + pObj->fMarkA = 1; + + // mark internal pivot nodes + if ( fUseInternal ) + Llb_ManMarkInternalPivots( p ); + + // assign variable numbers + Aig_ManConst1(p)->fMarkA = 0; + vVar2Obj = Vec_IntAlloc( 100 ); + Aig_ManForEachCi( p, pObj, i ) + Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) ); + Aig_ManForEachNode( p, pObj, i ) + if ( pObj->fMarkA ) + Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) ); + Saig_ManForEachLi( p, pObj, i ) + Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) ); + return vVar2Obj; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb1Reach.c b/src/bdd/llb/llb1Reach.c new file mode 100644 index 00000000..fae7bee2 --- /dev/null +++ b/src/bdd/llb/llb1Reach.c @@ -0,0 +1,904 @@ +/**CFile**************************************************************** + + FileName [llb1Reach.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Reachability analysis.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Reach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Derives global BDD for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManConstructOutBdd( Aig_Man_t * pAig, Aig_Obj_t * pNode, DdManager * dd ) +{ + DdNode * bBdd0, * bBdd1, * bFunc; + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj = NULL; + int i; + abctime TimeStop; + if ( Aig_ObjFanin0(pNode) == Aig_ManConst1(pAig) ) + return Cudd_NotCond( Cudd_ReadOne(dd), Aig_ObjFaninC0(pNode) ); + TimeStop = dd->TimeStop; dd->TimeStop = 0; + vNodes = Aig_ManDfsNodes( pAig, &pNode, 1 ); + assert( Vec_PtrSize(vNodes) > 0 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) ) + continue; + bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); + pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData ); + } + bFunc = (DdNode *)pObj->pData; Cudd_Ref( bFunc ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) ) + continue; + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + } + Vec_PtrFree( vNodes ); + if ( Aig_ObjIsCo(pNode) ) + bFunc = Cudd_NotCond( bFunc, Aig_ObjFaninC0(pNode) ); + Cudd_Deref( bFunc ); + dd->TimeStop = TimeStop; + return bFunc; +} + +/**Function************************************************************* + + Synopsis [Derives BDD for the group.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManConstructGroupBdd( Llb_Man_t * p, Llb_Grp_t * pGroup ) +{ + Aig_Obj_t * pObj; + DdNode * bBdd0, * bBdd1, * bRes, * bXor, * bTemp; + int i, k; + Aig_ManConst1(p->pAig)->pData = Cudd_ReadOne( p->dd ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) + pObj->pData = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vNodes, pObj, i ) + { + bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); +// pObj->pData = Extra_bddAndTime( p->dd, bBdd0, bBdd1, p->pPars->TimeTarget ); + pObj->pData = Cudd_bddAnd( p->dd, bBdd0, bBdd1 ); + if ( pObj->pData == NULL ) + { + Vec_PtrForEachEntryStop( Aig_Obj_t *, pGroup->vNodes, pObj, k, i ) + if ( pObj->pData ) + Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData ); + return NULL; + } + Cudd_Ref( (DdNode *)pObj->pData ); + } + bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + { + if ( Aig_ObjIsCo(pObj) ) + bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + else + bBdd0 = (DdNode *)pObj->pData; + bBdd1 = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + bXor = Cudd_bddXor( p->dd, bBdd0, bBdd1 ); Cudd_Ref( bXor ); +// bRes = Extra_bddAndTime( p->dd, bTemp = bRes, Cudd_Not(bXor), p->pPars->TimeTarget ); + bRes = Cudd_bddAnd( p->dd, bTemp = bRes, Cudd_Not(bXor) ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bXor ); + Vec_PtrForEachEntryStop( Aig_Obj_t *, pGroup->vNodes, pObj, k, i ) + if ( pObj->pData ) + Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData ); + return NULL; + } + Cudd_Ref( bRes ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bXor ); + } + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vNodes, pObj, i ) + Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData ); + Cudd_Deref( bRes ); + return bRes; +} + +/**Function************************************************************* + + Synopsis [Derives quantification cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManConstructQuantCubeIntern( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace, int fBackward ) +{ + Aig_Obj_t * pObj; + DdNode * bRes, * bTemp, * bVar; + int i, iGroupFirst, iGroupLast; + abctime TimeStop; + TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; + bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) + { + if ( fBackward && Saig_ObjIsPi(p->pAig, pObj) ) + continue; + iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); + iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); + assert( iGroupFirst <= iGroupLast ); + if ( iGroupFirst < iGroupLast ) + continue; + bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + { + if ( fBackward && Saig_ObjIsPi(p->pAig, pObj) ) + continue; + iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); + iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); + assert( iGroupFirst <= iGroupLast ); + if ( iGroupFirst < iGroupLast ) + continue; + bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Cudd_Deref( bRes ); + p->dd->TimeStop = TimeStop; + return bRes; +} + +/**Function************************************************************* + + Synopsis [Derives quantification cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManConstructQuantCubeFwd( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace ) +{ + Aig_Obj_t * pObj; + DdNode * bRes, * bTemp, * bVar; + int i, iGroupLast; + abctime TimeStop; + TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; + bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) + { + iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); + assert( iGroupLast >= iGrpPlace ); + if ( iGroupLast > iGrpPlace ) + continue; + bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + { + iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); + assert( iGroupLast >= iGrpPlace ); + if ( iGroupLast > iGrpPlace ) + continue; + bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Cudd_Deref( bRes ); + p->dd->TimeStop = TimeStop; + return bRes; +} + +/**Function************************************************************* + + Synopsis [Derives quantification cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManConstructQuantCubeBwd( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace ) +{ + Aig_Obj_t * pObj; + DdNode * bRes, * bTemp, * bVar; + int i, iGroupFirst; + abctime TimeStop; + TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; + bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) + { + if ( Saig_ObjIsPi(p->pAig, pObj) ) + continue; + iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); + assert( iGroupFirst <= iGrpPlace ); + if ( iGroupFirst < iGrpPlace ) + continue; + bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) + { + if ( Saig_ObjIsPi(p->pAig, pObj) ) + continue; + iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); + assert( iGroupFirst <= iGrpPlace ); + if ( iGroupFirst < iGrpPlace ) + continue; + bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); + bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Cudd_Deref( bRes ); + p->dd->TimeStop = TimeStop; + return bRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManComputeInitState( Llb_Man_t * p, DdManager * dd ) +{ + Aig_Obj_t * pObj; + DdNode * bRes, * bVar, * bTemp; + int i, iVar; + abctime TimeStop; + TimeStop = dd->TimeStop; dd->TimeStop = 0; + bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); + Saig_ManForEachLo( p->pAig, pObj, i ) + { + iVar = (dd == p->ddG) ? i : Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)); + bVar = Cudd_bddIthVar( dd, iVar ); + bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bRes ); + dd->TimeStop = TimeStop; + return bRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManComputeImage( Llb_Man_t * p, DdNode * bInit, int fBackward ) +{ + int fCheckSupport = 0; + Llb_Grp_t * pGroup; + DdNode * bImage, * bGroup, * bCube, * bTemp; + int k, Index; + bImage = bInit; Cudd_Ref( bImage ); + for ( k = 1; k < p->pMatrix->nCols-1; k++ ) + { + if ( fBackward ) + Index = p->pMatrix->nCols - 1 - k; + else + Index = k; + + // compute group BDD + pGroup = p->pMatrix->pColGrps[Index]; + bGroup = Llb_ManConstructGroupBdd( p, pGroup ); + if ( bGroup == NULL ) + { + Cudd_RecursiveDeref( p->dd, bImage ); + return NULL; + } + Cudd_Ref( bGroup ); + // quantify variables appearing only in this group + bCube = Llb_ManConstructQuantCubeIntern( p, pGroup, Index, fBackward ); Cudd_Ref( bCube ); + bGroup = Cudd_bddExistAbstract( p->dd, bTemp = bGroup, bCube ); + if ( bGroup == NULL ) + { + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bCube ); + return NULL; + } + Cudd_Ref( bGroup ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bCube ); + // perform partial product + if ( fBackward ) + bCube = Llb_ManConstructQuantCubeBwd( p, pGroup, Index ); + else + bCube = Llb_ManConstructQuantCubeFwd( p, pGroup, Index ); + Cudd_Ref( bCube ); +// bImage = Extra_bddAndAbstractTime( p->dd, bTemp = bImage, bGroup, bCube, p->pPars->TimeTarget ); + bImage = Cudd_bddAndAbstract( p->dd, bTemp = bImage, bGroup, bCube ); + if ( bImage == NULL ) + { + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bGroup ); + Cudd_RecursiveDeref( p->dd, bCube ); + return NULL; + } + Cudd_Ref( bImage ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bGroup ); + Cudd_RecursiveDeref( p->dd, bCube ); + } + + // make sure image depends on next state vars + if ( fCheckSupport ) + { + bCube = Cudd_Support( p->dd, bImage ); Cudd_Ref( bCube ); + for ( bTemp = bCube; bTemp != p->dd->one; bTemp = cuddT(bTemp) ) + { + int ObjId = Vec_IntEntry( p->vVar2Obj, bTemp->index ); + Aig_Obj_t * pObj = Aig_ManObj( p->pAig, ObjId ); + if ( !Saig_ObjIsLi(p->pAig, pObj) ) + printf( "Var %d assigned to obj %d that is not LI\n", bTemp->index, ObjId ); + } + Cudd_RecursiveDeref( p->dd, bCube ); + } + Cudd_Deref( bImage ); + return bImage; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ManCreateConstraints( Llb_Man_t * p, Vec_Int_t * vHints, int fUseNsVars ) +{ + DdNode * bConstr, * bFunc, * bTemp; + Aig_Obj_t * pObj; + int i, Entry; + abctime TimeStop; + if ( vHints == NULL ) + return Cudd_ReadOne( p->dd ); + TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; + assert( Aig_ManCiNum(p->pAig) == Aig_ManCiNum(p->pAigGlo) ); + // assign const and PI nodes to the original AIG + Aig_ManCleanData( p->pAig ); + Aig_ManConst1( p->pAig )->pData = Cudd_ReadOne( p->dd ); + Saig_ManForEachPi( p->pAig, pObj, i ) + pObj->pData = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var,Aig_ObjId(pObj)) ); + Saig_ManForEachLo( p->pAig, pObj, i ) + { + if ( fUseNsVars ) + Entry = Vec_IntEntry( p->vObj2Var, Aig_ObjId(Saig_ObjLoToLi(p->pAig, pObj)) ); + else + Entry = Vec_IntEntry( p->vObj2Var, Aig_ObjId(pObj) ); + pObj->pData = Cudd_bddIthVar( p->dd, Entry ); + } + // transfer them to the global AIG + Aig_ManCleanData( p->pAigGlo ); + Aig_ManConst1( p->pAigGlo )->pData = Cudd_ReadOne( p->dd ); + Aig_ManForEachCi( p->pAigGlo, pObj, i ) + pObj->pData = Aig_ManCi(p->pAig, i)->pData; + // derive consraints + bConstr = Cudd_ReadOne( p->dd ); Cudd_Ref( bConstr ); + Vec_IntForEachEntry( vHints, Entry, i ) + { + if ( Entry != 0 && Entry != 1 ) + continue; + bFunc = Llb_ManConstructOutBdd( p->pAigGlo, Aig_ManObj(p->pAigGlo, i), p->dd ); Cudd_Ref( bFunc ); + bFunc = Cudd_NotCond( bFunc, Entry ); // restrict to not constraint + // make the product + bConstr = Cudd_bddAnd( p->dd, bTemp = bConstr, bFunc ); Cudd_Ref( bConstr ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bFunc ); + } + Cudd_Deref( bConstr ); + p->dd->TimeStop = TimeStop; + return bConstr; +} + +/**Function************************************************************* + + Synopsis [Perform reachability with hints and returns reached states in ppGlo.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Llb_ManReachDeriveCex( Llb_Man_t * p ) +{ + Abc_Cex_t * pCex; + Aig_Obj_t * pObj; + DdNode * bState = NULL, * bImage, * bOneCube, * bTemp, * bRing; + int i, v, RetValue, nPiOffset; + char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) ); + assert( Vec_PtrSize(p->vRings) > 0 ); + + p->dd->TimeStop = 0; + p->ddR->TimeStop = 0; + +/* + Saig_ManForEachLo( p->pAig, pObj, i ) + printf( "%d ", pObj->Id ); + printf( "\n" ); + Saig_ManForEachLi( p->pAig, pObj, i ) + printf( "%d(%d) ", pObj->Id, Aig_ObjFaninId0(pObj) ); + printf( "\n" ); +*/ + // allocate room for the counter-example + pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) ); + pCex->iFrame = Vec_PtrSize(p->vRings) - 1; + pCex->iPo = -1; + + // get the last cube + bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc ); Cudd_Ref( bOneCube ); + RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); + Cudd_RecursiveDeref( p->ddR, bOneCube ); + assert( RetValue ); + + // write PIs of counter-example + nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1); + Saig_ManForEachPi( p->pAig, pObj, i ) + if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) + Abc_InfoSetBit( pCex->pData, nPiOffset + i ); + + // write state in terms of NS variables + if ( Vec_PtrSize(p->vRings) > 1 ) + { + bState = Llb_CoreComputeCube( p->dd, p->vGlo2Ns, 1, pValues ); Cudd_Ref( bState ); + } + // perform backward analysis + Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v ) + { + if ( v == Vec_PtrSize(p->vRings) - 1 ) + continue; +//Extra_bddPrintSupport( p->dd, bState ); printf( "\n" ); +//Extra_bddPrintSupport( p->dd, bRing ); printf( "\n" ); + // compute the next states + bImage = Llb_ManComputeImage( p, bState, 1 ); + assert( bImage != NULL ); + Cudd_Ref( bImage ); + Cudd_RecursiveDeref( p->dd, bState ); +//Extra_bddPrintSupport( p->dd, bImage ); printf( "\n" ); + + // move reached states into ring manager + bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) ); Cudd_Ref( bImage ); + Cudd_RecursiveDeref( p->dd, bTemp ); +//Extra_bddPrintSupport( p->ddR, bImage ); printf( "\n" ); + + // intersect with the previous set + bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing ); Cudd_Ref( bOneCube ); + Cudd_RecursiveDeref( p->ddR, bImage ); + + // find any assignment of the BDD + RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); + Cudd_RecursiveDeref( p->ddR, bOneCube ); + assert( RetValue ); +/* + for ( i = 0; i < p->ddR->size; i++ ) + printf( "%d ", pValues[i] ); + printf( "\n" ); +*/ + // write PIs of counter-example + nPiOffset -= Saig_ManPiNum(p->pAig); + Saig_ManForEachPi( p->pAig, pObj, i ) + if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) + Abc_InfoSetBit( pCex->pData, nPiOffset + i ); + + // check that we get the init state + if ( v == 0 ) + { + Saig_ManForEachLo( p->pAig, pObj, i ) + assert( pValues[i] == 0 ); + break; + } + + // write state in terms of NS variables + bState = Llb_CoreComputeCube( p->dd, p->vGlo2Ns, 1, pValues ); Cudd_Ref( bState ); + } + assert( nPiOffset == Saig_ManRegNum(p->pAig) ); + // update the output number +//Abc_CexPrint( pCex ); + RetValue = Saig_ManFindFailedPoCex( p->pAigGlo, pCex ); + assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pAigGlo) ); // invalid CEX!!! + pCex->iPo = RetValue; + // cleanup + ABC_FREE( pValues ); + return pCex; +} + +/**Function************************************************************* + + Synopsis [Perform reachability with hints and returns reached states in ppGlo.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManReachability( Llb_Man_t * p, Vec_Int_t * vHints, DdManager ** pddGlo ) +{ + int * pNs2Glo = Vec_IntArray( p->vNs2Glo ); + int * pCs2Glo = Vec_IntArray( p->vCs2Glo ); + int * pGlo2Cs = Vec_IntArray( p->vGlo2Cs ); + DdNode * bCurrent, * bReached, * bNext, * bTemp, * bCube; + DdNode * bConstrCs, * bConstrNs; + abctime clk2, clk = Abc_Clock(); + int nIters, nBddSize = 0; +// int nThreshold = 10000; + + // compute time to stop + p->pPars->TimeTarget = p->pPars->TimeLimit ? p->pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0; + + // define variable limits + Llb_ManPrepareVarLimits( p ); + + // start the managers + assert( p->dd == NULL ); + assert( p->ddG == NULL ); + assert( p->ddR == NULL ); + p->dd = Cudd_Init( Vec_IntSize(p->vVar2Obj), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + p->ddR = Cudd_Init( Aig_ManCiNum(p->pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + if ( pddGlo && *pddGlo ) + p->ddG = *pddGlo, *pddGlo = NULL; + else + p->ddG = Cudd_Init( Aig_ManRegNum(p->pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + + if ( p->pPars->fReorder ) + { + Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); + Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT ); + Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT ); + } + else + { + Cudd_AutodynDisable( p->dd ); + Cudd_AutodynDisable( p->ddG ); + Cudd_AutodynDisable( p->ddR ); + } + + // set the stop time parameter + p->dd->TimeStop = p->pPars->TimeTarget; + p->ddG->TimeStop = p->pPars->TimeTarget; + p->ddR->TimeStop = p->pPars->TimeTarget; + + // create bad state in the ring manager + p->ddR->bFunc = Llb_BddComputeBad( p->pAigGlo, p->ddR, p->pPars->TimeTarget ); + if ( p->ddR->bFunc == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + Cudd_Ref( p->ddR->bFunc ); + + // derive constraints + bConstrCs = Llb_ManCreateConstraints( p, vHints, 0 ); Cudd_Ref( bConstrCs ); + bConstrNs = Llb_ManCreateConstraints( p, vHints, 1 ); Cudd_Ref( bConstrNs ); +//Extra_bddPrint( p->dd, bConstrCs ); printf( "\n" ); +//Extra_bddPrint( p->dd, bConstrNs ); printf( "\n" ); + + // perform reachability analysis + // compute the starting set of states + if ( p->ddG->bFunc ) + { + bReached = p->ddG->bFunc; p->ddG->bFunc = NULL; + bCurrent = Extra_TransferPermute( p->ddG, p->dd, bReached, pGlo2Cs ); Cudd_Ref( bCurrent ); + } + else + { + bReached = Llb_ManComputeInitState( p, p->ddG ); Cudd_Ref( bReached ); + bCurrent = Llb_ManComputeInitState( p, p->dd ); Cudd_Ref( bCurrent ); + } +//Extra_bddPrintSupport( p->ddG, bReached ); printf( "\n" ); +//Extra_bddPrintSupport( p->dd, bCurrent ); printf( "\n" ); + +//Extra_bddPrintSupport( p->dd, bCurrent ); printf( "\n" ); + for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ ) + { + clk2 = Abc_Clock(); + // check the runtime limit + if ( p->pPars->TimeLimit && Abc_Clock() > p->pPars->TimeTarget ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout during image computation (%d seconds).\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; + Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + + // save the onion ring + bTemp = Extra_TransferPermute( p->dd, p->ddR, bCurrent, pCs2Glo ); + if ( bTemp == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during ring transfer.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; + Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bTemp ); + Vec_PtrPush( p->vRings, bTemp ); + + // check it for bad states + if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) ) + { + assert( p->pAigGlo->pSeqModel == NULL ); + if ( !p->pPars->fBackward ) + p->pAigGlo->pSeqModel = Llb_ManReachDeriveCex( p ); + if ( !p->pPars->fSilent ) + { + if ( !p->pPars->fBackward ) + Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", p->pAigGlo->pSeqModel->iPo, p->pAigGlo->pName, p->pAigGlo->pName, nIters ); + else + Abc_Print( 1, "Output ??? of miter \"%s\" was asserted in frame %d (counter-example is not produced). ", p->pAigGlo->pName, nIters ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; + Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return 0; + } + + // restrict reachable states using constraints + if ( vHints ) + { + bCurrent = Cudd_bddAnd( p->dd, bTemp = bCurrent, bConstrCs ); Cudd_Ref( bCurrent ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + + // quantify variables appearing only in the init state + bCube = Llb_ManConstructQuantCubeIntern( p, (Llb_Grp_t *)Vec_PtrEntry(p->vGroups,0), 0, 0 ); Cudd_Ref( bCube ); + bCurrent = Cudd_bddExistAbstract( p->dd, bTemp = bCurrent, bCube ); Cudd_Ref( bCurrent ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bCube ); + + // compute the next states + bNext = Llb_ManComputeImage( p, bCurrent, 0 ); + if ( bNext == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; + Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bNext ); + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + + // restrict reachable states using constraints + if ( vHints ) + { + bNext = Cudd_bddAnd( p->dd, bTemp = bNext, bConstrNs ); Cudd_Ref( bNext ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } +//Extra_bddPrintSupport( p->dd, bNext ); printf( "\n" ); + + // remap these states into the current state vars +// bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pNs2Glo ); Cudd_Ref( bNext ); +// Cudd_RecursiveDeref( p->dd, bTemp ); +// bNext = Extra_TransferPermuteTime( p->dd, p->ddG, bTemp = bNext, pNs2Glo, p->pPars->TimeTarget ); + bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pNs2Glo ); + if ( bNext == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; + Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bNext ); + Cudd_RecursiveDeref( p->dd, bTemp ); + + + // check if there are any new states + if ( Cudd_bddLeq( p->ddG, bNext, bReached ) ) // implication = no new states + { + Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; + break; + } + + // check the BDD size + nBddSize = Cudd_DagSize(bNext); + if ( nBddSize > p->pPars->nBddMax ) + { + Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; + break; + } + + // get the new states + bCurrent = Cudd_bddAnd( p->ddG, bNext, Cudd_Not(bReached) ); + if ( bCurrent == NULL ) + { + Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + break; + } + Cudd_Ref( bCurrent ); + // minimize the new states with the reached states +// bCurrent = Cudd_bddConstrain( p->ddG, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); +// bCurrent = Cudd_bddRestrict( p->ddG, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); +// Cudd_RecursiveDeref( p->ddG, bTemp ); +//printf( "Initial BDD =%7d. Constrained BDD =%7d.\n", Cudd_DagSize(bTemp), Cudd_DagSize(bCurrent) ); + + // remap these states into the current state vars +// bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs ); Cudd_Ref( bCurrent ); +// Cudd_RecursiveDeref( p->ddG, bTemp ); +// bCurrent = Extra_TransferPermuteTime( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs, p->pPars->TimeTarget ); + bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs ); + if ( bCurrent == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->ddG, bTemp ); + Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; + Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bCurrent ); + Cudd_RecursiveDeref( p->ddG, bTemp ); + + + // add to the reached states + bReached = Cudd_bddOr( p->ddG, bTemp = bReached, bNext ); + if ( bReached == NULL ) + { + Cudd_RecursiveDeref( p->ddG, bTemp ); bTemp = NULL; + Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; + break; + } + Cudd_Ref( bReached ); + Cudd_RecursiveDeref( p->ddG, bTemp ); + Cudd_RecursiveDeref( p->ddG, bNext ); + bNext = NULL; + + if ( p->pPars->fVerbose ) + { + fprintf( stdout, "F =%5d : ", nIters ); + fprintf( stdout, "Im =%6d ", nBddSize ); + fprintf( stdout, "(%4d %3d) ", Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) ); + fprintf( stdout, "Rea =%6d ", Cudd_DagSize(bReached) ); + fprintf( stdout, "(%4d%4d) ", Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk2 ); + } +/* + if ( p->pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); +// Extra_bddPrint( p->ddG, bReached );printf( "\n" ); + fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); + fflush( stdout ); + } +*/ + } + Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; + Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; + if ( bReached == NULL ) + { + p->pPars->iFrame = nIters - 1; + return 0; // reachable + } +// assert( bCurrent == NULL ); + if ( bCurrent ) + Cudd_RecursiveDeref( p->dd, bCurrent ); + // report the stats + if ( p->pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); + if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) + fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters ); + else + fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters ); + fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); + fflush( stdout ); + } + if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) + { + if ( !p->pPars->fSilent ) + printf( "Verified only for states reachable in %d frames. ", nIters ); + p->pPars->iFrame = p->pPars->nIterMax; + Cudd_RecursiveDeref( p->ddG, bReached ); + return -1; // undecided + } + if ( pddGlo ) + { + assert( p->ddG->bFunc == NULL ); + p->ddG->bFunc = bReached; bReached = NULL; + assert( *pddGlo == NULL ); + *pddGlo = p->ddG; p->ddG = NULL; + } + else + Cudd_RecursiveDeref( p->ddG, bReached ); + if ( !p->pPars->fSilent ) + printf( "The miter is proved unreachable after %d iterations. ", nIters ); + p->pPars->iFrame = nIters - 1; + return 1; // unreachable +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb1Sched.c b/src/bdd/llb/llb1Sched.c new file mode 100644 index 00000000..51de973a --- /dev/null +++ b/src/bdd/llb/llb1Sched.c @@ -0,0 +1,257 @@ +/**CFile**************************************************************** + + FileName [llb1Sched.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Partition scheduling algorithm.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb1Sched.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Swaps two rows.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrSwapColumns( Llb_Mtr_t * p, int iCol1, int iCol2 ) +{ + Llb_Grp_t * pGemp; + char * pTemp; + int iTemp; + assert( iCol1 >= 0 && iCol1 < p->nCols ); + assert( iCol2 >= 0 && iCol2 < p->nCols ); + if ( iCol1 == iCol2 ) + return; + assert( iCol1 != iCol2 ); + // swap col groups + pGemp = p->pColGrps[iCol1]; + p->pColGrps[iCol1] = p->pColGrps[iCol2]; + p->pColGrps[iCol2] = pGemp; + // swap col vectors + pTemp = p->pMatrix[iCol1]; + p->pMatrix[iCol1] = p->pMatrix[iCol2]; + p->pMatrix[iCol2] = pTemp; + // swap col sums + iTemp = p->pColSums[iCol1]; + p->pColSums[iCol1] = p->pColSums[iCol2]; + p->pColSums[iCol2] = iTemp; +} + +/**Function************************************************************* + + Synopsis [Find columns which brings as few vars as possible.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_MtrFindBestColumn( Llb_Mtr_t * p, int iGrpStart ) +{ + int Cost, Cost2, CostBest = ABC_INFINITY, Cost2Best = ABC_INFINITY; + int WeightCur, WeightBest = -ABC_INFINITY, iGrp = -1, iGrpBest = -1; + int k, c, iVar, Counter; + // find partition that reduces partial product as much as possible + for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ ) + { + if ( p->pRowSums[iVar] < 2 ) + continue; + // look at present variables that can be quantified + if ( !(p->pProdVars[iVar] == 1 && p->pProdNums[iVar] == 1) ) + continue; + // check that it appears in one partition only + Counter = 0; + for ( c = iGrpStart; c < p->nCols-1; c++ ) + if ( p->pMatrix[c][iVar] == 1 ) + { + iGrp = c; + Counter++; + } + assert( Counter == 1 ); + if ( Counter != 1 ) + Abc_Print( -1, "Llb_MtrFindBestColumn() Internal error!\n" ); + // find weight of this column + WeightCur = 0; + for ( k = 0; k < p->nRows; k++ ) + { + // increase weight if variable k will be quantified from partial product + if ( p->pProdVars[k] == 1 && p->pMatrix[iGrp][k] == 1 && p->pProdNums[k] == 1 ) + WeightCur += 2; + // decrease weight if variable k will be added to partial product + if ( p->pProdVars[k] == 0 && p->pMatrix[iGrp][k] == 1 ) + WeightCur--; + } + if ( WeightCur > 0 && WeightBest < WeightCur ) + { + WeightBest = WeightCur; + iGrpBest = iGrp; + } + } + if ( iGrpBest >= 0 ) + return iGrpBest; + // could not find the group with any vars to quantify + // select the group that contains as few extra variables as possible + // if there is a tie, select variables that appear in less groups than others + for ( iGrp = iGrpStart; iGrp < p->nCols-1; iGrp++ ) + { + Cost = Cost2 = 0; + for ( k = 0; k < p->nRows; k++ ) + if ( p->pProdVars[k] == 0 && p->pMatrix[iGrp][k] == 1 ) + { + Cost++; + Cost2 += p->pProdNums[k]; + } + if ( CostBest > Cost || + (CostBest == Cost && Cost2 > Cost2Best) ) + { + CostBest = Cost; + Cost2Best = Cost2; + iGrpBest = iGrp; + } + } + return iGrpBest; +} + +/**Function************************************************************* + + Synopsis [Returns the number of variables that will be saved.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrUseSelectedColumn( Llb_Mtr_t * p, int iCol ) +{ + int iVar; + assert( iCol >= 1 && iCol < p->nCols - 1 ); + for ( iVar = 0; iVar < p->nRows; iVar++ ) + { + if ( p->pMatrix[iCol][iVar] == 0 ) + continue; + if ( p->pProdVars[iVar] == 1 && p->pProdNums[iVar] == 1 ) + { + p->pProdVars[iVar] = 0; + p->pProdNums[iVar] = 0; + continue; + } + if ( p->pProdVars[iVar] == 0 ) + { + p->pProdVars[iVar] = 1; + p->pProdNums[iVar] = p->pRowSums[iVar]; + } + p->pProdNums[iVar]--; + assert( p->pProdNums[iVar] >= 0 ); + if ( p->pProdNums[iVar] < 0 ) + Abc_Print( -1, "Llb_MtrUseSelectedColumn() Internal error!\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Verify columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrVerifyColumns( Llb_Mtr_t * p, int iGrpStart ) +{ + int iVar, iGrp, Counter; + for ( iVar = 0; iVar < p->nRows; iVar++ ) + { + if ( p->pProdVars[iVar] == 0 ) + continue; + Counter = 0; + for ( iGrp = iGrpStart; iGrp < p->nCols; iGrp++ ) + if ( p->pMatrix[iGrp][iVar] == 1 ) + Counter++; + assert( Counter == p->pProdNums[iVar] ); + if ( Counter != p->pProdNums[iVar] ) + Abc_Print( -1, "Llb_MtrVerifyColumns(): Internal error.\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Matrix reduce.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MtrSchedule( Llb_Mtr_t * p ) +{ + int iGrp, iGrpBest, i; + // start partial product + for ( i = 0; i < p->nRows; i++ ) + { + if ( i >= p->nPis && i < p->nPis + p->nFfs ) + { + p->pProdVars[i] = 1; + p->pProdNums[i] = p->pRowSums[i] - 1; + } + else + { + p->pProdVars[i] = 0; + p->pProdNums[i] = p->pRowSums[i]; + } + } + // order the partitions + Llb_MtrVerifyMatrix( p ); + for ( iGrp = 1; iGrp < p->nCols-1; iGrp++ ) + { + Llb_MtrVerifyColumns( p, iGrp ); + iGrpBest = Llb_MtrFindBestColumn( p, iGrp ); + Llb_MtrUseSelectedColumn( p, iGrpBest ); + Llb_MtrSwapColumns( p, iGrp, iGrpBest ); + } + Llb_MtrVerifyMatrix( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb2Bad.c b/src/bdd/llb/llb2Bad.c new file mode 100644 index 00000000..ac04b563 --- /dev/null +++ b/src/bdd/llb/llb2Bad.c @@ -0,0 +1,138 @@ +/**CFile**************************************************************** + + FileName [llb2Bad.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Computing bad states.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Bad.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes bad in working manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_BddComputeBad( Aig_Man_t * pInit, DdManager * dd, abctime TimeOut ) +{ + Vec_Ptr_t * vNodes; + DdNode * bBdd0, * bBdd1, * bTemp, * bResult; + Aig_Obj_t * pObj; + int i, k; + assert( Cudd_ReadSize(dd) == Aig_ManCiNum(pInit) ); + // initialize elementary variables + Aig_ManConst1(pInit)->pData = Cudd_ReadOne( dd ); + Saig_ManForEachLo( pInit, pObj, i ) + pObj->pData = Cudd_bddIthVar( dd, i ); + Saig_ManForEachPi( pInit, pObj, i ) + pObj->pData = Cudd_bddIthVar( dd, Aig_ManRegNum(pInit) + i ); + // compute internal nodes + vNodes = Aig_ManDfsNodes( pInit, (Aig_Obj_t **)Vec_PtrArray(pInit->vCos), Saig_ManPoNum(pInit) ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) ) + continue; + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); +// pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeOut ); + pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); + if ( pObj->pData == NULL ) + { + Vec_PtrForEachEntryStop( Aig_Obj_t *, vNodes, pObj, k, i ) + if ( pObj->pData ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + Vec_PtrFree( vNodes ); + return NULL; + } + Cudd_Ref( (DdNode *)pObj->pData ); + } + // quantify PIs of each PO + bResult = Cudd_ReadLogicZero( dd ); Cudd_Ref( bResult ); + Saig_ManForEachPo( pInit, pObj, i ) + { + bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bResult = Cudd_bddOr( dd, bTemp = bResult, bBdd0 ); Cudd_Ref( bResult ); + Cudd_RecursiveDeref( dd, bTemp ); + } + // deref + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) ) + continue; + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + } + Vec_PtrFree( vNodes ); + Cudd_Deref( bResult ); + return bResult; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_BddQuantifyPis( Aig_Man_t * pInit, DdManager * dd, DdNode * bFunc ) +{ + DdNode * bVar, * bCube, * bTemp; + Aig_Obj_t * pObj; + int i; + abctime TimeStop; + assert( Cudd_ReadSize(dd) == Aig_ManCiNum(pInit) ); + TimeStop = dd->TimeStop; dd->TimeStop = 0; + // create PI cube + bCube = Cudd_ReadOne( dd ); Cudd_Ref( bCube ); + Saig_ManForEachPi( pInit, pObj, i ) { + bVar = Cudd_bddIthVar( dd, Aig_ManRegNum(pInit) + i ); + bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + } + // quantify PI cube + bFunc = Cudd_bddExistAbstract( dd, bFunc, bCube ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( dd, bCube ); + Cudd_Deref( bFunc ); + dd->TimeStop = TimeStop; + return bFunc; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb2Core.c b/src/bdd/llb/llb2Core.c new file mode 100644 index 00000000..3d62b322 --- /dev/null +++ b/src/bdd/llb/llb2Core.c @@ -0,0 +1,777 @@ +/**CFile**************************************************************** + + FileName [llb2Core.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Core procedure.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Core.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Llb_Img_t_ Llb_Img_t; +struct Llb_Img_t_ +{ + Aig_Man_t * pInit; // AIG manager + Aig_Man_t * pAig; // AIG manager + Gia_ParLlb_t * pPars; // parameters + + DdManager * dd; // BDD manager + DdManager * ddG; // BDD manager + DdManager * ddR; // BDD manager + Vec_Ptr_t * vDdMans; // BDD managers for each partition + Vec_Ptr_t * vRings; // onion rings in ddR + + Vec_Int_t * vDriRefs; // driver references + Vec_Int_t * vVarsCs; // cur state variables + Vec_Int_t * vVarsNs; // next state variables + + Vec_Int_t * vCs2Glo; // cur state variables into global variables + Vec_Int_t * vNs2Glo; // next state variables into global variables + Vec_Int_t * vGlo2Cs; // global variables into cur state variables + Vec_Int_t * vGlo2Ns; // global variables into next state variables +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes cube composed of given variables with given values.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_CoreComputeCube( DdManager * dd, Vec_Int_t * vVars, int fUseVarIndex, char * pValues ) +{ + DdNode * bRes, * bVar, * bTemp; + int i, iVar, Index; + abctime TimeStop; + TimeStop = dd->TimeStop; dd->TimeStop = 0; + bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); + Vec_IntForEachEntry( vVars, Index, i ) + { + iVar = fUseVarIndex ? Index : i; + bVar = Cudd_NotCond( Cudd_bddIthVar(dd, iVar), (int)(pValues == NULL || pValues[i] != 1) ); + bRes = Cudd_bddAnd( dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bRes ); + dd->TimeStop = TimeStop; + return bRes; +} + +/**Function************************************************************* + + Synopsis [Derives counter-example by backward reachability.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Llb_CoreDeriveCex( Llb_Img_t * p ) +{ + Abc_Cex_t * pCex; + Aig_Obj_t * pObj; + Vec_Ptr_t * vSupps, * vQuant0, * vQuant1; + DdNode * bState = NULL, * bImage, * bOneCube, * bTemp, * bRing; + int i, v, RetValue, nPiOffset; + char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) ); + assert( Vec_PtrSize(p->vRings) > 0 ); + + p->dd->TimeStop = 0; + p->ddR->TimeStop = 0; + + // get supports and quantified variables + Vec_PtrReverseOrder( p->vDdMans ); + vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsNs, p->vVarsCs, 1, 0 ); + Llb_ImgSchedule( vSupps, &vQuant0, &vQuant1, 0 ); + Vec_VecFree( (Vec_Vec_t *)vSupps ); + Llb_ImgQuantifyReset( p->vDdMans ); +// Llb_ImgQuantifyFirst( p->pAig, p->vDdMans, vQuant0 ); + + // allocate room for the counter-example + pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) ); + pCex->iFrame = Vec_PtrSize(p->vRings) - 1; + pCex->iPo = -1; + + // get the last cube + bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc ); Cudd_Ref( bOneCube ); + RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); + Cudd_RecursiveDeref( p->ddR, bOneCube ); + assert( RetValue ); + + // write PIs of counter-example + nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1); + Saig_ManForEachPi( p->pAig, pObj, i ) + if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) + Abc_InfoSetBit( pCex->pData, nPiOffset + i ); + + // write state in terms of NS variables + if ( Vec_PtrSize(p->vRings) > 1 ) + { + bState = Llb_CoreComputeCube( p->dd, p->vVarsNs, 1, pValues ); Cudd_Ref( bState ); + } + // perform backward analysis + Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v ) + { + if ( v == Vec_PtrSize(p->vRings) - 1 ) + continue; + // compute the next states + bImage = Llb_ImgComputeImage( p->pAig, p->vDdMans, p->dd, bState, + vQuant0, vQuant1, p->vDriRefs, p->pPars->TimeTarget, 1, 0, 0 ); + assert( bImage != NULL ); + Cudd_Ref( bImage ); + Cudd_RecursiveDeref( p->dd, bState ); +//Extra_bddPrintSupport( p->dd, bImage ); printf( "\n" ); + + // move reached states into ring manager + bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) ); Cudd_Ref( bImage ); + Cudd_RecursiveDeref( p->dd, bTemp ); + + // intersect with the previous set + bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing ); Cudd_Ref( bOneCube ); + Cudd_RecursiveDeref( p->ddR, bImage ); + + // find any assignment of the BDD + RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); + Cudd_RecursiveDeref( p->ddR, bOneCube ); + assert( RetValue ); + + // write PIs of counter-example + nPiOffset -= Saig_ManPiNum(p->pAig); + Saig_ManForEachPi( p->pAig, pObj, i ) + if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) + Abc_InfoSetBit( pCex->pData, nPiOffset + i ); + + // check that we get the init state + if ( v == 0 ) + { + Saig_ManForEachLo( p->pAig, pObj, i ) + assert( pValues[i] == 0 ); + break; + } + + // write state in terms of NS variables + bState = Llb_CoreComputeCube( p->dd, p->vVarsNs, 1, pValues ); Cudd_Ref( bState ); + } + assert( nPiOffset == Saig_ManRegNum(p->pAig) ); + // update the output number + RetValue = Saig_ManFindFailedPoCex( p->pInit, pCex ); + assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pInit) ); // invalid CEX!!! + pCex->iPo = RetValue; + // cleanup + ABC_FREE( pValues ); + Vec_VecFree( (Vec_Vec_t *)vQuant0 ); + Vec_VecFree( (Vec_Vec_t *)vQuant1 ); + return pCex; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_CoreReachability_int( Llb_Img_t * p, Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1 ) +{ + int * pLoc2Glo = p->pPars->fBackward? Vec_IntArray( p->vCs2Glo ) : Vec_IntArray( p->vNs2Glo ); + int * pLoc2GloR = p->pPars->fBackward? Vec_IntArray( p->vNs2Glo ) : Vec_IntArray( p->vCs2Glo ); + int * pGlo2Loc = p->pPars->fBackward? Vec_IntArray( p->vGlo2Ns ) : Vec_IntArray( p->vGlo2Cs ); + DdNode * bCurrent, * bReached, * bNext, * bTemp; + abctime clk2, clk = Abc_Clock(); + int nIters, nBddSize;//, iOutFail = -1; +/* + // compute time to stop + if ( p->pPars->TimeLimit ) + p->pPars->TimeTarget = Abc_Clock() + p->pPars->TimeLimit * CLOCKS_PER_SEC; + else + p->pPars->TimeTarget = 0; +*/ + + if ( Abc_Clock() > p->pPars->TimeTarget ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) before image computation.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + + // set the stop time parameter + p->dd->TimeStop = p->pPars->TimeTarget; + p->ddG->TimeStop = p->pPars->TimeTarget; + p->ddR->TimeStop = p->pPars->TimeTarget; + + // compute initial states + if ( p->pPars->fBackward ) + { + // create init state in the global manager + bTemp = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget ); + if ( bTemp == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) while computing bad states.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + Cudd_Ref( bTemp ); + // create bad state in the ring manager + p->ddR->bFunc = Llb_CoreComputeCube( p->ddR, p->vVarsCs, 0, NULL ); Cudd_Ref( p->ddR->bFunc ); + bCurrent = Llb_BddQuantifyPis( p->pInit, p->ddR, bTemp ); Cudd_Ref( bCurrent ); + Cudd_RecursiveDeref( p->ddR, bTemp ); + bReached = Cudd_bddTransfer( p->ddR, p->ddG, bCurrent ); Cudd_Ref( bReached ); + Cudd_RecursiveDeref( p->ddR, bCurrent ); + // move init state to the working manager + bCurrent = Extra_TransferPermute( p->ddG, p->dd, bReached, pGlo2Loc ); + if ( bCurrent == NULL ) + { + Cudd_RecursiveDeref( p->ddG, bReached ); + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during transfer 0.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + Cudd_Ref( bCurrent ); + } + else + { + // create bad state in the ring manager + p->ddR->bFunc = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget ); + if ( p->ddR->bFunc == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) while computing bad states.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + Cudd_Ref( p->ddR->bFunc ); + // create init state in the working and global manager + bCurrent = Llb_CoreComputeCube( p->dd, p->vVarsCs, 1, NULL ); Cudd_Ref( bCurrent ); + bReached = Llb_CoreComputeCube( p->ddG, p->vVarsCs, 0, NULL ); Cudd_Ref( bReached ); +//Extra_bddPrint( p->dd, bCurrent ); printf( "\n" ); +//Extra_bddPrint( p->ddG, bReached ); printf( "\n" ); + } + + // compute onion rings + for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ ) + { + clk2 = Abc_Clock(); + // check the runtime limit + if ( p->pPars->TimeLimit && Abc_Clock() > p->pPars->TimeTarget ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + + // save the onion ring + bTemp = Extra_TransferPermute( p->dd, p->ddR, bCurrent, pLoc2GloR ); + if ( bTemp == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bTemp ); + Vec_PtrPush( p->vRings, bTemp ); + + // check it for bad states + if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) ) + { + assert( p->pInit->pSeqModel == NULL ); + if ( !p->pPars->fBackward ) + p->pInit->pSeqModel = Llb_CoreDeriveCex( p ); + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + if ( !p->pPars->fSilent ) + { + if ( !p->pPars->fBackward ) + Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", p->pInit->pSeqModel->iPo, p->pInit->pName, nIters ); + else + Abc_Print( 1, "Output ??? was asserted in frame %d (counter-example is not produced). ", nIters ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + p->pPars->iFrame = nIters - 1; + return 0; + } + + // compute the next states + bNext = Llb_ImgComputeImage( p->pAig, p->vDdMans, p->dd, bCurrent, + vQuant0, vQuant1, p->vDriRefs, p->pPars->TimeTarget, + p->pPars->fBackward, p->pPars->fReorder, p->pPars->fVeryVerbose ); + if ( bNext == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bNext ); + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; +//Extra_bddPrintSupport( p->dd, bNext ); printf( "\n" ); + + // remap these states into the global manager +// bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pLoc2Glo ); Cudd_Ref( bNext ); +// Cudd_RecursiveDeref( p->dd, bTemp ); + +// bNext = Extra_TransferPermuteTime( p->dd, p->ddG, bTemp = bNext, pLoc2Glo, p->pPars->TimeTarget ); + bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pLoc2Glo ); + if ( bNext == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bNext ); + Cudd_RecursiveDeref( p->dd, bTemp ); + + nBddSize = Cudd_DagSize(bNext); + // check if there are any new states + if ( Cudd_bddLeq( p->ddG, bNext, bReached ) ) // implication = no new states + { + Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; + break; + } + + // get the new states + bCurrent = Cudd_bddAnd( p->ddG, bNext, Cudd_Not(bReached) ); + if ( bCurrent == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->ddG, bNext ); + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bCurrent ); + + // remap these states into the current state vars +// bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc ); Cudd_Ref( bCurrent ); +// Cudd_RecursiveDeref( p->ddG, bTemp ); + +// bCurrent = Extra_TransferPermuteTime( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc, p->pPars->TimeTarget ); + bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc ); + if ( bCurrent == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->ddG, bTemp ); + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + Cudd_Ref( bCurrent ); + Cudd_RecursiveDeref( p->ddG, bTemp ); + + // add to the reached states + bReached = Cudd_bddOr( p->ddG, bTemp = bReached, bNext ); Cudd_Ref( bReached ); + Cudd_RecursiveDeref( p->ddG, bTemp ); + Cudd_RecursiveDeref( p->ddG, bNext ); + bNext = NULL; + + if ( p->pPars->fVeryVerbose ) + { + double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); +// Extra_bddPrint( p->ddG, bReached );printf( "\n" ); + fprintf( stdout, " Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); + fflush( stdout ); + } + if ( p->pPars->fVerbose ) + { + fprintf( stdout, "F =%3d : ", nIters ); + fprintf( stdout, "Image =%6d ", nBddSize ); + fprintf( stdout, "(%4d%4d) ", + Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) ); + fprintf( stdout, "Reach =%6d ", Cudd_DagSize(bReached) ); + fprintf( stdout, "(%4d%4d) ", + Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk2 ); + } + + // check timeframe limit + if ( nIters == p->pPars->nIterMax - 1 ) + { + if ( !p->pPars->fSilent ) + printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nIterMax ); + p->pPars->iFrame = nIters; + Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; + Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; + return -1; + } + } + if ( bReached == NULL ) + { + p->pPars->iFrame = nIters - 1; + return 0; // reachable + } + if ( bCurrent ) + Cudd_RecursiveDeref( p->dd, bCurrent ); + // report the stats + if ( p->pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); + if ( nIters >= p->pPars->nIterMax ) + fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters ); + else + fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters ); + fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); + fflush( stdout ); + } + if ( p->pPars->fDumpReached ) + { + Llb_ManDumpReached( p->ddG, bReached, p->pAig->pName, "reached.blif" ); + printf( "Reached states with %d BDD nodes are dumpted into file \"reached.blif\".\n", Cudd_DagSize(bReached) ); + } + Cudd_RecursiveDeref( p->ddG, bReached ); + if ( nIters >= p->pPars->nIterMax ) + { + if ( !p->pPars->fSilent ) + { + printf( "Verified only for states reachable in %d frames. ", nIters ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + p->pPars->iFrame = p->pPars->nIterMax; + return -1; // undecided + } + if ( !p->pPars->fSilent ) + { + printf( "The miter is proved unreachable after %d iterations. ", nIters ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + p->pPars->iFrame = nIters - 1; + return 1; // unreachable +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_CoreReachability( Llb_Img_t * p ) +{ + Vec_Ptr_t * vSupps, * vQuant0, * vQuant1; + int RetValue; + // get supports and quantified variables + if ( p->pPars->fBackward ) + { + Vec_PtrReverseOrder( p->vDdMans ); + vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsNs, p->vVarsCs, 0, p->pPars->fVeryVerbose ); + } + else + vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsCs, p->vVarsNs, 0, p->pPars->fVeryVerbose ); + Llb_ImgSchedule( vSupps, &vQuant0, &vQuant1, p->pPars->fVeryVerbose ); + Vec_VecFree( (Vec_Vec_t *)vSupps ); + // remove variables + Llb_ImgQuantifyFirst( p->pAig, p->vDdMans, vQuant0, p->pPars->fVeryVerbose ); + // perform reachability + RetValue = Llb_CoreReachability_int( p, vQuant0, vQuant1 ); + Vec_VecFree( (Vec_Vec_t *)vQuant0 ); + Vec_VecFree( (Vec_Vec_t *)vQuant1 ); + return RetValue; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_CoreConstructAll( Aig_Man_t * p, Vec_Ptr_t * vResult, Vec_Int_t * vVarsNs, abctime TimeTarget ) +{ + DdManager * dd; + Vec_Ptr_t * vDdMans; + Vec_Ptr_t * vLower, * vUpper = NULL; + int i; + vDdMans = Vec_PtrStart( Vec_PtrSize(vResult) ); + Vec_PtrForEachEntryReverse( Vec_Ptr_t *, vResult, vLower, i ) + { + if ( i < Vec_PtrSize(vResult) - 1 ) + dd = Llb_ImgPartition( p, vLower, vUpper, TimeTarget ); + else + dd = Llb_DriverLastPartition( p, vVarsNs, TimeTarget ); + if ( dd == NULL ) + { + Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i ) + { + if ( dd == NULL ) + continue; + if ( dd->bFunc ) + Cudd_RecursiveDeref( dd, dd->bFunc ); + Extra_StopManager( dd ); + } + Vec_PtrFree( vDdMans ); + return NULL; + } + Vec_PtrWriteEntry( vDdMans, i, dd ); + vUpper = vLower; + } + return vDdMans; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_CoreSetVarMaps( Llb_Img_t * p ) +{ + Aig_Obj_t * pObj; + int i, iVarCs, iVarNs; + assert( p->vVarsCs != NULL ); + assert( p->vVarsNs != NULL ); + assert( p->vCs2Glo == NULL ); + assert( p->vNs2Glo == NULL ); + assert( p->vGlo2Cs == NULL ); + assert( p->vGlo2Ns == NULL ); + p->vCs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) ); + p->vNs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) ); + p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); + p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); + for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ ) + { + iVarCs = Vec_IntEntry( p->vVarsCs, i ); + iVarNs = Vec_IntEntry( p->vVarsNs, i ); + assert( iVarCs >= 0 && iVarCs < Aig_ManObjNumMax(p->pAig) ); + assert( iVarNs >= 0 && iVarNs < Aig_ManObjNumMax(p->pAig) ); + Vec_IntWriteEntry( p->vCs2Glo, iVarCs, i ); + Vec_IntWriteEntry( p->vNs2Glo, iVarNs, i ); + Vec_IntWriteEntry( p->vGlo2Cs, i, iVarCs ); + Vec_IntWriteEntry( p->vGlo2Ns, i, iVarNs ); + } + // add mapping of the PIs + Saig_ManForEachPi( p->pAig, pObj, i ) + Vec_IntWriteEntry( p->vCs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Img_t * Llb_CoreStart( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) +{ + Llb_Img_t * p; + p = ABC_CALLOC( Llb_Img_t, 1 ); + p->pInit = pInit; + p->pAig = pAig; + p->pPars = pPars; + p->dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + p->ddG = Cudd_Init( Aig_ManRegNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + p->ddR = Cudd_Init( Aig_ManCiNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); + Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT ); + Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT ); + p->vRings = Vec_PtrAlloc( 100 ); + p->vDriRefs = Llb_DriverCountRefs( pAig ); + p->vVarsCs = Llb_DriverCollectCs( pAig ); + p->vVarsNs = Llb_DriverCollectNs( pAig, p->vDriRefs ); + Llb_CoreSetVarMaps( p ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_CoreStop( Llb_Img_t * p ) +{ + DdManager * dd; + DdNode * bTemp; + int i; + if ( p->vDdMans ) + Vec_PtrForEachEntry( DdManager *, p->vDdMans, dd, i ) + { + if ( dd->bFunc ) + Cudd_RecursiveDeref( dd, dd->bFunc ); + if ( dd->bFunc2 ) + Cudd_RecursiveDeref( dd, dd->bFunc2 ); + Extra_StopManager( dd ); + } + Vec_PtrFreeP( &p->vDdMans ); + if ( p->ddR->bFunc ) + Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc ); + Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i ) + Cudd_RecursiveDeref( p->ddR, bTemp ); + Vec_PtrFree( p->vRings ); + Extra_StopManager( p->dd ); + Extra_StopManager( p->ddG ); + Extra_StopManager( p->ddR ); + Vec_IntFreeP( &p->vDriRefs ); + Vec_IntFreeP( &p->vVarsCs ); + Vec_IntFreeP( &p->vVarsNs ); + Vec_IntFreeP( &p->vCs2Glo ); + Vec_IntFreeP( &p->vNs2Glo ); + Vec_IntFreeP( &p->vGlo2Cs ); + Vec_IntFreeP( &p->vGlo2Ns ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_CoreExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, abctime TimeTarget ) +{ + int RetValue; + Llb_Img_t * p; +// printf( "\n" ); +// pPars->fVerbose = 1; + p = Llb_CoreStart( pInit, pAig, pPars ); + p->vDdMans = Llb_CoreConstructAll( pAig, vResult, p->vVarsNs, TimeTarget ); + if ( p->vDdMans == NULL ) + { + if ( !pPars->fSilent ) + printf( "Reached timeout (%d seconds) while deriving the partitions.\n", pPars->TimeLimit ); + Llb_CoreStop( p ); + return -1; + } + RetValue = Llb_CoreReachability( p ); + Llb_CoreStop( p ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManReachMinCut( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) +{ + extern Vec_Ptr_t * Llb_ManComputeCuts( Aig_Man_t * p, int Num, int fVerbose, int fVeryVerbose ); + Vec_Ptr_t * vResult; + Aig_Man_t * p; + int RetValue = -1; + abctime clk = Abc_Clock(); + + // compute time to stop + pPars->TimeTarget = pPars->TimeLimit ? pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0; + + p = Aig_ManDupFlopsOnly( pAig ); +//Aig_ManShow( p, 0, NULL ); + if ( pPars->fVerbose ) + Aig_ManPrintStats( pAig ); + if ( pPars->fVerbose ) + Aig_ManPrintStats( p ); + Aig_ManFanoutStart( p ); + + vResult = Llb_ManComputeCuts( p, pPars->nPartValue, pPars->fVerbose, pPars->fVeryVerbose ); + + if ( pPars->TimeLimit && Abc_Clock() > pPars->TimeTarget ) + { + if ( !pPars->fSilent ) + printf( "Reached timeout (%d seconds) after partitioning.\n", pPars->TimeLimit ); + + Vec_VecFree( (Vec_Vec_t *)vResult ); + Aig_ManFanoutStop( p ); + Aig_ManCleanMarkAB( p ); + Aig_ManStop( p ); + return RetValue; + } + + if ( !pPars->fSkipReach ) + RetValue = Llb_CoreExperiment( pAig, p, pPars, vResult, pPars->TimeTarget ); + + Vec_VecFree( (Vec_Vec_t *)vResult ); + Aig_ManFanoutStop( p ); + Aig_ManCleanMarkAB( p ); + Aig_ManStop( p ); + + if ( RetValue == -1 ) + Abc_PrintTime( 1, "Total runtime of the min-cut-based reachability engine", Abc_Clock() - clk ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb2Driver.c b/src/bdd/llb/llb2Driver.c new file mode 100644 index 00000000..1471f377 --- /dev/null +++ b/src/bdd/llb/llb2Driver.c @@ -0,0 +1,222 @@ +/**CFile**************************************************************** + + FileName [llb2Driver.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Procedures working with flop drivers.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Driver.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// driver issue:arises when creating +// - driver ref-counter array +// - Ns2Glo maps +// - final partition +// - change-phase cube + +// LI variable is used when +// - driver drives more than one LI +// - driver is a PI +// - driver is a constant + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the array of times each flop driver is referenced.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_DriverCountRefs( Aig_Man_t * p ) +{ + Vec_Int_t * vCounts; + Aig_Obj_t * pObj; + int i; + vCounts = Vec_IntStart( Aig_ManObjNumMax(p) ); + Saig_ManForEachLi( p, pObj, i ) + Vec_IntAddToEntry( vCounts, Aig_ObjFaninId0(pObj), 1 ); + return vCounts; +} + +/**Function************************************************************* + + Synopsis [Returns array of NS variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_DriverCollectNs( Aig_Man_t * pAig, Vec_Int_t * vDriRefs ) +{ + Vec_Int_t * vVars; + Aig_Obj_t * pObj, * pDri; + int i; + vVars = Vec_IntAlloc( Aig_ManRegNum(pAig) ); + Saig_ManForEachLi( pAig, pObj, i ) + { + pDri = Aig_ObjFanin0(pObj); + if ( Vec_IntEntry( vDriRefs, Aig_ObjId(pDri) ) != 1 || Saig_ObjIsPi(pAig, pDri) || Aig_ObjIsConst1(pDri) ) + Vec_IntPush( vVars, Aig_ObjId(pObj) ); + else + Vec_IntPush( vVars, Aig_ObjId(pDri) ); + } + return vVars; +} + +/**Function************************************************************* + + Synopsis [Returns array of CS variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_DriverCollectCs( Aig_Man_t * pAig ) +{ + Vec_Int_t * vVars; + Aig_Obj_t * pObj; + int i; + vVars = Vec_IntAlloc( Aig_ManRegNum(pAig) ); + Saig_ManForEachLo( pAig, pObj, i ) + Vec_IntPush( vVars, Aig_ObjId(pObj) ); + return vVars; +} + +/**Function************************************************************* + + Synopsis [Create cube for phase swapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_DriverPhaseCube( Aig_Man_t * pAig, Vec_Int_t * vDriRefs, DdManager * dd ) +{ + DdNode * bCube, * bVar, * bTemp; + Aig_Obj_t * pObj; + int i; + abctime TimeStop; + TimeStop = dd->TimeStop; dd->TimeStop = 0; + bCube = Cudd_ReadOne( dd ); Cudd_Ref( bCube ); + Saig_ManForEachLi( pAig, pObj, i ) + { + assert( Vec_IntEntry( vDriRefs, Aig_ObjFaninId0(pObj) ) >= 1 ); + if ( Vec_IntEntry( vDriRefs, Aig_ObjFaninId0(pObj) ) != 1 ) + continue; + if ( !Aig_ObjFaninC0(pObj) ) + continue; + bVar = Cudd_bddIthVar( dd, Aig_ObjFaninId0(pObj) ); + bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bCube ); + dd->TimeStop = TimeStop; + return bCube; +} + +/**Function************************************************************* + + Synopsis [Compute the last partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdManager * Llb_DriverLastPartition( Aig_Man_t * p, Vec_Int_t * vVarsNs, abctime TimeTarget ) +{ +// int fVerbose = 1; + DdManager * dd; + DdNode * bVar1, * bVar2, * bProd, * bRes, * bTemp; + Aig_Obj_t * pObj; + int i; + dd = Cudd_Init( Aig_ManObjNumMax(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + dd->TimeStop = TimeTarget; + bRes = Cudd_ReadOne(dd); Cudd_Ref( bRes ); + + // mark the duplicated flop inputs + Aig_ManForEachObjVec( vVarsNs, p, pObj, i ) + { + if ( !Saig_ObjIsLi(p, pObj) ) + continue; + bVar1 = Cudd_bddIthVar( dd, Aig_ObjId(pObj) ); + bVar2 = Cudd_bddIthVar( dd, Aig_ObjFaninId0(pObj) ); + if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) + bVar2 = Cudd_ReadOne(dd); + bVar2 = Cudd_NotCond( bVar2, Aig_ObjFaninC0(pObj) ); + bProd = Cudd_bddXnor( dd, bVar1, bVar2 ); Cudd_Ref( bProd ); +// bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); Cudd_Ref( bRes ); +// bRes = Extra_bddAndTime( dd, bTemp = bRes, bProd, TimeTarget ); + bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bProd ); + return NULL; + } + Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bProd ); + } + +/* + Saig_ManForEachLi( p, pObj, i ) + printf( "%d ", Aig_ObjId(pObj) ); + printf( "\n" ); + Saig_ManForEachLi( p, pObj, i ) + printf( "%c%d ", Aig_ObjFaninC0(pObj)? '-':'+', Aig_ObjFaninId0(pObj) ); + printf( "\n" ); +*/ + Cudd_AutodynDisable( dd ); +// Cudd_RecursiveDeref( dd, bRes ); +// Extra_StopManager( dd ); + dd->bFunc = bRes; + dd->TimeStop = 0; + return dd; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb2Dump.c b/src/bdd/llb/llb2Dump.c new file mode 100644 index 00000000..74f07922 --- /dev/null +++ b/src/bdd/llb/llb2Dump.c @@ -0,0 +1,104 @@ +/**CFile**************************************************************** + + FileName [llb2Dump.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Dumps the BDD of reached states into a file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Dump.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns a dummy name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Llb_ManGetDummyName( char * pPrefix, int Num, int nDigits ) +{ + static char Buffer[2000]; + sprintf( Buffer, "%s%0*d", pPrefix, nDigits, Num ); + return Buffer; +} + +/**Function************************************************************* + + Synopsis [Writes reached state BDD into a BLIF file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManDumpReached( DdManager * ddG, DdNode * bReached, char * pModel, char * pFileName ) +{ + FILE * pFile; + Vec_Ptr_t * vNamesIn, * vNamesOut; + char * pName; + int i, nDigits; + // reorder the BDD + Cudd_ReduceHeap( ddG, CUDD_REORDER_SYMM_SIFT, 1 ); + + // create input names + nDigits = Abc_Base10Log( Cudd_ReadSize(ddG) ); + vNamesIn = Vec_PtrAlloc( Cudd_ReadSize(ddG) ); + for ( i = 0; i < Cudd_ReadSize(ddG); i++ ) + { + pName = Llb_ManGetDummyName( "ff", i, nDigits ); + Vec_PtrPush( vNamesIn, Extra_UtilStrsav(pName) ); + } + // create output names + vNamesOut = Vec_PtrAlloc( 1 ); + Vec_PtrPush( vNamesOut, Extra_UtilStrsav("Reached") ); + + // write the file + pFile = fopen( pFileName, "wb" ); + Cudd_DumpBlif( ddG, 1, &bReached, (char **)Vec_PtrArray(vNamesIn), (char **)Vec_PtrArray(vNamesOut), pModel, pFile, 0 ); + fclose( pFile ); + + // cleanup + Vec_PtrForEachEntry( char *, vNamesIn, pName, i ) + ABC_FREE( pName ); + Vec_PtrForEachEntry( char *, vNamesOut, pName, i ) + ABC_FREE( pName ); + Vec_PtrFree( vNamesIn ); + Vec_PtrFree( vNamesOut ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb2Flow.c b/src/bdd/llb/llb2Flow.c new file mode 100644 index 00000000..64db32b3 --- /dev/null +++ b/src/bdd/llb/llb2Flow.c @@ -0,0 +1,1376 @@ +/**CFile**************************************************************** + + FileName [llb2Flow.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Flow computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Flow.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Llb_ObjSetPath( Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { pObj->pData = (void *)pNext; return 1; } +static inline Aig_Obj_t * Llb_ObjGetPath( Aig_Obj_t * pObj ) { return (Aig_Obj_t *)pObj->pData; } +static inline Aig_Obj_t * Llb_ObjGetFanoutPath( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pFanout; + int i, iFanout = -1; + assert( Llb_ObjGetPath(pObj) ); + Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) + if ( Llb_ObjGetPath(pFanout) == pObj ) + return pFanout; + return NULL; +} + +extern Vec_Ptr_t * Llb_ManCutSupp( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +/**Function************************************************************* + + Synopsis [For each cut, returns PIs that can be quantified.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManCutSupps( Aig_Man_t * p, Vec_Ptr_t * vResult ) +{ + Vec_Ptr_t * vSupps, * vOne, * vLower, * vUpper; + int i; + vSupps = Vec_PtrAlloc( 100 ); + Vec_PtrPush( vSupps, Vec_PtrAlloc(0) ); + vLower = (Vec_Ptr_t *)Vec_PtrEntry( vResult, 0 ); + Vec_PtrForEachEntryStart( Vec_Ptr_t *, vResult, vUpper, i, 1 ) + { + vOne = Llb_ManCutSupp( p, vLower, vUpper ); + Vec_PtrPush( vSupps, vOne ); + vLower = vUpper; + } + assert( Vec_PtrSize(vSupps) == Vec_PtrSize(vResult) ); + return vSupps; +} + +/**Function************************************************************* + + Synopsis [For each cut, returns PIs that can be quantified.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManCutMap( Aig_Man_t * p, Vec_Ptr_t * vResult, Vec_Ptr_t * vSupps ) +{ + int fShowMatrix = 1; + Vec_Ptr_t * vMaps, * vOne; + Vec_Int_t * vMap, * vPrev, * vNext; + Aig_Obj_t * pObj; + int * piFirst, * piLast; + int i, k, CounterPlus, CounterMinus, Counter; + + vMaps = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Vec_Ptr_t *, vResult, vOne, i ) + { + vMap = Vec_IntStart( Aig_ManObjNumMax(p) ); + Vec_PtrForEachEntry( Aig_Obj_t *, vOne, pObj, k ) + { + if ( !Saig_ObjIsPi(p, pObj) ) + Vec_IntWriteEntry( vMap, pObj->Id, 1 ); +// else +//printf( "*" ); +//printf( "%d ", pObj->Id ); + } + Vec_PtrPush( vMaps, vMap ); +//printf( "\n" ); + } + Vec_PtrPush( vMaps, Vec_IntStart( Aig_ManObjNumMax(p) ) ); + assert( Vec_PtrSize(vMaps) == Vec_PtrSize(vResult)+1 ); + + // collect the first and last PIs + piFirst = ABC_ALLOC( int, Saig_ManPiNum(p) ); + piLast = ABC_ALLOC( int, Saig_ManPiNum(p) ); + Saig_ManForEachPi( p, pObj, i ) + piFirst[i] = piLast[i] = -1; + Vec_PtrForEachEntry( Vec_Ptr_t *, vSupps, vOne, i ) + { + Vec_PtrForEachEntry( Aig_Obj_t *, vOne, pObj, k ) + { + if ( !Saig_ObjIsPi(p, pObj) ) + continue; + if ( piFirst[Aig_ObjCioId(pObj)] == -1 ) + piFirst[Aig_ObjCioId(pObj)] = i; + piLast[Aig_ObjCioId(pObj)] = i; + } + } + // PIs feeding into the flops should be extended to the last frame + Saig_ManForEachLi( p, pObj, i ) + { + if ( !Saig_ObjIsPi(p, Aig_ObjFanin0(pObj)) ) + continue; + piLast[Aig_ObjCioId(Aig_ObjFanin0(pObj))] = Vec_PtrSize(vMaps)-1; + } + + // set the PI map + Saig_ManForEachPi( p, pObj, i ) + { + if ( piFirst[i] == -1 ) + continue; + if ( piFirst[i] == piLast[i] ) + { + vMap = (Vec_Int_t *)Vec_PtrEntry( vMaps, piFirst[i] ); + Vec_IntWriteEntry( vMap, pObj->Id, 2 ); + continue; + } + + // set support for all in between + for ( k = piFirst[i]; k <= piLast[i]; k++ ) + { + vMap = (Vec_Int_t *)Vec_PtrEntry( vMaps, k ); + Vec_IntWriteEntry( vMap, pObj->Id, 1 ); + } + } + ABC_FREE( piFirst ); + ABC_FREE( piLast ); + + + // find all that will appear here + Counter = Aig_ManRegNum(p); + printf( "%d ", Counter ); + Vec_PtrForEachEntryStart( Vec_Int_t *, vMaps, vMap, i, 1 ) + { + vPrev = (Vec_Int_t *)Vec_PtrEntry( vMaps, i-1 ); + vNext = (i == Vec_PtrSize(vMaps)-1)? NULL: (Vec_Int_t *)Vec_PtrEntry( vMaps, i+1 ); + + CounterPlus = CounterMinus = 0; + Aig_ManForEachObj( p, pObj, k ) + { + if ( Saig_ObjIsPi(p, pObj) ) + { + if ( Vec_IntEntry(vPrev, k) == 0 && Vec_IntEntry(vMap, k) == 1 ) + CounterPlus++; + if ( Vec_IntEntry(vMap, k) == 1 && (vNext == NULL || Vec_IntEntry(vNext, k) == 0) ) + CounterMinus++; + } + else + { + if ( Vec_IntEntry(vPrev, k) == 0 && Vec_IntEntry(vMap, k) == 1 ) + CounterPlus++; + if ( Vec_IntEntry(vPrev, k) == 1 && Vec_IntEntry(vMap, k) == 0 ) + CounterMinus++; + } + } + Counter = Counter + CounterPlus - CounterMinus; + printf( "%d=%d ", i, Counter ); + } + printf( "\n" ); + + if ( !fShowMatrix ) + return vMaps; + Aig_ManForEachObj( p, pObj, i ) + { + if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) ) + continue; + Vec_PtrForEachEntry( Vec_Int_t *, vMaps, vMap, k ) + if ( Vec_IntEntry(vMap, i) ) + break; + if ( k == Vec_PtrSize(vMaps) ) + continue; + printf( "Obj = %4d : ", i ); + if ( Saig_ObjIsPi(p,pObj) ) + printf( "pi " ); + else if ( Saig_ObjIsLo(p,pObj) ) + printf( "lo " ); + else if ( Aig_ObjIsNode(pObj) ) + printf( "and " ); + + Vec_PtrForEachEntry( Vec_Int_t *, vMaps, vMap, k ) + printf( "%d", Vec_IntEntry(vMap, i) ); + printf( "\n" ); + } + return vMaps; +} + +/**Function************************************************************* + + Synopsis [Counts the number of PIs in the cut] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManCutPiNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) + if ( Saig_ObjIsPi(p,pObj) ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of LOs in the cut] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManCutLoNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) + if ( Saig_ObjIsLo(p,pObj) ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of LIs in the cut] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManCutLiNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) +{ + Aig_Obj_t * pFanout; + Aig_Obj_t * pObj; + int i, k, iFanout = -1, Counter = 0; + Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) + { + if ( Aig_ObjIsCi(pObj) ) + continue; + Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, k ) + { + if ( Saig_ObjIsLi(p, pFanout) ) + { + Counter++; + break; + } + } + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManCutVolume_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return 0; + Aig_ObjSetTravIdCurrent(p, pObj); + assert( Aig_ObjIsNode(pObj) ); + return 1 + Llb_ManCutVolume_rec(p, Aig_ObjFanin0(pObj)) + + Llb_ManCutVolume_rec(p, Aig_ObjFanin1(pObj)); +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManCutVolume( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + // mark the lower cut with the traversal ID + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // count the upper cut + Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) + Counter += Llb_ManCutVolume_rec( p, pObj ); + return Counter; +} + + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManCutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + assert( Aig_ObjIsNode(pObj) ); + Llb_ManCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); + Llb_ManCutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + // mark the lower cut with the traversal ID + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // count the upper cut + vNodes = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) + Llb_ManCutNodes_rec( p, pObj, vNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManCutSupp( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) +{ + Vec_Ptr_t * vNodes, * vSupp; + Aig_Obj_t * pObj; + int i; + vNodes = Llb_ManCutNodes( p, vLower, vUpper ); + // mark support of the nodes + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + assert( Aig_ObjIsNode(pObj) ); + Aig_ObjSetTravIdCurrent( p, Aig_ObjFanin0(pObj) ); + Aig_ObjSetTravIdCurrent( p, Aig_ObjFanin1(pObj) ); + } + Vec_PtrFree( vNodes ); + // collect the support nodes + vSupp = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + Vec_PtrPush( vSupp, pObj ); + return vSupp; + +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManCutRange( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) +{ + Vec_Ptr_t * vRange; + Aig_Obj_t * pObj; + int i; + // mark the lower cut with the traversal ID + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // collect the upper ones that are not marked + vRange = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) + if ( !Aig_ObjIsTravIdCurrent(p, pObj) ) + Vec_PtrPush( vRange, pObj ); + return vRange; +} + + + + +/**Function************************************************************* + + Synopsis [Prints the given cluster.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManCutPrint( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) +{ + Vec_Ptr_t * vSupp, * vRange; + int Pis, Ffs, And; + + Pis = Llb_ManCutPiNum(p, vLower); + Ffs = Llb_ManCutLoNum(p, vLower); + And = Vec_PtrSize(vLower) - Pis - Ffs; + printf( "Leaf: %3d=%3d+%3d+%3d ", Vec_PtrSize(vLower), Pis, Ffs, And ); + + Pis = Llb_ManCutPiNum(p, vUpper); + Ffs = Llb_ManCutLiNum(p, vUpper); + And = Vec_PtrSize(vUpper) - Pis - Ffs; + printf( "Root: %3d=%3d+%3d+%3d ", Vec_PtrSize(vUpper), Pis, Ffs, And ); + + vSupp = Llb_ManCutSupp( p, vLower, vUpper ); + Pis = Llb_ManCutPiNum(p, vSupp); + Ffs = Llb_ManCutLoNum(p, vSupp); + And = Vec_PtrSize(vSupp) - Pis - Ffs; + printf( "Supp: %3d=%3d+%3d+%3d ", Vec_PtrSize(vSupp), Pis, Ffs, And ); + + vRange = Llb_ManCutRange( p, vLower, vUpper ); + Pis = Llb_ManCutPiNum(p, vRange); + Ffs = Llb_ManCutLiNum(p, vRange); + And = Vec_PtrSize(vRange) - Pis - Ffs; + printf( "Range: %3d=%3d+%3d+%3d ", Vec_PtrSize(vRange), Pis, Ffs, And ); + + printf( "S =%3d. V =%3d.\n", + Vec_PtrSize(vSupp)+Vec_PtrSize(vRange), Llb_ManCutVolume(p, vLower, vUpper) ); + Vec_PtrFree( vSupp ); + Vec_PtrFree( vRange ); +/* + { + Aig_Obj_t * pObj; + int i; + printf( "Lower: " ); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + printf( " %d", pObj->Id ); + printf( " " ); + printf( "Upper: " ); + Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) + printf( " %d", pObj->Id ); + printf( "\n" ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Prints the given cluster.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManResultPrint( Aig_Man_t * p, Vec_Ptr_t * vResult ) +{ + Vec_Ptr_t * vLower, * vUpper = NULL; + int i; + Vec_PtrForEachEntryReverse( Vec_Ptr_t *, vResult, vLower, i ) + { + if ( i < Vec_PtrSize(vResult) - 1 ) + Llb_ManCutPrint( p, vLower, vUpper ); + vUpper = vLower; + } +} + +/**Function************************************************************* + + Synopsis [Tries to find an augmenting path originating in this node.] + + Description [This procedure works for directed graphs only!] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManFlowBwdPath2_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pFanout; + assert( Aig_ObjIsNode(pObj) || Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) ); + // skip visited nodes + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return 0; + Aig_ObjSetTravIdCurrent(p, pObj); + // process node without flow + if ( !Llb_ObjGetPath(pObj) ) + { + // start the path if we reached a terminal node + if ( pObj->fMarkA ) + return Llb_ObjSetPath( pObj, (Aig_Obj_t *)1 ); + // explore the fanins +// Abc_ObjForEachFanin( pObj, pFanin, i ) +// if ( Abc_NtkMaxFlowBwdPath2_rec(pFanin) ) +// return Abc_ObjSetPath( pObj, pFanin ); + if ( Aig_ObjIsNode(pObj) ) + { + if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ) ) + return Llb_ObjSetPath( pObj, Aig_ObjFanin0(pObj) ); + if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ) ) + return Llb_ObjSetPath( pObj, Aig_ObjFanin1(pObj) ); + } + return 0; + } + // pObj has flow - find the fanout with flow + pFanout = Llb_ObjGetFanoutPath( p, pObj ); + if ( pFanout == NULL ) + return 0; + // go through the fanins of the fanout with flow +// Abc_ObjForEachFanin( pFanout, pFanin, i ) +// if ( Abc_NtkMaxFlowBwdPath2_rec( pFanin ) ) +// return Abc_ObjSetPath( pFanout, pFanin ); + assert( Aig_ObjIsNode(pFanout) ); + if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pFanout) ) ) + return Llb_ObjSetPath( pFanout, Aig_ObjFanin0(pFanout) ); + if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pFanout) ) ) + return Llb_ObjSetPath( pFanout, Aig_ObjFanin1(pFanout) ); + // try the fanout + if ( Llb_ManFlowBwdPath2_rec( p, pFanout ) ) + return Llb_ObjSetPath( pFanout, NULL ); + return 0; +} + + +/**Function************************************************************* + + Synopsis [Cleans markB.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowLabelTfi_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) ) + return; + assert( Aig_ObjIsNode(pObj) ); + Llb_ManFlowLabelTfi_rec( p, Aig_ObjFanin0(pObj) ); + Llb_ManFlowLabelTfi_rec( p, Aig_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowUpdateCut( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) +{ + Aig_Obj_t * pObj; + int i; + // label the TFI of the cut nodes + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) + Llb_ManFlowLabelTfi_rec( p, pObj ); + // collect labeled fanins of non-labeled nodes + Vec_PtrClear( vMinCut ); + Aig_ManIncrementTravId(p); + Aig_ManForEachObj( p, pObj, i ) + { + if ( !Aig_ObjIsCo(pObj) && !Aig_ObjIsNode(pObj) ) + continue; + if ( Aig_ObjIsTravIdCurrent(p, pObj) || Aig_ObjIsTravIdPrevious(p, pObj) ) + continue; + if ( Aig_ObjIsTravIdPrevious(p, Aig_ObjFanin0(pObj)) ) + { + Aig_ObjSetTravIdCurrent(p, Aig_ObjFanin0(pObj)); + Vec_PtrPush( vMinCut, Aig_ObjFanin0(pObj) ); + } + if ( Aig_ObjIsNode(pObj) && Aig_ObjIsTravIdPrevious(p, Aig_ObjFanin1(pObj)) ) + { + Aig_ObjSetTravIdCurrent(p, Aig_ObjFanin1(pObj)); + Vec_PtrPush( vMinCut, Aig_ObjFanin1(pObj) ); + } + } +} + +/**Function************************************************************* + + Synopsis [Find minimum-volume minumum cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManFlowMinCut( Aig_Man_t * p ) +{ + Vec_Ptr_t * vMinCut; + Aig_Obj_t * pObj; + int i; + // collect the cut nodes + vMinCut = Vec_PtrAlloc( Aig_ManRegNum(p) ); + Aig_ManForEachObj( p, pObj, i ) + { + // node without flow is not a cut node + if ( !Llb_ObjGetPath(pObj) ) + continue; + // unvisited node is below the cut + if ( !Aig_ObjIsTravIdCurrent(p, pObj) ) + continue; + // add terminal with flow or node whose path is not visited + if ( pObj->fMarkA || !Aig_ObjIsTravIdCurrent( p, Llb_ObjGetPath(pObj) ) ) + Vec_PtrPush( vMinCut, pObj ); + } + return vMinCut; +} + +/**Function************************************************************* + + Synopsis [Verifies the min-cut is indeed a cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManFlowVerifyCut_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + // skip visited nodes + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return 1; + Aig_ObjSetTravIdCurrent(p, pObj); + // visit the node + if ( Aig_ObjIsConst1(pObj) ) + return 1; + if ( Aig_ObjIsCi(pObj) ) + return 0; + // explore the fanins + assert( Aig_ObjIsNode(pObj) ); + if ( !Llb_ManFlowVerifyCut_rec(p, Aig_ObjFanin0(pObj)) ) + return 0; + if ( !Llb_ManFlowVerifyCut_rec(p, Aig_ObjFanin1(pObj)) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Verifies the min-cut is indeed a cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_ManFlowVerifyCut( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) +{ + Aig_Obj_t * pObj; + int i; + // mark the cut with the current traversal ID + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // search from the latches for a path to the COs/CIs + Saig_ManForEachLi( p, pObj, i ) + { + if ( !Llb_ManFlowVerifyCut_rec( p, Aig_ObjFanin0(pObj) ) ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Implementation of max-flow/min-cut computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManFlow( Aig_Man_t * p, Vec_Ptr_t * vSources, int * pnFlow ) +{ + Vec_Ptr_t * vMinCut; + Aig_Obj_t * pObj; + int Flow, FlowCur, RetValue, i; + // find the max-flow + Flow = 0; + Aig_ManCleanData( p ); + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vSources, pObj, i ) + { + assert( !pObj->fMarkA && pObj->fMarkB ); + if ( !Aig_ObjFanin0(pObj)->fMarkB ) + { + FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ); + Flow += FlowCur; + if ( FlowCur ) + Aig_ManIncrementTravId(p); + } + if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB ) + { + FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ); + Flow += FlowCur; + if ( FlowCur ) + Aig_ManIncrementTravId(p); + } + } + if ( pnFlow ) + *pnFlow = Flow; + + // mark the nodes reachable from the latches + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vSources, pObj, i ) + { + assert( !pObj->fMarkA && pObj->fMarkB ); + if ( !Aig_ObjFanin0(pObj)->fMarkB ) + { + RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ); + assert( RetValue == 0 ); + } + if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB ) + { + RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ); + assert( RetValue == 0 ); + } + } + + // find the min-cut with the smallest volume + vMinCut = Llb_ManFlowMinCut( p ); + assert( Vec_PtrSize(vMinCut) == Flow ); + // verify the cut + if ( !Llb_ManFlowVerifyCut(p, vMinCut) ) + printf( "Llb_ManFlow() error! The computed min-cut is not a cut!\n" ); +// Llb_ManFlowPrintCut( p, vMinCut ); + return vMinCut; +} + +/**Function************************************************************* + + Synopsis [Implementation of max-flow/min-cut computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManFlowCompute( Aig_Man_t * p ) +{ + Vec_Ptr_t * vMinCut; + Aig_Obj_t * pObj; + int Flow, FlowCur, RetValue, i; + // find the max-flow + Flow = 0; + Aig_ManCleanData( p ); + Aig_ManIncrementTravId(p); + Aig_ManForEachObj( p, pObj, i ) + { + if ( !pObj->fMarkB ) + continue; + assert( !pObj->fMarkA ); + if ( !Aig_ObjFanin0(pObj)->fMarkB ) + { +//printf( "%d ", Aig_ObjFanin0(pObj)->Id ); + FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ); + Flow += FlowCur; + if ( FlowCur ) + Aig_ManIncrementTravId(p); + } + if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB ) + { +//printf( "%d ", Aig_ObjFanin1(pObj)->Id ); + FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ); + Flow += FlowCur; + if ( FlowCur ) + Aig_ManIncrementTravId(p); + } + } +//printf( "\n" ); + + // mark the nodes reachable from the latches + Aig_ManIncrementTravId(p); + Aig_ManForEachObj( p, pObj, i ) + { + if ( !pObj->fMarkB ) + continue; + assert( !pObj->fMarkA ); + if ( !Aig_ObjFanin0(pObj)->fMarkB ) + { + RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ); + assert( RetValue == 0 ); + } + if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB ) + { + RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ); + assert( RetValue == 0 ); + } + } + // find the min-cut with the smallest volume + vMinCut = Llb_ManFlowMinCut( p ); + assert( Vec_PtrSize(vMinCut) == Flow ); +//printf( "%d ", Vec_PtrSize(vMinCut) ); + Llb_ManFlowUpdateCut( p, vMinCut ); +//printf( "%d ", Vec_PtrSize(vMinCut) ); + // verify the cut + if ( !Llb_ManFlowVerifyCut(p, vMinCut) ) + printf( "Llb_ManFlow() error! The computed min-cut is not a cut!\n" ); +// Llb_ManFlowPrintCut( p, vMinCut ); + return vMinCut; +} + + + + +/**Function************************************************************* + + Synopsis [Cleans markB.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowCleanMarkB_rec( Aig_Obj_t * pObj ) +{ + if ( pObj->fMarkB == 0 ) + return; + pObj->fMarkB = 0; + assert( Aig_ObjIsNode(pObj) ); + Llb_ManFlowCleanMarkB_rec( Aig_ObjFanin0(pObj) ); + Llb_ManFlowCleanMarkB_rec( Aig_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Cleans markB.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowSetMarkA_rec( Aig_Obj_t * pObj ) +{ + if ( pObj->fMarkA ) + return; + pObj->fMarkA = 1; + if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) ) + return; + assert( Aig_ObjIsNode(pObj) ); + Llb_ManFlowSetMarkA_rec( Aig_ObjFanin0(pObj) ); + Llb_ManFlowSetMarkA_rec( Aig_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Prepares flow computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowPrepareCut( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) +{ + Aig_Obj_t * pObj; + int i; + // reset marks + Aig_ManForEachObj( p, pObj, i ) + { + pObj->fMarkA = 0; + pObj->fMarkB = 1; + } + // clean PIs and const + Aig_ManConst1(p)->fMarkB = 0; + Aig_ManForEachCi( p, pObj, i ) + pObj->fMarkB = 0; + // clean upper cut +//printf( "Upper: "); + Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) + { + Llb_ManFlowCleanMarkB_rec( pObj ); +//printf( "%d ", pObj->Id ); + } +//printf( "\n" ); + // set lower cut +//printf( "Lower: "); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + { +//printf( "%d ", pObj->Id ); + assert( pObj->fMarkB == 0 ); + Llb_ManFlowSetMarkA_rec( pObj ); + } +//printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Prepares flow computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowUnmarkCone( Aig_Man_t * p, Vec_Ptr_t * vCone ) +{ + Aig_Obj_t * pObj; + int i; + Vec_PtrForEachEntry( Aig_Obj_t *, vCone, pObj, i ) + { + assert( Aig_ObjIsNode(pObj) ); + assert( pObj->fMarkB == 1 ); + pObj->fMarkB = 0; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowCollectAndMarkCone_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vCone ) +{ + Aig_Obj_t * pFanout; + int i, iFanout = -1; + if ( Saig_ObjIsLi(p, pObj) ) + return; + if ( pObj->fMarkB ) + return; + if ( pObj->fMarkA == 0 ) + { + assert( Aig_ObjIsNode(pObj) ); + pObj->fMarkB = 1; + if ( Aig_ObjIsNode(pObj) ) + Vec_PtrPush( vCone, pObj ); + } + Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) + Llb_ManFlowCollectAndMarkCone_rec( p, pFanout, vCone ); +} + +/**Function************************************************************* + + Synopsis [Collects the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowCollectAndMarkCone( Aig_Man_t * p, Vec_Ptr_t * vStarts, Vec_Ptr_t * vCone ) +{ + Aig_Obj_t * pObj; + int i; + Vec_PtrClear( vCone ); + Vec_PtrForEachEntry( Aig_Obj_t *, vStarts, pObj, i ) + { + assert( pObj->fMarkA && !pObj->fMarkB ); + Llb_ManFlowCollectAndMarkCone_rec( p, pObj, vCone ); + } +} + + + + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManComputeCutLo( Aig_Man_t * p ) +{ + Vec_Ptr_t * vMinCut; + Aig_Obj_t * pObj; + int i; + vMinCut = Vec_PtrAlloc( 100 ); + Aig_ManForEachCi( p, pObj, i ) + Vec_PtrPush( vMinCut, pObj ); + return vMinCut; +} + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManComputeCutLi( Aig_Man_t * p ) +{ + Vec_Ptr_t * vMinCut; + Aig_Obj_t * pObj; + int i; + assert( Saig_ManPoNum(p) == 0 ); + vMinCut = Vec_PtrAlloc( 100 ); + Aig_ManIncrementTravId(p); + Saig_ManForEachLi( p, pObj, i ) + { + pObj = Aig_ObjFanin0(pObj); + if ( Aig_ObjIsConst1(pObj) ) + continue; + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + continue; + Aig_ObjSetTravIdCurrent(p, pObj); + Vec_PtrPush( vMinCut, pObj ); + } + return vMinCut; +} + + + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManFlowGetObjSet( Aig_Man_t * p, Vec_Ptr_t * vLower, int iStart, int nSize, Vec_Ptr_t * vSet ) +{ + Aig_Obj_t * pObj; + int i; + Vec_PtrClear( vSet ); + for ( i = 0; i < nSize; i++ ) + { + pObj = (Aig_Obj_t *)Vec_PtrEntry( vLower, (iStart + i) % Vec_PtrSize(vLower) ); + Vec_PtrPush( vSet, pObj ); + } +} + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManFlowFindBestCut( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, int Num ) +{ + int nVolMin = Aig_ManNodeNum(p) / Num / 2; + Vec_Ptr_t * vMinCut; + Vec_Ptr_t * vCone, * vSet; + Aig_Obj_t * pObj; + int i, s, Vol, VolLower, VolUpper, VolCmp; + int iBest = -1, iMinCut = ABC_INFINITY, iVolBest = 0; + + Vol = Llb_ManCutVolume( p, vLower, vUpper ); + assert( Vol > nVolMin ); + VolCmp = Abc_MinInt( nVolMin, Vol - nVolMin ); + vCone = Vec_PtrAlloc( 100 ); + vSet = Vec_PtrAlloc( 100 ); + Llb_ManFlowPrepareCut( p, vLower, vUpper ); + for ( s = 1; s < Aig_ManRegNum(p); s += 5 ) + { + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + { + Llb_ManFlowGetObjSet( p, vLower, i, s, vSet ); + Llb_ManFlowCollectAndMarkCone( p, vSet, vCone ); + if ( Vec_PtrSize(vCone) == 0 ) + continue; + vMinCut = Llb_ManFlowCompute( p ); + Llb_ManFlowUnmarkCone( p, vCone ); + + VolLower = Llb_ManCutVolume( p, vLower, vMinCut ); + VolUpper = Llb_ManCutVolume( p, vMinCut, vUpper ); + Vol = Abc_MinInt( VolLower, VolUpper ); + if ( Vol >= VolCmp && (iMinCut == -1 || + iMinCut > Vec_PtrSize(vMinCut) || + (iMinCut == Vec_PtrSize(vMinCut) && iVolBest < Vol)) ) + { + iBest = i; + iMinCut = Vec_PtrSize(vMinCut); + iVolBest = Vol; + } + Vec_PtrFree( vMinCut ); + } + if ( iBest >= 0 ) + break; + } + if ( iBest == -1 ) + { + // cleanup + Vec_PtrFree( vCone ); + Vec_PtrFree( vSet ); + return NULL; + } + // get the best cut + assert( iBest >= 0 ); + Llb_ManFlowGetObjSet( p, vLower, iBest, s, vSet ); + Llb_ManFlowCollectAndMarkCone( p, vSet, vCone ); + vMinCut = Llb_ManFlowCompute( p ); + Llb_ManFlowUnmarkCone( p, vCone ); + // cleanup + Vec_PtrFree( vCone ); + Vec_PtrFree( vSet ); + return vMinCut; +} + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ManComputeCuts( Aig_Man_t * p, int Num, int fVerbose, int fVeryVerbose ) +{ + int nVolMax = Aig_ManNodeNum(p) / Num; + Vec_Ptr_t * vResult, * vMinCut = NULL, * vLower, * vUpper; + int i, k, nVol; + abctime clk = Abc_Clock(); + vResult = Vec_PtrAlloc( 100 ); + Vec_PtrPush( vResult, Llb_ManComputeCutLo(p) ); + Vec_PtrPush( vResult, Llb_ManComputeCutLi(p) ); + while ( 1 ) + { + // find a place to insert new cut + vLower = (Vec_Ptr_t *)Vec_PtrEntry( vResult, 0 ); + Vec_PtrForEachEntryStart( Vec_Ptr_t *, vResult, vUpper, i, 1 ) + { + nVol = Llb_ManCutVolume( p, vLower, vUpper ); + if ( nVol <= nVolMax ) + { + vLower = vUpper; + continue; + } + + if ( fVeryVerbose ) + Llb_ManCutPrint( p, vLower, vUpper ); + vMinCut = Llb_ManFlowFindBestCut( p, vLower, vUpper, Num ); + if ( vMinCut == NULL ) + { + if ( fVeryVerbose ) + printf( "Could not break the cut.\n" ); + if ( fVeryVerbose ) + printf( "\n" ); + vLower = vUpper; + continue; + } + + if ( fVeryVerbose ) + Llb_ManCutPrint( p, vMinCut, vUpper ); + if ( fVeryVerbose ) + Llb_ManCutPrint( p, vLower, vMinCut ); + if ( fVeryVerbose ) + printf( "\n" ); + + break; + } + if ( i == Vec_PtrSize(vResult) ) + break; + // insert vMinCut before vUpper + Vec_PtrPush( vResult, NULL ); + for ( k = Vec_PtrSize(vResult) - 1; k > i; k-- ) + Vec_PtrWriteEntry( vResult, k, Vec_PtrEntry(vResult, k-1) ); + Vec_PtrWriteEntry( vResult, i, vMinCut ); + } + if ( fVerbose ) + { + printf( "Finished computing %d partitions. ", Vec_PtrSize(vResult) - 1 ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + Llb_ManResultPrint( p, vResult ); + } + return vResult; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_BddSetDefaultParams( Gia_ParLlb_t * p ) +{ + memset( p, 0, sizeof(Gia_ParLlb_t) ); + p->nBddMax = 1000000; + p->nIterMax = 10000000; + p->nClusterMax = 20; + p->nHintDepth = 0; + p->HintFirst = 0; + p->fUseFlow = 0; // use flow + p->nVolumeMax = 100; // max volume + p->nVolumeMin = 30; // min volume + p->fReorder = 1; + p->fIndConstr = 0; + p->fUsePivots = 0; + p->fCluster = 0; + p->fSchedule = 0; + p->fVerbose = 0; + p->fVeryVerbose = 0; + p->fSilent = 0; + p->TimeLimit = 0; +// p->TimeLimit = 0; + p->TimeLimitGlo = 0; + p->TimeTarget = 0; + p->iFrame = -1; +} + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ManMinCutTest( Aig_Man_t * pAig, int Num ) +{ + extern void Llb_BddConstructTest( Aig_Man_t * p, Vec_Ptr_t * vResult ); + extern void Llb_BddExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, Vec_Ptr_t * vMaps ); + + +// int fVerbose = 1; + Gia_ParLlb_t Pars, * pPars = &Pars; + Vec_Ptr_t * vResult;//, * vSupps, * vMaps; + Aig_Man_t * p; + + Llb_BddSetDefaultParams( pPars ); + + p = Aig_ManDupFlopsOnly( pAig ); +//Aig_ManShow( p, 0, NULL ); + Aig_ManPrintStats( pAig ); + Aig_ManPrintStats( p ); + Aig_ManFanoutStart( p ); + + vResult = Llb_ManComputeCuts( p, Num, 1, 0 ); +// vSupps = Llb_ManCutSupps( p, vResult ); +// vMaps = Llb_ManCutMap( p, vResult, vSupps ); + +// Llb_BddExperiment( pAig, p, pPars, vResult, vMaps ); + Llb_CoreExperiment( pAig, p, pPars, vResult, 0 ); + +// Vec_VecFree( (Vec_Vec_t *)vMaps ); +// Vec_VecFree( (Vec_Vec_t *)vSupps ); + Vec_VecFree( (Vec_Vec_t *)vResult ); + + Aig_ManFanoutStop( p ); + Aig_ManCleanMarkAB( p ); + Aig_ManStop( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb2Image.c b/src/bdd/llb/llb2Image.c new file mode 100644 index 00000000..e245ba36 --- /dev/null +++ b/src/bdd/llb/llb2Image.c @@ -0,0 +1,482 @@ +/**CFile**************************************************************** + + FileName [llb2Image.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Computes image using partitioned structure.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern Vec_Ptr_t * Llb_ManCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ); +extern Vec_Ptr_t * Llb_ManCutRange( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes supports of the partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_ImgSupports( Aig_Man_t * p, Vec_Ptr_t * vDdMans, Vec_Int_t * vStart, Vec_Int_t * vStop, int fAddPis, int fVerbose ) +{ + Vec_Ptr_t * vSupps; + Vec_Int_t * vOne; + Aig_Obj_t * pObj; + DdManager * dd; + DdNode * bSupp, * bTemp; + int i, Entry, nSize; + nSize = Cudd_ReadSize( (DdManager *)Vec_PtrEntry( vDdMans, 0 ) ); + vSupps = Vec_PtrAlloc( 100 ); + // create initial + vOne = Vec_IntStart( nSize ); + Vec_IntForEachEntry( vStart, Entry, i ) + Vec_IntWriteEntry( vOne, Entry, 1 ); + Vec_PtrPush( vSupps, vOne ); + // create intermediate + Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i ) + { + vOne = Vec_IntStart( nSize ); + bSupp = Cudd_Support( dd, dd->bFunc ); Cudd_Ref( bSupp ); + for ( bTemp = bSupp; bTemp != Cudd_ReadOne(dd); bTemp = cuddT(bTemp) ) + Vec_IntWriteEntry( vOne, bTemp->index, 1 ); + Cudd_RecursiveDeref( dd, bSupp ); + Vec_PtrPush( vSupps, vOne ); + } + // create final + vOne = Vec_IntStart( nSize ); + Vec_IntForEachEntry( vStop, Entry, i ) + Vec_IntWriteEntry( vOne, Entry, 1 ); + if ( fAddPis ) + Saig_ManForEachPi( p, pObj, i ) + Vec_IntWriteEntry( vOne, Aig_ObjId(pObj), 1 ); + Vec_PtrPush( vSupps, vOne ); + + // print supports + assert( nSize == Aig_ManObjNumMax(p) ); + if ( !fVerbose ) + return vSupps; + Aig_ManForEachObj( p, pObj, i ) + { + int k, Counter = 0; + Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k ) + Counter += Vec_IntEntry(vOne, i); + if ( Counter == 0 ) + continue; + printf( "Obj = %4d : ", i ); + if ( Saig_ObjIsPi(p,pObj) ) + printf( "pi " ); + else if ( Saig_ObjIsLo(p,pObj) ) + printf( "lo " ); + else if ( Saig_ObjIsLi(p,pObj) ) + printf( "li " ); + else if ( Aig_ObjIsNode(pObj) ) + printf( "and " ); + Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k ) + printf( "%d", Vec_IntEntry(vOne, i) ); + printf( "\n" ); + } + return vSupps; +} + +/**Function************************************************************* + + Synopsis [Computes quantification schedule.] + + Description [Input array contains supports: 0=starting, ... intermediate... + N-1=final. Output arrays contain immediately quantifiable vars (vQuant0) + and vars that should be quantified after conjunction (vQuant1).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ImgSchedule( Vec_Ptr_t * vSupps, Vec_Ptr_t ** pvQuant0, Vec_Ptr_t ** pvQuant1, int fVerbose ) +{ + Vec_Int_t * vOne; + int nVarsAll, Counter, iSupp = -1, Entry, i, k; + // start quantification arrays + *pvQuant0 = Vec_PtrAlloc( Vec_PtrSize(vSupps) ); + *pvQuant1 = Vec_PtrAlloc( Vec_PtrSize(vSupps) ); + Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k ) + { + Vec_PtrPush( *pvQuant0, Vec_IntAlloc(16) ); + Vec_PtrPush( *pvQuant1, Vec_IntAlloc(16) ); + } + // count how many times each var appears + nVarsAll = Vec_IntSize( (Vec_Int_t *)Vec_PtrEntry(vSupps, 0) ); + for ( i = 0; i < nVarsAll; i++ ) + { + Counter = 0; + Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k ) + if ( Vec_IntEntry(vOne, i) ) + { + iSupp = k; + Counter++; + } + if ( Counter == 0 ) + continue; + if ( Counter == 1 ) + Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(*pvQuant0, iSupp), i ); + else // if ( Counter > 1 ) + Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(*pvQuant1, iSupp), i ); + } + + if ( fVerbose ) + for ( i = 0; i < Vec_PtrSize(vSupps); i++ ) + { + printf( "%2d : Quant0 = ", i ); + Vec_IntForEachEntry( (Vec_Int_t *)Vec_PtrEntry(*pvQuant0, i), Entry, k ) + printf( "%d ", Entry ); + printf( "\n" ); + } + + if ( fVerbose ) + for ( i = 0; i < Vec_PtrSize(vSupps); i++ ) + { + printf( "%2d : Quant1 = ", i ); + Vec_IntForEachEntry( (Vec_Int_t *)Vec_PtrEntry(*pvQuant1, i), Entry, k ) + printf( "%d ", Entry ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Computes one partition in a separate BDD manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdManager * Llb_ImgPartition( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, abctime TimeTarget ) +{ + Vec_Ptr_t * vNodes, * vRange; + Aig_Obj_t * pObj; + DdManager * dd; + DdNode * bBdd0, * bBdd1, * bProd, * bRes, * bTemp; + int i; + + dd = Cudd_Init( Aig_ManObjNumMax(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + dd->TimeStop = TimeTarget; + + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + pObj->pData = Cudd_bddIthVar( dd, Aig_ObjId(pObj) ); + + vNodes = Llb_ManCutNodes( p, vLower, vUpper ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); +// pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData ); +// pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeTarget ); + pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); + if ( pObj->pData == NULL ) + { + Cudd_Quit( dd ); + Vec_PtrFree( vNodes ); + return NULL; + } + Cudd_Ref( (DdNode *)pObj->pData ); + } + + vRange = Llb_ManCutRange( p, vLower, vUpper ); + bRes = Cudd_ReadOne(dd); Cudd_Ref( bRes ); + Vec_PtrForEachEntry( Aig_Obj_t *, vRange, pObj, i ) + { + assert( Aig_ObjIsNode(pObj) ); + bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), (DdNode *)pObj->pData ); Cudd_Ref( bProd ); +// bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); Cudd_Ref( bRes ); +// bRes = Extra_bddAndTime( dd, bTemp = bRes, bProd, TimeTarget ); + bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); + if ( bRes == NULL ) + { + Cudd_Quit( dd ); + Vec_PtrFree( vRange ); + Vec_PtrFree( vNodes ); + return NULL; + } + Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bProd ); + } + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + + Vec_PtrFree( vRange ); + Vec_PtrFree( vNodes ); + Cudd_AutodynDisable( dd ); +// Cudd_RecursiveDeref( dd, bRes ); +// Extra_StopManager( dd ); + dd->bFunc = bRes; + dd->TimeStop = 0; + return dd; +} + +/**Function************************************************************* + + Synopsis [Derives positive cube composed of nodes IDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ImgComputeCube( Aig_Man_t * pAig, Vec_Int_t * vNodeIds, DdManager * dd ) +{ + DdNode * bProd, * bTemp; + Aig_Obj_t * pObj; + int i; + abctime TimeStop; + TimeStop = dd->TimeStop; dd->TimeStop = 0; + bProd = Cudd_ReadOne(dd); Cudd_Ref( bProd ); + Aig_ManForEachObjVec( vNodeIds, pAig, pObj, i ) + { + bProd = Cudd_bddAnd( dd, bTemp = bProd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)) ); Cudd_Ref( bProd ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bProd ); + dd->TimeStop = TimeStop; + return bProd; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ImgQuantifyFirst( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, Vec_Ptr_t * vQuant0, int fVerbose ) +{ + DdManager * dd; + DdNode * bProd, * bRes, * bTemp; + int i; + abctime clk = Abc_Clock(); + Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i ) + { + // remember unquantified ones + assert( dd->bFunc2 == NULL ); + dd->bFunc2 = dd->bFunc; Cudd_Ref( dd->bFunc2 ); + + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + + bRes = dd->bFunc; + if ( fVerbose ) + Abc_Print( 1, "Part %2d : Init =%5d. ", i, Cudd_DagSize(bRes) ); + bProd = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, i+1), dd ); Cudd_Ref( bProd ); + bRes = Cudd_bddExistAbstract( dd, bTemp = bRes, bProd ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bProd ); + dd->bFunc = bRes; + + Cudd_AutodynDisable( dd ); + + if ( fVerbose ) + Abc_Print( 1, "Quant =%5d. ", Cudd_DagSize(bRes) ); + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + if ( fVerbose ) + Abc_Print( 1, "Reo = %5d. ", Cudd_DagSize(bRes) ); + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + if ( fVerbose ) + Abc_Print( 1, "Reo = %5d. ", Cudd_DagSize(bRes) ); + if ( fVerbose ) + Abc_Print( 1, "Supp = %3d. ", Cudd_SupportSize(dd, bRes) ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_ImgQuantifyReset( Vec_Ptr_t * vDdMans ) +{ + DdManager * dd; + int i; + Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i ) + { + assert( dd->bFunc2 != NULL ); + Cudd_RecursiveDeref( dd, dd->bFunc ); + dd->bFunc = dd->bFunc2; + dd->bFunc2 = NULL; + } +} + +/**Function************************************************************* + + Synopsis [Computes image of the initial set of states.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_ImgComputeImage( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, DdManager * dd, DdNode * bInit, + Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1, Vec_Int_t * vDriRefs, + abctime TimeTarget, int fBackward, int fReorder, int fVerbose ) +{ +// int fCheckSupport = 0; + DdManager * ddPart; + DdNode * bImage, * bGroup, * bCube, * bTemp; + int i; + abctime clk, clk0 = Abc_Clock(); + + bImage = bInit; Cudd_Ref( bImage ); + if ( fBackward ) + { + // change polarity + bCube = Llb_DriverPhaseCube( pAig, vDriRefs, dd ); Cudd_Ref( bCube ); + bImage = Extra_bddChangePolarity( dd, bTemp = bImage, bCube ); Cudd_Ref( bImage ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + } + else + { + // quantify unique vriables + bCube = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, 0), dd ); Cudd_Ref( bCube ); + bImage = Cudd_bddExistAbstract( dd, bTemp = bImage, bCube ); + if ( bImage == NULL ) + { + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + return NULL; + } + Cudd_Ref( bImage ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + } + // perform image computation + Vec_PtrForEachEntry( DdManager *, vDdMans, ddPart, i ) + { + clk = Abc_Clock(); +if ( fVerbose ) +printf( " %2d : ", i ); + // transfer the BDD from the group manager to the main manager + bGroup = Cudd_bddTransfer( ddPart, dd, ddPart->bFunc ); + if ( bGroup == NULL ) + return NULL; + Cudd_Ref( bGroup ); +if ( fVerbose ) +printf( "Pt0 =%6d. Pt1 =%6d. ", Cudd_DagSize(ddPart->bFunc), Cudd_DagSize(bGroup) ); + // perform partial product + bCube = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant1, i+1), dd ); Cudd_Ref( bCube ); +// bImage = Cudd_bddAndAbstract( dd, bTemp = bImage, bGroup, bCube ); +// bImage = Extra_bddAndAbstractTime( dd, bTemp = bImage, bGroup, bCube, TimeTarget ); + bImage = Cudd_bddAndAbstract( dd, bTemp = bImage, bGroup, bCube ); + if ( bImage == NULL ) + { + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + Cudd_RecursiveDeref( dd, bGroup ); + return NULL; + } + Cudd_Ref( bImage ); + +if ( fVerbose ) +printf( "Im0 =%6d. Im1 =%6d. ", Cudd_DagSize(bTemp), Cudd_DagSize(bImage) ); +//printf("\n"); Extra_bddPrintSupport(dd, bImage); printf("\n"); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + Cudd_RecursiveDeref( dd, bGroup ); + +// Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); +// Abc_Print( 1, "Reo =%6d. ", Cudd_DagSize(bImage) ); + +if ( fVerbose ) +printf( "Supp =%3d. ", Cudd_SupportSize(dd, bImage) ); +if ( fVerbose ) +Abc_PrintTime( 1, "T", Abc_Clock() - clk ); + } + + if ( !fBackward ) + { + // change polarity + bCube = Llb_DriverPhaseCube( pAig, vDriRefs, dd ); Cudd_Ref( bCube ); + bImage = Extra_bddChangePolarity( dd, bTemp = bImage, bCube ); Cudd_Ref( bImage ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + } + else + { + // quantify unique vriables + bCube = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, 0), dd ); Cudd_Ref( bCube ); + bImage = Cudd_bddExistAbstract( dd, bTemp = bImage, bCube ); Cudd_Ref( bImage ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + } + + if ( fReorder ) + { + if ( fVerbose ) + Abc_Print( 1, " Reordering... Before =%5d. ", Cudd_DagSize(bImage) ); + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + if ( fVerbose ) + Abc_Print( 1, "After =%5d. ", Cudd_DagSize(bImage) ); +// Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); +// Abc_Print( 1, "After =%5d. ", Cudd_DagSize(bImage) ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk0 ); +// Abc_Print( 1, "\n" ); + } + + Cudd_Deref( bImage ); + return bImage; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb3Image.c b/src/bdd/llb/llb3Image.c new file mode 100644 index 00000000..72c6120a --- /dev/null +++ b/src/bdd/llb/llb3Image.c @@ -0,0 +1,1095 @@ +/**CFile**************************************************************** + + FileName [llb3Image.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Computes image using partitioned structure.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb3Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Llb_Var_t_ Llb_Var_t; +struct Llb_Var_t_ +{ + int iVar; // variable number + int nScore; // variable score + Vec_Int_t * vParts; // partitions +}; + +typedef struct Llb_Prt_t_ Llb_Prt_t; +struct Llb_Prt_t_ +{ + int iPart; // partition number + int nSize; // the number of BDD nodes + DdNode * bFunc; // the partition + Vec_Int_t * vVars; // support +}; + +typedef struct Llb_Mgr_t_ Llb_Mgr_t; +struct Llb_Mgr_t_ +{ + Aig_Man_t * pAig; // AIG manager + Vec_Ptr_t * vLeaves; // leaves in the AIG manager + Vec_Ptr_t * vRoots; // roots in the AIG manager + DdManager * dd; // working BDD manager + int * pVars2Q; // variables to quantify + // internal + Llb_Prt_t ** pParts; // partitions + Llb_Var_t ** pVars; // variables + int iPartFree; // next free partition + int nVars; // the number of BDD variables + int nSuppMax; // maximum support size + // temporary + int * pSupp; // temporary support storage +}; + +static inline Llb_Var_t * Llb_MgrVar( Llb_Mgr_t * p, int i ) { return p->pVars[i]; } +static inline Llb_Prt_t * Llb_MgrPart( Llb_Mgr_t * p, int i ) { return p->pParts[i]; } + +// iterator over vars +#define Llb_MgrForEachVar( p, pVar, i ) \ + for ( i = 0; (i < p->nVars) && (((pVar) = Llb_MgrVar(p, i)), 1); i++ ) if ( pVar == NULL ) {} else +// iterator over parts +#define Llb_MgrForEachPart( p, pPart, i ) \ + for ( i = 0; (i < p->iPartFree) && (((pPart) = Llb_MgrPart(p, i)), 1); i++ ) if ( pPart == NULL ) {} else + +// iterator over vars of one partition +#define Llb_PartForEachVar( p, pPart, pVar, i ) \ + for ( i = 0; (i < Vec_IntSize(pPart->vVars)) && (((pVar) = Llb_MgrVar(p, Vec_IntEntry(pPart->vVars,i))), 1); i++ ) +// iterator over parts of one variable +#define Llb_VarForEachPart( p, pVar, pPart, i ) \ + for ( i = 0; (i < Vec_IntSize(pVar->vParts)) && (((pPart) = Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,i))), 1); i++ ) + +// statistics +abctime timeBuild, timeAndEx, timeOther; +int nSuppMax; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Removes one variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinRemoveVar( Llb_Mgr_t * p, Llb_Var_t * pVar ) +{ + assert( p->pVars[pVar->iVar] == pVar ); + p->pVars[pVar->iVar] = NULL; + Vec_IntFree( pVar->vParts ); + ABC_FREE( pVar ); +} + +/**Function************************************************************* + + Synopsis [Removes one partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinRemovePart( Llb_Mgr_t * p, Llb_Prt_t * pPart ) +{ + assert( p->pParts[pPart->iPart] == pPart ); + p->pParts[pPart->iPart] = NULL; + Vec_IntFree( pPart->vVars ); + Cudd_RecursiveDeref( p->dd, pPart->bFunc ); + ABC_FREE( pPart ); +} + +/**Function************************************************************* + + Synopsis [Create cube with singleton variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_NonlinCreateCube1( Llb_Mgr_t * p, Llb_Prt_t * pPart ) +{ + DdNode * bCube, * bTemp; + Llb_Var_t * pVar; + int i; + abctime TimeStop; + TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; + bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube ); + Llb_PartForEachVar( p, pPart, pVar, i ) + { + assert( Vec_IntSize(pVar->vParts) > 0 ); + if ( Vec_IntSize(pVar->vParts) != 1 ) + continue; + assert( Vec_IntEntry(pVar->vParts, 0) == pPart->iPart ); + bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Cudd_Deref( bCube ); + p->dd->TimeStop = TimeStop; + return bCube; +} + +/**Function************************************************************* + + Synopsis [Create cube of variables appearing only in two partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_NonlinCreateCube2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 ) +{ + DdNode * bCube, * bTemp; + Llb_Var_t * pVar; + int i; + abctime TimeStop; + TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; + bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube ); + Llb_PartForEachVar( p, pPart1, pVar, i ) + { + assert( Vec_IntSize(pVar->vParts) > 0 ); + if ( Vec_IntSize(pVar->vParts) != 2 ) + continue; + if ( (Vec_IntEntry(pVar->vParts, 0) == pPart1->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart2->iPart) || + (Vec_IntEntry(pVar->vParts, 0) == pPart2->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart1->iPart) ) + { + bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + } + Cudd_Deref( bCube ); + p->dd->TimeStop = TimeStop; + return bCube; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if partition has singleton variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinHasSingletonVars( Llb_Mgr_t * p, Llb_Prt_t * pPart ) +{ + Llb_Var_t * pVar; + int i; + Llb_PartForEachVar( p, pPart, pVar, i ) + if ( Vec_IntSize(pVar->vParts) == 1 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if partition has singleton variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinPrint( Llb_Mgr_t * p ) +{ + Llb_Prt_t * pPart; + Llb_Var_t * pVar; + int i, k; + printf( "\n" ); + Llb_MgrForEachVar( p, pVar, i ) + { + printf( "Var %3d : ", i ); + Llb_VarForEachPart( p, pVar, pPart, k ) + printf( "%d ", pPart->iPart ); + printf( "\n" ); + } + Llb_MgrForEachPart( p, pPart, i ) + { + printf( "Part %3d : ", i ); + Llb_PartForEachVar( p, pPart, pVar, k ) + printf( "%d ", pVar->iVar ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Quantifies singles belonging to one partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinQuantify1( Llb_Mgr_t * p, Llb_Prt_t * pPart, int fSubset ) +{ + Llb_Var_t * pVar; + Llb_Prt_t * pTemp; + Vec_Ptr_t * vSingles; + DdNode * bCube, * bTemp; + int i, RetValue, nSizeNew; + if ( fSubset ) + { + int Length; +// int nSuppSize = Cudd_SupportSize( p->dd, pPart->bFunc ); +// pPart->bFunc = Cudd_SubsetHeavyBranch( p->dd, bTemp = pPart->bFunc, nSuppSize, 3*pPart->nSize/4 ); Cudd_Ref( pPart->bFunc ); + pPart->bFunc = Cudd_LargestCube( p->dd, bTemp = pPart->bFunc, &Length ); Cudd_Ref( pPart->bFunc ); + + printf( "Subsetting %3d : ", pPart->iPart ); + printf( "(Supp =%3d Node =%5d) -> ", Cudd_SupportSize(p->dd, bTemp), Cudd_DagSize(bTemp) ); + printf( "(Supp =%3d Node =%5d)\n", Cudd_SupportSize(p->dd, pPart->bFunc), Cudd_DagSize(pPart->bFunc) ); + + RetValue = (Cudd_DagSize(bTemp) == Cudd_DagSize(pPart->bFunc)); + + Cudd_RecursiveDeref( p->dd, bTemp ); + + if ( RetValue ) + return 1; + } + else + { + // create cube to be quantified + bCube = Llb_NonlinCreateCube1( p, pPart ); Cudd_Ref( bCube ); +// assert( !Cudd_IsConstant(bCube) ); + // derive new function + pPart->bFunc = Cudd_bddExistAbstract( p->dd, bTemp = pPart->bFunc, bCube ); Cudd_Ref( pPart->bFunc ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bCube ); + } + // get support + vSingles = Vec_PtrAlloc( 0 ); + nSizeNew = Cudd_DagSize(pPart->bFunc); + Extra_SupportArray( p->dd, pPart->bFunc, p->pSupp ); + Llb_PartForEachVar( p, pPart, pVar, i ) + if ( p->pSupp[pVar->iVar] ) + { + assert( Vec_IntSize(pVar->vParts) > 1 ); + pVar->nScore -= pPart->nSize - nSizeNew; + } + else + { + RetValue = Vec_IntRemove( pVar->vParts, pPart->iPart ); + assert( RetValue ); + pVar->nScore -= pPart->nSize; + if ( Vec_IntSize(pVar->vParts) == 0 ) + Llb_NonlinRemoveVar( p, pVar ); + else if ( Vec_IntSize(pVar->vParts) == 1 ) + Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); + } + + // update partition + pPart->nSize = nSizeNew; + Vec_IntClear( pPart->vVars ); + for ( i = 0; i < p->nVars; i++ ) + if ( p->pSupp[i] && p->pVars2Q[i] ) + Vec_IntPush( pPart->vVars, i ); + // remove other variables + Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i ) + Llb_NonlinQuantify1( p, pTemp, 0 ); + Vec_PtrFree( vSingles ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Quantifies singles belonging to one partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinQuantify2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 ) +{ + int fVerbose = 0; + Llb_Var_t * pVar; + Llb_Prt_t * pTemp; + Vec_Ptr_t * vSingles; + DdNode * bCube, * bFunc; + int i, RetValue, nSuppSize; +// int iPart1 = pPart1->iPart; +// int iPart2 = pPart2->iPart; + + // create cube to be quantified + bCube = Llb_NonlinCreateCube2( p, pPart1, pPart2 ); Cudd_Ref( bCube ); +if ( fVerbose ) +{ +printf( "\n" ); +printf( "\n" ); +Llb_NonlinPrint( p ); +printf( "Conjoining partitions %d and %d.\n", pPart1->iPart, pPart2->iPart ); +Extra_bddPrintSupport( p->dd, bCube ); printf( "\n" ); +} + + // derive new function +// bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube ); Cudd_Ref( bFunc ); +/* + bFunc = Cudd_bddAndAbstractLimit( p->dd, pPart1->bFunc, pPart2->bFunc, bCube, Limit ); + if ( bFunc == NULL ) + { + int RetValue; + Cudd_RecursiveDeref( p->dd, bCube ); + if ( pPart1->nSize < pPart2->nSize ) + RetValue = Llb_NonlinQuantify1( p, pPart1, 1 ); + else + RetValue = Llb_NonlinQuantify1( p, pPart2, 1 ); + if ( RetValue ) + Limit = Limit + 1000; + Llb_NonlinQuantify2( p, pPart1, pPart2 ); + return 0; + } + Cudd_Ref( bFunc ); +*/ + +// bFunc = Extra_bddAndAbstractTime( p->dd, pPart1->bFunc, pPart2->bFunc, bCube, TimeOut ); + bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube ); + if ( bFunc == NULL ) + { + Cudd_RecursiveDeref( p->dd, bCube ); + return 0; + } + Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( p->dd, bCube ); + + // create new partition + pTemp = p->pParts[p->iPartFree] = ABC_CALLOC( Llb_Prt_t, 1 ); + pTemp->iPart = p->iPartFree++; + pTemp->nSize = Cudd_DagSize(bFunc); + pTemp->bFunc = bFunc; + pTemp->vVars = Vec_IntAlloc( 8 ); + // update variables + Llb_PartForEachVar( p, pPart1, pVar, i ) + { + RetValue = Vec_IntRemove( pVar->vParts, pPart1->iPart ); + assert( RetValue ); + pVar->nScore -= pPart1->nSize; + } + // update variables + Llb_PartForEachVar( p, pPart2, pVar, i ) + { + RetValue = Vec_IntRemove( pVar->vParts, pPart2->iPart ); + assert( RetValue ); + pVar->nScore -= pPart2->nSize; + } + // add variables to the new partition + nSuppSize = 0; + Extra_SupportArray( p->dd, bFunc, p->pSupp ); + for ( i = 0; i < p->nVars; i++ ) + { + nSuppSize += p->pSupp[i]; + if ( p->pSupp[i] && p->pVars2Q[i] ) + { + pVar = Llb_MgrVar( p, i ); + pVar->nScore += pTemp->nSize; + Vec_IntPush( pVar->vParts, pTemp->iPart ); + Vec_IntPush( pTemp->vVars, i ); + } + } + p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize ); + // remove variables and collect partitions with singleton variables + vSingles = Vec_PtrAlloc( 0 ); + Llb_PartForEachVar( p, pPart1, pVar, i ) + { + if ( Vec_IntSize(pVar->vParts) == 0 ) + Llb_NonlinRemoveVar( p, pVar ); + else if ( Vec_IntSize(pVar->vParts) == 1 ) + { + if ( fVerbose ) + printf( "Adding partition %d because of var %d.\n", + Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar ); + Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); + } + } + Llb_PartForEachVar( p, pPart2, pVar, i ) + { + if ( pVar == NULL ) + continue; + if ( Vec_IntSize(pVar->vParts) == 0 ) + Llb_NonlinRemoveVar( p, pVar ); + else if ( Vec_IntSize(pVar->vParts) == 1 ) + { + if ( fVerbose ) + printf( "Adding partition %d because of var %d.\n", + Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar ); + Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); + } + } + // remove partitions + Llb_NonlinRemovePart( p, pPart1 ); + Llb_NonlinRemovePart( p, pPart2 ); + // remove other variables +if ( fVerbose ) +Llb_NonlinPrint( p ); + Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i ) + { +if ( fVerbose ) +printf( "Updating partitiong %d with singlton vars.\n", pTemp->iPart ); + Llb_NonlinQuantify1( p, pTemp, 0 ); + } +if ( fVerbose ) +Llb_NonlinPrint( p ); + Vec_PtrFree( vSingles ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinCutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Saig_ObjIsLi(p, pObj) ) + { + Llb_NonlinCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); + return; + } + if ( Aig_ObjIsConst1(pObj) ) + return; + assert( Aig_ObjIsNode(pObj) ); + Llb_NonlinCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); + Llb_NonlinCutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_NonlinCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + // mark the lower cut with the traversal ID + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // count the upper cut + vNodes = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) + Llb_NonlinCutNodes_rec( p, pObj, vNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Returns array of BDDs for the roots in terms of the leaves.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_NonlinBuildBdds( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, DdManager * dd ) +{ + Vec_Ptr_t * vNodes, * vResult; + Aig_Obj_t * pObj; + DdNode * bBdd0, * bBdd1, * bProd; + int i, k; + + Aig_ManConst1(p)->pData = Cudd_ReadOne( dd ); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + pObj->pData = Cudd_bddIthVar( dd, Aig_ObjId(pObj) ); + + vNodes = Llb_NonlinCutNodes( p, vLower, vUpper ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); +// pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeOut ); + pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); + if ( pObj->pData == NULL ) + { + Vec_PtrForEachEntryStop( Aig_Obj_t *, vNodes, pObj, k, i ) + if ( pObj->pData ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + Vec_PtrFree( vNodes ); + return NULL; + } + Cudd_Ref( (DdNode *)pObj->pData ); + } + + vResult = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) + { + if ( Aig_ObjIsNode(pObj) ) + { + bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), (DdNode *)pObj->pData ); Cudd_Ref( bProd ); + } + else + { + assert( Saig_ObjIsLi(p, pObj) ); + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), bBdd0 ); Cudd_Ref( bProd ); + } + Vec_PtrPush( vResult, bProd ); + } + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + + Vec_PtrFree( vNodes ); + return vResult; +} + +/**Function************************************************************* + + Synopsis [Starts non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinAddPair( Llb_Mgr_t * p, DdNode * bFunc, int iPart, int iVar ) +{ + if ( p->pVars[iVar] == NULL ) + { + p->pVars[iVar] = ABC_CALLOC( Llb_Var_t, 1 ); + p->pVars[iVar]->iVar = iVar; + p->pVars[iVar]->nScore = 0; + p->pVars[iVar]->vParts = Vec_IntAlloc( 8 ); + } + Vec_IntPush( p->pVars[iVar]->vParts, iPart ); + Vec_IntPush( p->pParts[iPart]->vVars, iVar ); +} + +/**Function************************************************************* + + Synopsis [Starts non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinAddPartition( Llb_Mgr_t * p, int i, DdNode * bFunc ) +{ + int k, nSuppSize; + assert( !Cudd_IsConstant(bFunc) ); + // create partition + p->pParts[i] = ABC_CALLOC( Llb_Prt_t, 1 ); + p->pParts[i]->iPart = i; + p->pParts[i]->bFunc = bFunc; + p->pParts[i]->vVars = Vec_IntAlloc( 8 ); + // add support dependencies + nSuppSize = 0; + Extra_SupportArray( p->dd, bFunc, p->pSupp ); + for ( k = 0; k < p->nVars; k++ ) + { + nSuppSize += p->pSupp[k]; + if ( p->pSupp[k] && p->pVars2Q[k] ) + Llb_NonlinAddPair( p, bFunc, i, k ); + } + p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize ); +} + +/**Function************************************************************* + + Synopsis [Starts non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinStart( Llb_Mgr_t * p ) +{ + Vec_Ptr_t * vRootBdds; + DdNode * bFunc; + int i; + // create and collect BDDs + vRootBdds = Llb_NonlinBuildBdds( p->pAig, p->vLeaves, p->vRoots, p->dd ); // come referenced + if ( vRootBdds == NULL ) + return 0; + // add pairs (refs are consumed inside) + Vec_PtrForEachEntry( DdNode *, vRootBdds, bFunc, i ) + Llb_NonlinAddPartition( p, i, bFunc ); + Vec_PtrFree( vRootBdds ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks that each var appears in at least one partition.] + + Description [] + + SideEffects [] + + SeeAlso [] +**********************************************************************/ +void Llb_NonlinCheckVars( Llb_Mgr_t * p ) +{ + Llb_Var_t * pVar; + int i; + Llb_MgrForEachVar( p, pVar, i ) + assert( Vec_IntSize(pVar->vParts) > 1 ); +} + +/**Function************************************************************* + + Synopsis [Find next partition to quantify] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinNextPartitions( Llb_Mgr_t * p, Llb_Prt_t ** ppPart1, Llb_Prt_t ** ppPart2 ) +{ + Llb_Var_t * pVar, * pVarBest = NULL; + Llb_Prt_t * pPart, * pPart1Best = NULL, * pPart2Best = NULL; + int i; + Llb_NonlinCheckVars( p ); + // find variable with minimum score + Llb_MgrForEachVar( p, pVar, i ) + if ( pVarBest == NULL || pVarBest->nScore > pVar->nScore ) + pVarBest = pVar; + if ( pVarBest == NULL ) + return 0; + // find two partitions with minimum size + Llb_VarForEachPart( p, pVarBest, pPart, i ) + { + if ( pPart1Best == NULL ) + pPart1Best = pPart; + else if ( pPart2Best == NULL ) + pPart2Best = pPart; + else if ( pPart1Best->nSize > pPart->nSize || pPart2Best->nSize > pPart->nSize ) + { + if ( pPart1Best->nSize > pPart2Best->nSize ) + pPart1Best = pPart; + else + pPart2Best = pPart; + } + } + *ppPart1 = pPart1Best; + *ppPart2 = pPart2Best; + return 1; +} + +/**Function************************************************************* + + Synopsis [Reorders BDDs in the working manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinReorder( DdManager * dd, int fTwice, int fVerbose ) +{ + abctime clk = Abc_Clock(); + if ( fVerbose ) + Abc_Print( 1, "Reordering... Before =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + if ( fVerbose ) + Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + if ( fTwice ) + { + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + if ( fVerbose ) + Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + } + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [Recomputes scores after variable reordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinRecomputeScores( Llb_Mgr_t * p ) +{ + Llb_Prt_t * pPart; + Llb_Var_t * pVar; + int i, k; + Llb_MgrForEachPart( p, pPart, i ) + pPart->nSize = Cudd_DagSize(pPart->bFunc); + Llb_MgrForEachVar( p, pVar, i ) + { + pVar->nScore = 0; + Llb_VarForEachPart( p, pVar, pPart, k ) + pVar->nScore += pPart->nSize; + } +} + +/**Function************************************************************* + + Synopsis [Recomputes scores after variable reordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinVerifyScores( Llb_Mgr_t * p ) +{ + Llb_Prt_t * pPart; + Llb_Var_t * pVar; + int i, k, nScore; + Llb_MgrForEachPart( p, pPart, i ) + assert( pPart->nSize == Cudd_DagSize(pPart->bFunc) ); + Llb_MgrForEachVar( p, pVar, i ) + { + nScore = 0; + Llb_VarForEachPart( p, pVar, pPart, k ) + nScore += pPart->nSize; + assert( nScore == pVar->nScore ); + } +} + +/**Function************************************************************* + + Synopsis [Starts non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Mgr_t * Llb_NonlinAlloc( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, DdManager * dd ) +{ + Llb_Mgr_t * p; + p = ABC_CALLOC( Llb_Mgr_t, 1 ); + p->pAig = pAig; + p->vLeaves = vLeaves; + p->vRoots = vRoots; + p->dd = dd; + p->pVars2Q = pVars2Q; + p->nVars = Cudd_ReadSize(dd); + p->iPartFree = Vec_PtrSize(vRoots); + p->pVars = ABC_CALLOC( Llb_Var_t *, p->nVars ); + p->pParts = ABC_CALLOC( Llb_Prt_t *, 2 * p->iPartFree + 2 ); + p->pSupp = ABC_ALLOC( int, Cudd_ReadSize(dd) ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinFree( Llb_Mgr_t * p ) +{ + Llb_Prt_t * pPart; + Llb_Var_t * pVar; + int i; + Llb_MgrForEachVar( p, pVar, i ) + Llb_NonlinRemoveVar( p, pVar ); + Llb_MgrForEachPart( p, pPart, i ) + Llb_NonlinRemovePart( p, pPart ); + ABC_FREE( p->pVars ); + ABC_FREE( p->pParts ); + ABC_FREE( p->pSupp ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Performs image computation.] + + Description [Computes image of BDDs (vFuncs).] + + SideEffects [BDDs in vFuncs are derefed inside. The result is refed.] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_NonlinImage( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, + DdManager * dd, DdNode * bCurrent, int fReorder, int fVerbose, int * pOrder ) +{ + Llb_Prt_t * pPart, * pPart1, * pPart2; + Llb_Mgr_t * p; + DdNode * bFunc, * bTemp; + int i, nReorders, timeInside; + abctime clk = Abc_Clock(), clk2; + // start the manager + clk2 = Abc_Clock(); + p = Llb_NonlinAlloc( pAig, vLeaves, vRoots, pVars2Q, dd ); + if ( !Llb_NonlinStart( p ) ) + { + Llb_NonlinFree( p ); + return NULL; + } + // add partition + Llb_NonlinAddPartition( p, p->iPartFree++, bCurrent ); + // remove singles + Llb_MgrForEachPart( p, pPart, i ) + if ( Llb_NonlinHasSingletonVars(p, pPart) ) + Llb_NonlinQuantify1( p, pPart, 0 ); + timeBuild += Abc_Clock() - clk2; + timeInside = Abc_Clock() - clk2; + // compute scores + Llb_NonlinRecomputeScores( p ); + // save permutation + if ( pOrder ) + memcpy( pOrder, dd->invperm, sizeof(int) * dd->size ); + // iteratively quantify variables + while ( Llb_NonlinNextPartitions(p, &pPart1, &pPart2) ) + { + clk2 = Abc_Clock(); + nReorders = Cudd_ReadReorderings(dd); + if ( !Llb_NonlinQuantify2( p, pPart1, pPart2 ) ) + { + Llb_NonlinFree( p ); + return NULL; + } + timeAndEx += Abc_Clock() - clk2; + timeInside += Abc_Clock() - clk2; + if ( nReorders < Cudd_ReadReorderings(dd) ) + Llb_NonlinRecomputeScores( p ); +// else +// Llb_NonlinVerifyScores( p ); + } + // load partitions + bFunc = Cudd_ReadOne(p->dd); Cudd_Ref( bFunc ); + Llb_MgrForEachPart( p, pPart, i ) + { + bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + nSuppMax = p->nSuppMax; + Llb_NonlinFree( p ); + // reorder variables + if ( fReorder ) + Llb_NonlinReorder( dd, 0, fVerbose ); + timeOther += Abc_Clock() - clk - timeInside; + // return + Cudd_Deref( bFunc ); + return bFunc; +} + + + +static Llb_Mgr_t * p = NULL; + +/**Function************************************************************* + + Synopsis [Starts image computation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdManager * Llb_NonlinImageStart( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, int * pOrder, int fFirst, abctime TimeTarget ) +{ + DdManager * dd; + abctime clk = Abc_Clock(); + assert( p == NULL ); + // start a new manager (disable reordering) + dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + dd->TimeStop = TimeTarget; + Cudd_ShuffleHeap( dd, pOrder ); +// if ( fFirst ) + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + // start the manager + p = Llb_NonlinAlloc( pAig, vLeaves, vRoots, pVars2Q, dd ); + if ( !Llb_NonlinStart( p ) ) + { + Llb_NonlinFree( p ); + p = NULL; + return NULL; + } + timeBuild += Abc_Clock() - clk; +// if ( !fFirst ) +// Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + return dd; +} + +/**Function************************************************************* + + Synopsis [Performs image computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_NonlinImageCompute( DdNode * bCurrent, int fReorder, int fDrop, int fVerbose, int * pOrder ) +{ + Llb_Prt_t * pPart, * pPart1, * pPart2; + DdNode * bFunc, * bTemp; + int i, nReorders, timeInside = 0; + abctime clk = Abc_Clock(), clk2; + + // add partition + Llb_NonlinAddPartition( p, p->iPartFree++, bCurrent ); + // remove singles + Llb_MgrForEachPart( p, pPart, i ) + if ( Llb_NonlinHasSingletonVars(p, pPart) ) + Llb_NonlinQuantify1( p, pPart, 0 ); + // reorder + if ( fReorder ) + Llb_NonlinReorder( p->dd, 0, 0 ); + // save permutation + memcpy( pOrder, p->dd->invperm, sizeof(int) * p->dd->size ); + + // compute scores + Llb_NonlinRecomputeScores( p ); + // iteratively quantify variables + while ( Llb_NonlinNextPartitions(p, &pPart1, &pPart2) ) + { + clk2 = Abc_Clock(); + nReorders = Cudd_ReadReorderings(p->dd); + if ( !Llb_NonlinQuantify2( p, pPart1, pPart2 ) ) + { + Llb_NonlinFree( p ); + return NULL; + } + timeAndEx += Abc_Clock() - clk2; + timeInside += Abc_Clock() - clk2; + if ( nReorders < Cudd_ReadReorderings(p->dd) ) + Llb_NonlinRecomputeScores( p ); +// else +// Llb_NonlinVerifyScores( p ); + } + // load partitions + bFunc = Cudd_ReadOne(p->dd); Cudd_Ref( bFunc ); + Llb_MgrForEachPart( p, pPart, i ) + { + bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc ); + if ( bFunc == NULL ) + { + Cudd_RecursiveDeref( p->dd, bTemp ); + Llb_NonlinFree( p ); + return NULL; + } + Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + nSuppMax = p->nSuppMax; + // reorder variables +// if ( fReorder ) +// Llb_NonlinReorder( p->dd, 0, fVerbose ); + // save permutation +// memcpy( pOrder, p->dd->invperm, sizeof(int) * Cudd_ReadSize(p->dd) ); + + timeOther += Abc_Clock() - clk - timeInside; + // return + Cudd_Deref( bFunc ); + return bFunc; +} + +/**Function************************************************************* + + Synopsis [Quits image computation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinImageQuit() +{ + DdManager * dd; + if ( p == NULL ) + return; + dd = p->dd; + Llb_NonlinFree( p ); + if ( dd->bFunc ) + Cudd_RecursiveDeref( dd, dd->bFunc ); + Extra_StopManager( dd ); +// Cudd_Quit ( dd ); + p = NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb3Nonlin.c b/src/bdd/llb/llb3Nonlin.c new file mode 100644 index 00000000..94a48bbf --- /dev/null +++ b/src/bdd/llb/llb3Nonlin.c @@ -0,0 +1,872 @@ +/**CFile**************************************************************** + + FileName [llb2Nonlin.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Non-linear quantification scheduling.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Nonlin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Llb_Mnn_t_ Llb_Mnn_t; +struct Llb_Mnn_t_ +{ + Aig_Man_t * pInit; // AIG manager + Aig_Man_t * pAig; // AIG manager + Gia_ParLlb_t * pPars; // parameters + + DdManager * dd; // BDD manager + DdManager * ddG; // BDD manager + DdManager * ddR; // BDD manager + Vec_Ptr_t * vRings; // onion rings in ddR + + Vec_Ptr_t * vLeaves; + Vec_Ptr_t * vRoots; + int * pVars2Q; + int * pOrderL; + int * pOrderL2; + int * pOrderG; + + Vec_Int_t * vCs2Glo; // cur state variables into global variables + Vec_Int_t * vNs2Glo; // next state variables into global variables + Vec_Int_t * vGlo2Cs; // global variables into cur state variables + Vec_Int_t * vGlo2Ns; // global variables into next state variables + + int ddLocReos; + int ddLocGrbs; + + abctime timeImage; + abctime timeTran1; + abctime timeTran2; + abctime timeGloba; + abctime timeOther; + abctime timeTotal; + abctime timeReo; + abctime timeReoG; + +}; + +extern abctime timeBuild, timeAndEx, timeOther; +extern int nSuppMax; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Finds variable whose 0-cofactor is the smallest.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinFindBestVar( DdManager * dd, DdNode * bFunc, Aig_Man_t * pAig ) +{ + int fVerbose = 0; + Aig_Obj_t * pObj; + DdNode * bCof, * bVar; + int i, iVar, iVarBest = -1, iValue, iValueBest = ABC_INFINITY, Size0Best = -1; + int Size, Size0, Size1; + abctime clk = Abc_Clock(); + Size = Cudd_DagSize(bFunc); +// printf( "Original = %6d. SuppSize = %3d. Vars = %3d.\n", +// Size = Cudd_DagSize(bFunc), Cudd_SupportSize(dd, bFunc), Aig_ManRegNum(pAig) ); + Saig_ManForEachLo( pAig, pObj, i ) + { + iVar = Aig_ObjId(pObj); + +if ( fVerbose ) +printf( "Var =%3d : ", iVar ); + bVar = Cudd_bddIthVar(dd, iVar); + + bCof = Cudd_bddAnd( dd, bFunc, Cudd_Not(bVar) ); Cudd_Ref( bCof ); + Size0 = Cudd_DagSize(bCof); +if ( fVerbose ) +printf( "Supp0 =%3d ", Cudd_SupportSize(dd, bCof) ); +if ( fVerbose ) +printf( "Size0 =%6d ", Size0 ); + Cudd_RecursiveDeref( dd, bCof ); + + bCof = Cudd_bddAnd( dd, bFunc, bVar ); Cudd_Ref( bCof ); + Size1 = Cudd_DagSize(bCof); +if ( fVerbose ) +printf( "Supp1 =%3d ", Cudd_SupportSize(dd, bCof) ); +if ( fVerbose ) +printf( "Size1 =%6d ", Size1 ); + Cudd_RecursiveDeref( dd, bCof ); + + iValue = Abc_MaxInt(Size0, Size1) - Abc_MinInt(Size0, Size1) + Size0 + Size1 - Size; +if ( fVerbose ) +printf( "D =%6d ", Size0 + Size1 - Size ); +if ( fVerbose ) +printf( "B =%6d ", Abc_MaxInt(Size0, Size1) - Abc_MinInt(Size0, Size1) ); +if ( fVerbose ) +printf( "S =%6d\n", iValue ); + if ( Size0 > 1 && Size1 > 1 && iValueBest > iValue ) + { + iValueBest = iValue; + iVarBest = i; + Size0Best = Size0; + } + } + printf( "BestVar = %4d/%4d. Value =%6d. Orig =%6d. Size0 =%6d. ", + iVarBest, Aig_ObjId(Saig_ManLo(pAig,iVarBest)), iValueBest, Size, Size0Best ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return iVarBest; +} + + +/**Function************************************************************* + + Synopsis [Finds variable whose 0-cofactor is the smallest.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinTrySubsetting( DdManager * dd, DdNode * bFunc ) +{ + DdNode * bNew; + printf( "Original = %6d. SuppSize = %3d. ", + Cudd_DagSize(bFunc), Cudd_SupportSize(dd, bFunc) ); + bNew = Cudd_SubsetHeavyBranch( dd, bFunc, Cudd_SupportSize(dd, bFunc), 1000 ); Cudd_Ref( bNew ); + printf( "Result = %6d. SuppSize = %3d.\n", + Cudd_DagSize(bNew), Cudd_SupportSize(dd, bNew) ); + Cudd_RecursiveDeref( dd, bNew ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinPrepareVarMap( Llb_Mnn_t * p ) +{ + Aig_Obj_t * pObjLi, * pObjLo, * pObj; + int i, iVarLi, iVarLo; + p->vCs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) ); + p->vNs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) ); + p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); + p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); + Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) + { + iVarLi = Aig_ObjId(pObjLi); + iVarLo = Aig_ObjId(pObjLo); + assert( iVarLi >= 0 && iVarLi < Aig_ManObjNumMax(p->pAig) ); + assert( iVarLo >= 0 && iVarLo < Aig_ManObjNumMax(p->pAig) ); + Vec_IntWriteEntry( p->vCs2Glo, iVarLo, i ); + Vec_IntWriteEntry( p->vNs2Glo, iVarLi, i ); + Vec_IntWriteEntry( p->vGlo2Cs, i, iVarLo ); + Vec_IntWriteEntry( p->vGlo2Ns, i, iVarLi ); + } + // add mapping of the PIs + Saig_ManForEachPi( p->pAig, pObj, i ) + { + Vec_IntWriteEntry( p->vCs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i ); + Vec_IntWriteEntry( p->vNs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i ); + } +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_NonlinComputeInitState( Aig_Man_t * pAig, DdManager * dd ) +{ + Aig_Obj_t * pObj; + DdNode * bRes, * bVar, * bTemp; + int i, iVar; + abctime TimeStop; + TimeStop = dd->TimeStop; dd->TimeStop = 0; + bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); + Saig_ManForEachLo( pAig, pObj, i ) + { + iVar = (Cudd_ReadSize(dd) == Aig_ManRegNum(pAig)) ? i : Aig_ObjId(pObj); + bVar = Cudd_bddIthVar( dd, iVar ); + bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bRes ); + dd->TimeStop = TimeStop; + return bRes; +} + + +/**Function************************************************************* + + Synopsis [Derives counter-example by backward reachability.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Llb_NonlinDeriveCex( Llb_Mnn_t * p ) +{ + Abc_Cex_t * pCex; + Aig_Obj_t * pObj; + Vec_Int_t * vVarsNs; + DdNode * bState = NULL, * bImage, * bOneCube, * bTemp, * bRing; + int i, v, RetValue, nPiOffset; + char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) ); + assert( Vec_PtrSize(p->vRings) > 0 ); + + p->dd->TimeStop = 0; + p->ddR->TimeStop = 0; + + // update quantifiable vars + memset( p->pVars2Q, 0, sizeof(int) * Cudd_ReadSize(p->dd) ); + vVarsNs = Vec_IntAlloc( Aig_ManRegNum(p->pAig) ); + Saig_ManForEachLi( p->pAig, pObj, i ) + { + p->pVars2Q[Aig_ObjId(pObj)] = 1; + Vec_IntPush( vVarsNs, Aig_ObjId(pObj) ); + } +/* + Saig_ManForEachLo( p->pAig, pObj, i ) + printf( "%d ", pObj->Id ); + printf( "\n" ); + Saig_ManForEachLi( p->pAig, pObj, i ) + printf( "%d(%d) ", pObj->Id, Aig_ObjFaninId0(pObj) ); + printf( "\n" ); +*/ + // allocate room for the counter-example + pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) ); + pCex->iFrame = Vec_PtrSize(p->vRings) - 1; + pCex->iPo = -1; + + // get the last cube + bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc ); Cudd_Ref( bOneCube ); + RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); + Cudd_RecursiveDeref( p->ddR, bOneCube ); + assert( RetValue ); + + // write PIs of counter-example + nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1); + Saig_ManForEachPi( p->pAig, pObj, i ) + if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) + Abc_InfoSetBit( pCex->pData, nPiOffset + i ); + + // write state in terms of NS variables + if ( Vec_PtrSize(p->vRings) > 1 ) + { + bState = Llb_CoreComputeCube( p->dd, vVarsNs, 1, pValues ); Cudd_Ref( bState ); + } + // perform backward analysis + Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v ) + { + if ( v == Vec_PtrSize(p->vRings) - 1 ) + continue; +//Extra_bddPrintSupport( p->dd, bState ); printf( "\n" ); +//Extra_bddPrintSupport( p->dd, bRing ); printf( "\n" ); + // compute the next states + bImage = Llb_NonlinImage( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->dd, bState, + p->pPars->fReorder, p->pPars->fVeryVerbose, NULL ); // consumed reference + assert( bImage != NULL ); + Cudd_Ref( bImage ); +//Extra_bddPrintSupport( p->dd, bImage ); printf( "\n" ); + + // move reached states into ring manager + bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) ); Cudd_Ref( bImage ); + Cudd_RecursiveDeref( p->dd, bTemp ); + + // intersect with the previous set + bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing ); Cudd_Ref( bOneCube ); + Cudd_RecursiveDeref( p->ddR, bImage ); + + // find any assignment of the BDD + RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); + Cudd_RecursiveDeref( p->ddR, bOneCube ); + assert( RetValue ); + + // write PIs of counter-example + nPiOffset -= Saig_ManPiNum(p->pAig); + Saig_ManForEachPi( p->pAig, pObj, i ) + if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) + Abc_InfoSetBit( pCex->pData, nPiOffset + i ); + + // check that we get the init state + if ( v == 0 ) + { + Saig_ManForEachLo( p->pAig, pObj, i ) + assert( pValues[i] == 0 ); + break; + } + + // write state in terms of NS variables + bState = Llb_CoreComputeCube( p->dd, vVarsNs, 1, pValues ); Cudd_Ref( bState ); + } + assert( nPiOffset == Saig_ManRegNum(p->pAig) ); + // update the output number +//Abc_CexPrint( pCex ); + RetValue = Saig_ManFindFailedPoCex( p->pInit, pCex ); + assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pInit) ); // invalid CEX!!! + pCex->iPo = RetValue; + // cleanup + ABC_FREE( pValues ); + Vec_IntFree( vVarsNs ); + return pCex; +} + + +/**Function************************************************************* + + Synopsis [Perform reachability with hints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinReoHook( DdManager * dd, char * Type, void * Method ) +{ + Aig_Man_t * pAig = (Aig_Man_t *)dd->bFunc; + Aig_Obj_t * pObj; + int i; + printf( "Order: " ); + for ( i = 0; i < Cudd_ReadSize(dd); i++ ) + { + pObj = Aig_ManObj( pAig, i ); + if ( pObj == NULL ) + continue; + if ( Saig_ObjIsPi(pAig, pObj) ) + printf( "pi" ); + else if ( Saig_ObjIsLo(pAig, pObj) ) + printf( "lo" ); + else if ( Saig_ObjIsPo(pAig, pObj) ) + printf( "po" ); + else if ( Saig_ObjIsLi(pAig, pObj) ) + printf( "li" ); + else continue; + printf( "%d=%d ", i, dd->perm[i] ); + } + printf( "\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Perform reachability with hints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinCompPerms( DdManager * dd, int * pVar2Lev ) +{ + DdSubtable * pSubt; + int i, Sum = 0, Entry; + for ( i = 0; i < dd->size; i++ ) + { + pSubt = &(dd->subtables[dd->perm[i]]); + if ( pSubt->keys == pSubt->dead + 1 ) + continue; + Entry = Abc_MaxInt(dd->perm[i], pVar2Lev[i]) - Abc_MinInt(dd->perm[i], pVar2Lev[i]); + Sum += Entry; +//printf( "%d-%d(%d) ", dd->perm[i], pV2L[i], Entry ); + } + return Sum; +} + +/**Function************************************************************* + + Synopsis [Perform reachability with hints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinReachability( Llb_Mnn_t * p ) +{ + DdNode * bTemp, * bNext; + int nIters, nBddSize0, nBddSize = -1, NumCmp;//, Limit = p->pPars->nBddMax; + abctime clk2, clk3, clk = Abc_Clock(); + assert( Aig_ManRegNum(p->pAig) > 0 ); + + // compute time to stop + p->pPars->TimeTarget = p->pPars->TimeLimit ? p->pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0; + + // set the stop time parameter + p->dd->TimeStop = p->pPars->TimeTarget; + p->ddG->TimeStop = p->pPars->TimeTarget; + p->ddR->TimeStop = p->pPars->TimeTarget; + + // set reordering hooks + assert( p->dd->bFunc == NULL ); +// p->dd->bFunc = (DdNode *)p->pAig; +// Cudd_AddHook( p->dd, Llb_NonlinReoHook, CUDD_POST_REORDERING_HOOK ); + + // create bad state in the ring manager + p->ddR->bFunc = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget ); + if ( p->ddR->bFunc == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + Cudd_Ref( p->ddR->bFunc ); + // compute the starting set of states + Cudd_Quit( p->dd ); + p->dd = Llb_NonlinImageStart( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->pOrderL, 1, p->pPars->TimeTarget ); + if ( p->dd == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + p->dd->bFunc = Llb_NonlinComputeInitState( p->pAig, p->dd ); Cudd_Ref( p->dd->bFunc ); // current + p->ddG->bFunc = Llb_NonlinComputeInitState( p->pAig, p->ddG ); Cudd_Ref( p->ddG->bFunc ); // reached + p->ddG->bFunc2 = Llb_NonlinComputeInitState( p->pAig, p->ddG ); Cudd_Ref( p->ddG->bFunc2 ); // frontier + for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ ) + { + // check the runtime limit + clk2 = Abc_Clock(); + if ( p->pPars->TimeLimit && Abc_Clock() > p->pPars->TimeTarget ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Llb_NonlinImageQuit(); + return -1; + } + + // save the onion ring + bTemp = Extra_TransferPermute( p->dd, p->ddR, p->dd->bFunc, Vec_IntArray(p->vCs2Glo) ); + if ( bTemp == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during ring transfer.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Llb_NonlinImageQuit(); + return -1; + } + Cudd_Ref( bTemp ); + Vec_PtrPush( p->vRings, bTemp ); + + // check it for bad states + if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) ) + { + assert( p->pInit->pSeqModel == NULL ); + if ( !p->pPars->fBackward ) + p->pInit->pSeqModel = Llb_NonlinDeriveCex( p ); + if ( !p->pPars->fSilent ) + { + if ( !p->pPars->fBackward ) + Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", p->pInit->pSeqModel->iPo, nIters ); + else + Abc_Print( 1, "Output ??? was asserted in frame %d (counter-example is not produced). ", nIters ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + p->pPars->iFrame = nIters - 1; + Llb_NonlinImageQuit(); + return 0; + } + + // compute the next states + clk3 = Abc_Clock(); + nBddSize0 = Cudd_DagSize( p->dd->bFunc ); + bNext = Llb_NonlinImageCompute( p->dd->bFunc, p->pPars->fReorder, 0, 1, p->pOrderL ); // consumes ref +// bNext = Llb_NonlinImage( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->dd, bCurrent, +// p->pPars->fReorder, p->pPars->fVeryVerbose, NULL, ABC_INFINITY, p->pPars->TimeTarget ); + if ( bNext == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in quantification.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Llb_NonlinImageQuit(); + return -1; + } + Cudd_Ref( bNext ); + nBddSize = Cudd_DagSize( bNext ); + p->timeImage += Abc_Clock() - clk3; + + + // transfer to the state manager + clk3 = Abc_Clock(); + Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc2 ); + p->ddG->bFunc2 = Extra_TransferPermute( p->dd, p->ddG, bNext, Vec_IntArray(p->vNs2Glo) ); +// p->ddG->bFunc2 = Extra_bddAndPermute( p->ddG, Cudd_Not(p->ddG->bFunc), p->dd, bNext, Vec_IntArray(p->vNs2Glo) ); + if ( p->ddG->bFunc2 == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bNext ); + Llb_NonlinImageQuit(); + return -1; + } + Cudd_Ref( p->ddG->bFunc2 ); + Cudd_RecursiveDeref( p->dd, bNext ); + p->timeTran1 += Abc_Clock() - clk3; + + // save permutation + NumCmp = Llb_NonlinCompPerms( p->dd, p->pOrderL2 ); + // save order before image computation + memcpy( p->pOrderL2, p->dd->perm, sizeof(int) * p->dd->size ); + // update the image computation manager + p->timeReo += Cudd_ReadReorderingTime(p->dd); + p->ddLocReos += Cudd_ReadReorderings(p->dd); + p->ddLocGrbs += Cudd_ReadGarbageCollections(p->dd); + Llb_NonlinImageQuit(); + p->dd = Llb_NonlinImageStart( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->pOrderL, 0, p->pPars->TimeTarget ); + if ( p->dd == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + return -1; + } + //Extra_TestAndPerm( p->ddG, Cudd_Not(p->ddG->bFunc), p->ddG->bFunc2 ); + + // derive new states + clk3 = Abc_Clock(); + p->ddG->bFunc2 = Cudd_bddAnd( p->ddG, bTemp = p->ddG->bFunc2, Cudd_Not(p->ddG->bFunc) ); + if ( p->ddG->bFunc2 == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->ddG, bTemp ); + Llb_NonlinImageQuit(); + return -1; + } + Cudd_Ref( p->ddG->bFunc2 ); + Cudd_RecursiveDeref( p->ddG, bTemp ); + p->timeGloba += Abc_Clock() - clk3; + + if ( Cudd_IsConstant(p->ddG->bFunc2) ) + break; + // add to the reached set + clk3 = Abc_Clock(); + p->ddG->bFunc = Cudd_bddOr( p->ddG, bTemp = p->ddG->bFunc, p->ddG->bFunc2 ); + if ( p->ddG->bFunc == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->ddG, bTemp ); + Llb_NonlinImageQuit(); + return -1; + } + Cudd_Ref( p->ddG->bFunc ); + Cudd_RecursiveDeref( p->ddG, bTemp ); + p->timeGloba += Abc_Clock() - clk3; + + // reset permutation +// RetValue = Cudd_CheckZeroRef( dd ); +// assert( RetValue == 0 ); +// Cudd_ShuffleHeap( dd, pOrderG ); + + // move new states to the working manager + clk3 = Abc_Clock(); + p->dd->bFunc = Extra_TransferPermute( p->ddG, p->dd, p->ddG->bFunc2, Vec_IntArray(p->vGlo2Cs) ); + if ( p->dd->bFunc == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Llb_NonlinImageQuit(); + return -1; + } + Cudd_Ref( p->dd->bFunc ); + p->timeTran2 += Abc_Clock() - clk3; + + // report the results + if ( p->pPars->fVerbose ) + { + printf( "I =%3d : ", nIters ); + printf( "Fr =%7d ", nBddSize0 ); + printf( "Im =%7d ", nBddSize ); + printf( "(%4d %4d) ", p->ddLocReos, p->ddLocGrbs ); + printf( "Rea =%6d ", Cudd_DagSize(p->ddG->bFunc) ); + printf( "(%4d %4d) ", Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) ); + printf( "S =%4d ", nSuppMax ); + printf( "cL =%5d ", NumCmp ); + printf( "cG =%5d ", Llb_NonlinCompPerms( p->ddG, p->pOrderG ) ); + Abc_PrintTime( 1, "T", Abc_Clock() - clk2 ); + memcpy( p->pOrderG, p->ddG->perm, sizeof(int) * p->ddG->size ); + } +/* + if ( pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(ddG, bReached, Saig_ManRegNum(pAig) ); +// Extra_bddPrint( ddG, bReached );printf( "\n" ); + printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(pAig)) ); + fflush( stdout ); + } +*/ + if ( nIters == p->pPars->nIterMax - 1 ) + { + if ( !p->pPars->fSilent ) + printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nIterMax ); + p->pPars->iFrame = nIters; + Llb_NonlinImageQuit(); + return -1; + } + } + Llb_NonlinImageQuit(); + + // report the stats + if ( p->pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(p->ddG, p->ddG->bFunc, Saig_ManRegNum(p->pAig) ); + if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) + printf( "Reachability analysis is stopped after %d frames.\n", nIters ); + else + printf( "Reachability analysis completed after %d frames.\n", nIters ); + printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); + fflush( stdout ); + } + if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) + { + if ( !p->pPars->fSilent ) + printf( "Verified only for states reachable in %d frames. ", nIters ); + p->pPars->iFrame = p->pPars->nIterMax; + return -1; // undecided + } + // report + if ( !p->pPars->fSilent ) + printf( "The miter is proved unreachable after %d iterations. ", nIters ); + p->pPars->iFrame = nIters - 1; + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return 1; // unreachable +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Mnn_t * Llb_MnnStart( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) +{ + Llb_Mnn_t * p; + Aig_Obj_t * pObj; + int i; + p = ABC_CALLOC( Llb_Mnn_t, 1 ); + p->pInit = pInit; + p->pAig = pAig; + p->pPars = pPars; + p->dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + p->ddG = Cudd_Init( Aig_ManRegNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + p->ddR = Cudd_Init( Aig_ManCiNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); + Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT ); + Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT ); + p->vRings = Vec_PtrAlloc( 100 ); + // create leaves + p->vLeaves = Vec_PtrAlloc( Aig_ManCiNum(pAig) ); + Aig_ManForEachCi( pAig, pObj, i ) + Vec_PtrPush( p->vLeaves, pObj ); + // create roots + p->vRoots = Vec_PtrAlloc( Aig_ManCoNum(pAig) ); + Saig_ManForEachLi( pAig, pObj, i ) + Vec_PtrPush( p->vRoots, pObj ); + // variables to quantify + p->pOrderL = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); + p->pOrderL2= ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); + p->pOrderG = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); + p->pVars2Q = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); + Aig_ManForEachCi( pAig, pObj, i ) + p->pVars2Q[Aig_ObjId(pObj)] = 1; + for ( i = 0; i < Aig_ManObjNumMax(pAig); i++ ) + p->pOrderL[i] = p->pOrderL2[i] = p->pOrderG[i] = i; + Llb_NonlinPrepareVarMap( p ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MnnStop( Llb_Mnn_t * p ) +{ + DdNode * bTemp; + int i; + if ( p->pPars->fVerbose ) + { + p->timeOther = p->timeTotal - p->timeImage - p->timeTran1 - p->timeTran2 - p->timeGloba; + p->timeReoG = Cudd_ReadReorderingTime(p->ddG); + ABC_PRTP( "Image ", p->timeImage, p->timeTotal ); + ABC_PRTP( " build ", timeBuild, p->timeTotal ); + ABC_PRTP( " and-ex ", timeAndEx, p->timeTotal ); + ABC_PRTP( " other ", timeOther, p->timeTotal ); + ABC_PRTP( "Transfer1", p->timeTran1, p->timeTotal ); + ABC_PRTP( "Transfer2", p->timeTran2, p->timeTotal ); + ABC_PRTP( "Global ", p->timeGloba, p->timeTotal ); + ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); + ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); + ABC_PRTP( " reo ", p->timeReo, p->timeTotal ); + ABC_PRTP( " reoG ", p->timeReoG, p->timeTotal ); + } + if ( p->ddR->bFunc ) + Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc ); + Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i ) + Cudd_RecursiveDeref( p->ddR, bTemp ); + Vec_PtrFree( p->vRings ); + if ( p->ddG->bFunc ) + Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc ); + if ( p->ddG->bFunc2 ) + Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc2 ); +// printf( "manager1\n" ); +// Extra_StopManager( p->dd ); +// printf( "manager2\n" ); + Extra_StopManager( p->ddG ); +// printf( "manager3\n" ); + Extra_StopManager( p->ddR ); + Vec_IntFreeP( &p->vCs2Glo ); + Vec_IntFreeP( &p->vNs2Glo ); + Vec_IntFreeP( &p->vGlo2Cs ); + Vec_IntFreeP( &p->vGlo2Ns ); + Vec_PtrFree( p->vLeaves ); + Vec_PtrFree( p->vRoots ); + ABC_FREE( p->pVars2Q ); + ABC_FREE( p->pOrderL ); + ABC_FREE( p->pOrderL2 ); + ABC_FREE( p->pOrderG ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_NonlinExperiment( Aig_Man_t * pAig, int Num ) +{ + Llb_Mnn_t * pMnn; + Gia_ParLlb_t Pars, * pPars = &Pars; + Aig_Man_t * p; + abctime clk = Abc_Clock(); + + Llb_ManSetDefaultParams( pPars ); + pPars->fVerbose = 1; + + p = Aig_ManDupFlopsOnly( pAig ); +//Aig_ManShow( p, 0, NULL ); + Aig_ManPrintStats( pAig ); + Aig_ManPrintStats( p ); + + pMnn = Llb_MnnStart( pAig, p, pPars ); + Llb_NonlinReachability( pMnn ); + pMnn->timeTotal = Abc_Clock() - clk; + Llb_MnnStop( pMnn ); + + Aig_ManStop( p ); +} + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_NonlinCoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) +{ + Llb_Mnn_t * pMnn; + Aig_Man_t * p; + int RetValue = -1; + + p = Aig_ManDupFlopsOnly( pAig ); +//Aig_ManShow( p, 0, NULL ); + if ( pPars->fVerbose ) + Aig_ManPrintStats( pAig ); + if ( pPars->fVerbose ) + Aig_ManPrintStats( p ); + + if ( !pPars->fSkipReach ) + { + abctime clk = Abc_Clock(); + pMnn = Llb_MnnStart( pAig, p, pPars ); + RetValue = Llb_NonlinReachability( pMnn ); + pMnn->timeTotal = Abc_Clock() - clk; + Llb_MnnStop( pMnn ); + } + + Aig_ManStop( p ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb4Cex.c b/src/bdd/llb/llb4Cex.c new file mode 100644 index 00000000..18aeaf04 --- /dev/null +++ b/src/bdd/llb/llb4Cex.c @@ -0,0 +1,320 @@ +/**CFile**************************************************************** + + FileName [llb2Cex.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Non-linear quantification scheduling.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Cex.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" +#include "sat/cnf/cnf.h" +#include "sat/bsat/satSolver.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Translates a sequence of states into a counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Llb4_Nonlin4TransformCex( Aig_Man_t * pAig, Vec_Ptr_t * vStates, int iCexPo, int fVerbose ) +{ + Abc_Cex_t * pCex; + Cnf_Dat_t * pCnf; + Vec_Int_t * vAssumps; + sat_solver * pSat; + Aig_Obj_t * pObj; + unsigned * pNext, * pThis; + int i, k, iBit, status, nRegs;//, clk = Abc_Clock(); +/* + Vec_PtrForEachEntry( unsigned *, vStates, pNext, i ) + { + printf( "%4d : ", i ); + Extra_PrintBinary( stdout, pNext, Aig_ManRegNum(pAig) ); + printf( "\n" ); + } +*/ + // derive SAT solver + nRegs = Aig_ManRegNum(pAig); pAig->nRegs = 0; + pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) ); + pAig->nRegs = nRegs; +// Cnf_DataTranformPolarity( pCnf, 0 ); + // convert into SAT solver + pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + if ( pSat == NULL ) + { + printf( "Llb4_Nonlin4TransformCex(): Counter-example generation has failed.\n" ); + Cnf_DataFree( pCnf ); + return NULL; + } + // simplify the problem + status = sat_solver_simplify(pSat); + if ( status == 0 ) + { + printf( "Llb4_Nonlin4TransformCex(): SAT solver is invalid.\n" ); + sat_solver_delete( pSat ); + Cnf_DataFree( pCnf ); + return NULL; + } + // start the counter-example + pCex = Abc_CexAlloc( Saig_ManRegNum(pAig), Saig_ManPiNum(pAig), Vec_PtrSize(vStates) ); + pCex->iFrame = Vec_PtrSize(vStates)-1; + pCex->iPo = -1; + + // solve each time frame + iBit = Saig_ManRegNum(pAig); + pThis = (unsigned *)Vec_PtrEntry( vStates, 0 ); + vAssumps = Vec_IntAlloc( 2 * Aig_ManRegNum(pAig) ); + Vec_PtrForEachEntryStart( unsigned *, vStates, pNext, i, 1 ) + { + // create assumptions + Vec_IntClear( vAssumps ); + Saig_ManForEachLo( pAig, pObj, k ) + Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Abc_InfoHasBit(pThis,k) ) ); + Saig_ManForEachLi( pAig, pObj, k ) + Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Abc_InfoHasBit(pNext,k) ) ); + // solve SAT problem + status = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), + (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + // if the problem is SAT, get the counterexample + if ( status != l_True ) + { + printf( "Llb4_Nonlin4TransformCex(): There is no transition between state %d and %d.\n", i-1, i ); + Vec_IntFree( vAssumps ); + sat_solver_delete( pSat ); + Cnf_DataFree( pCnf ); + ABC_FREE( pCex ); + return NULL; + } + // get the assignment of PIs + Saig_ManForEachPi( pAig, pObj, k ) + if ( sat_solver_var_value(pSat, pCnf->pVarNums[Aig_ObjId(pObj)]) ) + Abc_InfoSetBit( pCex->pData, iBit + k ); + // update the counter + iBit += Saig_ManPiNum(pAig); + pThis = pNext; + } + + // add the last frame when the property fails + Vec_IntClear( vAssumps ); + if ( iCexPo >= 0 ) + { + Saig_ManForEachPo( pAig, pObj, k ) + if ( k == iCexPo ) + Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 ) ); + } + else + { + Saig_ManForEachPo( pAig, pObj, k ) + Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 ) ); + } + + // add clause + status = sat_solver_addclause( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps) ); + if ( status == 0 ) + { + printf( "Llb4_Nonlin4TransformCex(): The SAT solver is unsat after adding last clause.\n" ); + Vec_IntFree( vAssumps ); + sat_solver_delete( pSat ); + Cnf_DataFree( pCnf ); + ABC_FREE( pCex ); + return NULL; + } + // create assumptions + Vec_IntClear( vAssumps ); + Saig_ManForEachLo( pAig, pObj, k ) + Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Abc_InfoHasBit(pThis,k) ) ); + // solve the last frame + status = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), + (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + if ( status != l_True ) + { + printf( "Llb4_Nonlin4TransformCex(): There is no last transition that makes the property fail.\n" ); + Vec_IntFree( vAssumps ); + sat_solver_delete( pSat ); + Cnf_DataFree( pCnf ); + ABC_FREE( pCex ); + return NULL; + } + // get the assignment of PIs + Saig_ManForEachPi( pAig, pObj, k ) + if ( sat_solver_var_value(pSat, pCnf->pVarNums[Aig_ObjId(pObj)]) ) + Abc_InfoSetBit( pCex->pData, iBit + k ); + iBit += Saig_ManPiNum(pAig); + assert( iBit == pCex->nBits ); + + // free the sat_solver + Vec_IntFree( vAssumps ); + sat_solver_delete( pSat ); + Cnf_DataFree( pCnf ); + + // verify counter-example + status = Saig_ManFindFailedPoCex( pAig, pCex ); + if ( status >= 0 && status < Saig_ManPoNum(pAig) ) + pCex->iPo = status; + else + { + printf( "Llb4_Nonlin4TransformCex(): Counter-example verification has FAILED.\n" ); + ABC_FREE( pCex ); + return NULL; + } + // report the results +// if ( fVerbose ) +// Abc_PrintTime( 1, "SAT-based cex generation time", Abc_Clock() - clk ); + return pCex; +} + + +/**Function************************************************************* + + Synopsis [Resimulates the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb4_Nonlin4VerifyCex( Aig_Man_t * pAig, Abc_Cex_t * p ) +{ + Vec_Ptr_t * vStates; + Aig_Obj_t * pObj, * pObjRi, * pObjRo; + int i, k, iBit = 0; + // create storage for states + vStates = Vec_PtrAllocSimInfo( p->iFrame+1, Abc_BitWordNum(Aig_ManRegNum(pAig)) ); + Vec_PtrCleanSimInfo( vStates, 0, Abc_BitWordNum(Aig_ManRegNum(pAig)) ); + // verify counter-example + Aig_ManCleanMarkB(pAig); + Aig_ManConst1(pAig)->fMarkB = 1; + Saig_ManForEachLo( pAig, pObj, i ) + pObj->fMarkB = 0; //Abc_InfoHasBit(p->pData, iBit++); + // do not require equal flop count in the AIG and in the CEX + iBit = p->nRegs; + for ( i = 0; i <= p->iFrame; i++ ) + { + // save current state + Saig_ManForEachLo( pAig, pObj, k ) + if ( pObj->fMarkB ) + Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(vStates, i), k ); + // compute new state + Saig_ManForEachPi( pAig, pObj, k ) + pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++); + Aig_ManForEachNode( pAig, pObj, k ) + pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & + (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj)); + Aig_ManForEachCo( pAig, pObj, k ) + pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj); + if ( i == p->iFrame ) + break; + Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, k ) + pObjRo->fMarkB = pObjRi->fMarkB; + } +/* + { + unsigned * pNext; + Vec_PtrForEachEntry( unsigned *, vStates, pNext, i ) + { + printf( "%4d : ", i ); + Extra_PrintBinary( stdout, pNext, Aig_ManRegNum(pAig) ); + printf( "\n" ); + } + } +*/ + assert( iBit == p->nBits ); +// if ( Aig_ManCo(pAig, p->iPo)->fMarkB == 0 ) +// Vec_PtrFreeP( &vStates ); + for ( i = Saig_ManPoNum(pAig) - 1; i >= 0; i-- ) + { + if ( Aig_ManCo(pAig, i)->fMarkB ) + { + p->iPo = i; + break; + } + } + if ( i == -1 ) + Vec_PtrFreeP( &vStates ); + Aig_ManCleanMarkB(pAig); + return vStates; +} + +/**Function************************************************************* + + Synopsis [Translates a sequence of states into a counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Llb4_Nonlin4NormalizeCex( Aig_Man_t * pAigOrg, Aig_Man_t * pAigRpm, Abc_Cex_t * pCexRpm ) +{ + Abc_Cex_t * pCexOrg; + Vec_Ptr_t * vStates; + // check parameters of the AIG + if ( Saig_ManRegNum(pAigOrg) != Saig_ManRegNum(pAigRpm) ) + { + printf( "Llb4_Nonlin4NormalizeCex(): The number of flops in the original and reparametrized AIGs do not agree.\n" ); + return NULL; + } +/* + if ( Saig_ManRegNum(pAigRpm) != pCexRpm->nRegs ) + { + printf( "Llb4_Nonlin4NormalizeCex(): The number of flops in the reparametrized AIG and in the CEX do not agree.\n" ); + return NULL; + } +*/ + if ( Saig_ManPiNum(pAigRpm) != pCexRpm->nPis ) + { + printf( "Llb4_Nonlin4NormalizeCex(): The number of PIs in the reparametrized AIG and in the CEX do not agree.\n" ); + return NULL; + } + // get the sequence of states + vStates = Llb4_Nonlin4VerifyCex( pAigRpm, pCexRpm ); + if ( vStates == NULL ) + { + Abc_Print( 1, "Llb4_Nonlin4NormalizeCex(): The given CEX does not fail outputs of pAigRpm.\n" ); + return NULL; + } + // derive updated counter-example + pCexOrg = Llb4_Nonlin4TransformCex( pAigOrg, vStates, pCexRpm->iPo, 0 ); + Vec_PtrFree( vStates ); + return pCexOrg; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb4Cluster.c b/src/bdd/llb/llb4Cluster.c new file mode 100644 index 00000000..7e325597 --- /dev/null +++ b/src/bdd/llb/llb4Cluster.c @@ -0,0 +1,452 @@ +/**CFile**************************************************************** + + FileName [llb2Cluster.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Non-linear quantification scheduling.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Cluster.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Find good static variable ordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4FindOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter ) +{ + Aig_Obj_t * pFanin0, * pFanin1; + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return; + Aig_ObjSetTravIdCurrent( pAig, pObj ); + assert( Llb_ObjBddVar(vOrder, pObj) < 0 ); + if ( Aig_ObjIsCi(pObj) ) + { + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); + return; + } + // try fanins with higher level first + pFanin0 = Aig_ObjFanin0(pObj); + pFanin1 = Aig_ObjFanin1(pObj); +// if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) ) + if ( pFanin0->Level > pFanin1->Level ) + { + Llb_Nonlin4FindOrder_rec( pAig, pFanin0, vOrder, pCounter ); + Llb_Nonlin4FindOrder_rec( pAig, pFanin1, vOrder, pCounter ); + } + else + { + Llb_Nonlin4FindOrder_rec( pAig, pFanin1, vOrder, pCounter ); + Llb_Nonlin4FindOrder_rec( pAig, pFanin0, vOrder, pCounter ); + } + if ( pObj->fMarkA ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); +} + +/**Function************************************************************* + + Synopsis [Find good static variable ordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_Nonlin4FindOrder( Aig_Man_t * pAig, int * pCounter ) +{ + Vec_Int_t * vNodes = NULL; + Vec_Int_t * vOrder; + Aig_Obj_t * pObj; + int i, Counter = 0; + // mark nodes to exclude: AND with low level and CO drivers + Aig_ManCleanMarkA( pAig ); + Aig_ManForEachNode( pAig, pObj, i ) + if ( Aig_ObjLevel(pObj) > 3 ) + pObj->fMarkA = 1; + Aig_ManForEachCo( pAig, pObj, i ) + Aig_ObjFanin0(pObj)->fMarkA = 0; + + // collect nodes in the order + vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) ); + Aig_ManIncrementTravId( pAig ); + Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); +// Aig_ManForEachCo( pAig, pObj, i ) + Saig_ManForEachLi( pAig, pObj, i ) + { + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); + Llb_Nonlin4FindOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter ); + } + Aig_ManForEachCi( pAig, pObj, i ) + if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); + Aig_ManCleanMarkA( pAig ); + Vec_IntFreeP( &vNodes ); +// assert( Counter == Aig_ManObjNum(pAig) - 1 ); + +/* + Saig_ManForEachPi( pAig, pObj, i ) + printf( "pi%d ", Llb_ObjBddVar(vOrder, pObj) ); + printf( "\n" ); + Saig_ManForEachLo( pAig, pObj, i ) + printf( "lo%d ", Llb_ObjBddVar(vOrder, pObj) ); + printf( "\n" ); + Saig_ManForEachPo( pAig, pObj, i ) + printf( "po%d ", Llb_ObjBddVar(vOrder, pObj) ); + printf( "\n" ); + Saig_ManForEachLi( pAig, pObj, i ) + printf( "li%d ", Llb_ObjBddVar(vOrder, pObj) ); + printf( "\n" ); + Aig_ManForEachNode( pAig, pObj, i ) + printf( "n%d ", Llb_ObjBddVar(vOrder, pObj) ); + printf( "\n" ); +*/ + if ( pCounter ) + *pCounter = Counter; + return vOrder; +} + +/**Function************************************************************* + + Synopsis [Derives BDDs for the partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_Nonlin4FindPartitions_rec( DdManager * dd, Aig_Obj_t * pObj, Vec_Int_t * vOrder, Vec_Ptr_t * vRoots ) +{ + DdNode * bBdd, * bBdd0, * bBdd1, * bPart, * vVar; + if ( Aig_ObjIsConst1(pObj) ) + return Cudd_ReadOne(dd); + if ( Aig_ObjIsCi(pObj) ) + return Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + if ( pObj->pData ) + return (DdNode *)pObj->pData; + if ( Aig_ObjIsCo(pObj) ) + { + bBdd0 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) ); + bPart = Cudd_bddXnor( dd, Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ), bBdd0 ); Cudd_Ref( bPart ); + Vec_PtrPush( vRoots, bPart ); + return NULL; + } + bBdd0 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin1(pObj), vOrder, vRoots), Aig_ObjFaninC1(pObj) ); + bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bBdd ); + if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) + { + vVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + bPart = Cudd_bddXnor( dd, vVar, bBdd ); Cudd_Ref( bPart ); + Vec_PtrPush( vRoots, bPart ); + Cudd_RecursiveDeref( dd, bBdd ); + bBdd = vVar; Cudd_Ref( vVar ); + } + pObj->pData = bBdd; + return bBdd; +} + +/**Function************************************************************* + + Synopsis [Derives BDDs for the partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_Nonlin4FindPartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fOutputs ) +{ + Vec_Ptr_t * vRoots; + Aig_Obj_t * pObj; + int i; + Aig_ManCleanData( pAig ); + vRoots = Vec_PtrAlloc( 100 ); + if ( fOutputs ) + { + Saig_ManForEachPo( pAig, pObj, i ) + Llb_Nonlin4FindPartitions_rec( dd, pObj, vOrder, vRoots ); + } + else + { + Saig_ManForEachLi( pAig, pObj, i ) + Llb_Nonlin4FindPartitions_rec( dd, pObj, vOrder, vRoots ); + } + Aig_ManForEachNode( pAig, pObj, i ) + if ( pObj->pData ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + return vRoots; +} + +/**Function************************************************************* + + Synopsis [Creates quantifiable variables for both types of traversal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_Nonlin4FindVars2Q( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder ) +{ + Vec_Int_t * vVars2Q; + Aig_Obj_t * pObj; + int i; + vVars2Q = Vec_IntAlloc( 0 ); + Vec_IntFill( vVars2Q, Cudd_ReadSize(dd), 1 ); + Saig_ManForEachLo( pAig, pObj, i ) + Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 ); +// Aig_ManForEachCo( pAig, pObj, i ) + Saig_ManForEachLi( pAig, pObj, i ) + Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 ); + return vVars2Q; +} + +/**Function************************************************************* + + Synopsis [Creates quantifiable variables for both types of traversal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_Nonlin4CountTerms( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, DdNode * bFunc, int fCo, int fFlop ) +{ + DdNode * bSupp; + Aig_Obj_t * pObj; + int i, Counter = 0; + bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); + if ( !fCo && !fFlop ) + { + Saig_ManForEachPi( pAig, pObj, i ) + if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) + Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) ); + } + else if ( fCo && !fFlop ) + { + Saig_ManForEachPo( pAig, pObj, i ) + if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) + Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) ); + } + else if ( !fCo && fFlop ) + { + Saig_ManForEachLo( pAig, pObj, i ) + if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) + Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) ); + } + else if ( fCo && fFlop ) + { + Saig_ManForEachLi( pAig, pObj, i ) + if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) + Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) ); + } + Cudd_RecursiveDeref( dd, bSupp ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Creates quantifiable variables for both types of traversal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4PrintGroups( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups ) +{ + DdNode * bTemp; + int i, nSuppAll, nSuppPi, nSuppPo, nSuppLi, nSuppLo, nSuppAnd; + Vec_PtrForEachEntry( DdNode *, vGroups, bTemp, i ) + { +//Extra_bddPrintSupport(dd, bTemp); printf("\n" ); + nSuppAll = Cudd_SupportSize(dd,bTemp); + nSuppPi = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 0, 0); + nSuppPo = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 1, 0); + nSuppLi = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 0, 1); + nSuppLo = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 1, 1); + nSuppAnd = nSuppAll - (nSuppPi+nSuppPo+nSuppLi+nSuppLo); + + if ( Cudd_DagSize(bTemp) <= 10 ) + continue; + + printf( "%4d : bdd =%6d supp =%3d ", i, Cudd_DagSize(bTemp), nSuppAll ); + printf( "pi =%3d ", nSuppPi ); + printf( "po =%3d ", nSuppPo ); + printf( "lo =%3d ", nSuppLo ); + printf( "li =%3d ", nSuppLi ); + printf( "and =%3d", nSuppAnd ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Creates quantifiable variables for both types of traversal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4PrintSuppProfile( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups ) +{ + Aig_Obj_t * pObj; + int i, * pSupp; + int nSuppAll = 0, nSuppPi = 0, nSuppPo = 0, nSuppLi = 0, nSuppLo = 0, nSuppAnd = 0; + + pSupp = ABC_CALLOC( int, Cudd_ReadSize(dd) ); + Extra_VectorSupportArray( dd, (DdNode **)Vec_PtrArray(vGroups), Vec_PtrSize(vGroups), pSupp ); + + Aig_ManForEachObj( pAig, pObj, i ) + { + if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) + continue; + // remove variables that do not participate + if ( pSupp[Llb_ObjBddVar(vOrder, pObj)] == 0 ) + { + if ( Aig_ObjIsNode(pObj) ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), -1 ); + continue; + } + nSuppAll++; + if ( Saig_ObjIsPi(pAig, pObj) ) + nSuppPi++; + else if ( Saig_ObjIsLo(pAig, pObj) ) + nSuppLo++; + else if ( Saig_ObjIsPo(pAig, pObj) ) + nSuppPo++; + else if ( Saig_ObjIsLi(pAig, pObj) ) + nSuppLi++; + else + nSuppAnd++; + } + ABC_FREE( pSupp ); + + printf( "Groups =%3d ", Vec_PtrSize(vGroups) ); + printf( "Variables: all =%4d ", nSuppAll ); + printf( "pi =%4d ", nSuppPi ); + printf( "po =%4d ", nSuppPo ); + printf( "lo =%4d ", nSuppLo ); + printf( "li =%4d ", nSuppLi ); + printf( "and =%4d", nSuppAnd ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4Cluster( Aig_Man_t * pAig, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int nBddMax, int fVerbose ) +{ + DdManager * dd; + Vec_Int_t * vOrder, * vVars2Q; + Vec_Ptr_t * vParts, * vGroups; + DdNode * bTemp; + int i, nVarNum; + + // create the BDD manager + vOrder = Llb_Nonlin4FindOrder( pAig, &nVarNum ); + dd = Cudd_Init( nVarNum, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); +// Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + + vVars2Q = Llb_Nonlin4FindVars2Q( dd, pAig, vOrder ); + vParts = Llb_Nonlin4FindPartitions( dd, pAig, vOrder, 0 ); + + vGroups = Llb_Nonlin4Group( dd, vParts, vVars2Q, nBddMax ); + Vec_IntFree( vVars2Q ); + + Vec_PtrForEachEntry( DdNode *, vParts, bTemp, i ) + Cudd_RecursiveDeref( dd, bTemp ); + Vec_PtrFree( vParts ); + + +// if ( fVerbose ) + Llb_Nonlin4PrintSuppProfile( dd, pAig, vOrder, vGroups ); + if ( fVerbose ) + printf( "Before reordering\n" ); + if ( fVerbose ) + Llb_Nonlin4PrintGroups( dd, pAig, vOrder, vGroups ); + +// Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); +// printf( "After reordering\n" ); +// Llb_Nonlin4PrintGroups( dd, pAig, vOrder, vGroups ); + + if ( pvOrder ) + *pvOrder = vOrder; + else + Vec_IntFree( vOrder ); + + if ( pvGroups ) + *pvGroups = vGroups; + else + { + Vec_PtrForEachEntry( DdNode *, vGroups, bTemp, i ) + Cudd_RecursiveDeref( dd, bTemp ); + Vec_PtrFree( vGroups ); + } + + if ( pdd ) + *pdd = dd; + else + Extra_StopManager( dd ); +// Cudd_Quit( dd ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb4Image.c b/src/bdd/llb/llb4Image.c new file mode 100644 index 00000000..2ba4fcfd --- /dev/null +++ b/src/bdd/llb/llb4Image.c @@ -0,0 +1,863 @@ +/**CFile**************************************************************** + + FileName [llb3Image.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Computes image using partitioned structure.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb3Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Llb_Var_t_ Llb_Var_t; +struct Llb_Var_t_ +{ + int iVar; // variable number + int nScore; // variable score + Vec_Int_t * vParts; // partitions +}; + +typedef struct Llb_Prt_t_ Llb_Prt_t; +struct Llb_Prt_t_ +{ + int iPart; // partition number + int nSize; // the number of BDD nodes + DdNode * bFunc; // the partition + Vec_Int_t * vVars; // support +}; + +typedef struct Llb_Mgr_t_ Llb_Mgr_t; +struct Llb_Mgr_t_ +{ + DdManager * dd; // working BDD manager + Vec_Int_t * vVars2Q; // variables to quantify + int nSizeMax; // maximum size of the cluster + // internal + Llb_Prt_t ** pParts; // partitions + Llb_Var_t ** pVars; // variables + int iPartFree; // next free partition + int nVars; // the number of BDD variables + int nSuppMax; // maximum support size + // temporary + int * pSupp; // temporary support storage +}; + +static inline Llb_Var_t * Llb_MgrVar( Llb_Mgr_t * p, int i ) { return p->pVars[i]; } +static inline Llb_Prt_t * Llb_MgrPart( Llb_Mgr_t * p, int i ) { return p->pParts[i]; } + +// iterator over vars +#define Llb_MgrForEachVar( p, pVar, i ) \ + for ( i = 0; (i < p->nVars) && (((pVar) = Llb_MgrVar(p, i)), 1); i++ ) if ( pVar == NULL ) {} else +// iterator over parts +#define Llb_MgrForEachPart( p, pPart, i ) \ + for ( i = 0; (i < p->iPartFree) && (((pPart) = Llb_MgrPart(p, i)), 1); i++ ) if ( pPart == NULL ) {} else + +// iterator over vars of one partition +#define Llb_PartForEachVar( p, pPart, pVar, i ) \ + for ( i = 0; (i < Vec_IntSize(pPart->vVars)) && (((pVar) = Llb_MgrVar(p, Vec_IntEntry(pPart->vVars,i))), 1); i++ ) +// iterator over parts of one variable +#define Llb_VarForEachPart( p, pVar, pPart, i ) \ + for ( i = 0; (i < Vec_IntSize(pVar->vParts)) && (((pPart) = Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,i))), 1); i++ ) + +// statistics +//abctime timeBuild, timeAndEx, timeOther; +//int nSuppMax; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Removes one variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4RemoveVar( Llb_Mgr_t * p, Llb_Var_t * pVar ) +{ + assert( p->pVars[pVar->iVar] == pVar ); + p->pVars[pVar->iVar] = NULL; + Vec_IntFree( pVar->vParts ); + ABC_FREE( pVar ); +} + +/**Function************************************************************* + + Synopsis [Removes one partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4RemovePart( Llb_Mgr_t * p, Llb_Prt_t * pPart ) +{ +//printf( "Removing %d\n", pPart->iPart ); + assert( p->pParts[pPart->iPart] == pPart ); + p->pParts[pPart->iPart] = NULL; + Vec_IntFree( pPart->vVars ); + Cudd_RecursiveDeref( p->dd, pPart->bFunc ); + ABC_FREE( pPart ); +} + +/**Function************************************************************* + + Synopsis [Create cube with singleton variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_Nonlin4CreateCube1( Llb_Mgr_t * p, Llb_Prt_t * pPart ) +{ + DdNode * bCube, * bTemp; + Llb_Var_t * pVar; + int i; + abctime TimeStop; + TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; + bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube ); + Llb_PartForEachVar( p, pPart, pVar, i ) + { + assert( Vec_IntSize(pVar->vParts) > 0 ); + if ( Vec_IntSize(pVar->vParts) != 1 ) + continue; + assert( Vec_IntEntry(pVar->vParts, 0) == pPart->iPart ); + bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + Cudd_Deref( bCube ); + p->dd->TimeStop = TimeStop; + return bCube; +} + +/**Function************************************************************* + + Synopsis [Create cube of variables appearing only in two partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_Nonlin4CreateCube2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 ) +{ + DdNode * bCube, * bTemp; + Llb_Var_t * pVar; + int i; + abctime TimeStop; + TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; + bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube ); + Llb_PartForEachVar( p, pPart1, pVar, i ) + { + assert( Vec_IntSize(pVar->vParts) > 0 ); + if ( Vec_IntSize(pVar->vParts) != 2 ) + continue; + if ( (Vec_IntEntry(pVar->vParts, 0) == pPart1->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart2->iPart) || + (Vec_IntEntry(pVar->vParts, 0) == pPart2->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart1->iPart) ) + { + bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + } + Cudd_Deref( bCube ); + p->dd->TimeStop = TimeStop; + return bCube; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if partition has singleton variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_Nonlin4HasSingletonVars( Llb_Mgr_t * p, Llb_Prt_t * pPart ) +{ + Llb_Var_t * pVar; + int i; + Llb_PartForEachVar( p, pPart, pVar, i ) + if ( Vec_IntSize(pVar->vParts) == 1 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if partition has singleton variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4Print( Llb_Mgr_t * p ) +{ + Llb_Prt_t * pPart; + Llb_Var_t * pVar; + int i, k; + printf( "\n" ); + Llb_MgrForEachVar( p, pVar, i ) + { + printf( "Var %3d : ", i ); + Llb_VarForEachPart( p, pVar, pPart, k ) + printf( "%d ", pPart->iPart ); + printf( "\n" ); + } + Llb_MgrForEachPart( p, pPart, i ) + { + printf( "Part %3d : ", i ); + Llb_PartForEachVar( p, pPart, pVar, k ) + printf( "%d ", pVar->iVar ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Quantifies singles belonging to one partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_Nonlin4Quantify1( Llb_Mgr_t * p, Llb_Prt_t * pPart ) +{ + Llb_Var_t * pVar; + Llb_Prt_t * pTemp; + Vec_Ptr_t * vSingles; + DdNode * bCube, * bTemp; + int i, RetValue, nSizeNew; + // create cube to be quantified + bCube = Llb_Nonlin4CreateCube1( p, pPart ); Cudd_Ref( bCube ); +// assert( !Cudd_IsConstant(bCube) ); + // derive new function + pPart->bFunc = Cudd_bddExistAbstract( p->dd, bTemp = pPart->bFunc, bCube ); Cudd_Ref( pPart->bFunc ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bCube ); + // get support + vSingles = Vec_PtrAlloc( 0 ); + nSizeNew = Cudd_DagSize(pPart->bFunc); + Extra_SupportArray( p->dd, pPart->bFunc, p->pSupp ); + Llb_PartForEachVar( p, pPart, pVar, i ) + if ( p->pSupp[pVar->iVar] ) + { + assert( Vec_IntSize(pVar->vParts) > 1 ); + pVar->nScore -= pPart->nSize - nSizeNew; + } + else + { + RetValue = Vec_IntRemove( pVar->vParts, pPart->iPart ); + assert( RetValue ); + pVar->nScore -= pPart->nSize; + if ( Vec_IntSize(pVar->vParts) == 0 ) + Llb_Nonlin4RemoveVar( p, pVar ); + else if ( Vec_IntSize(pVar->vParts) == 1 ) + Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); + } + + // update partition + pPart->nSize = nSizeNew; + Vec_IntClear( pPart->vVars ); + for ( i = 0; i < p->nVars; i++ ) + if ( p->pSupp[i] && Vec_IntEntry(p->vVars2Q, i) ) + Vec_IntPush( pPart->vVars, i ); + // remove other variables + Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i ) + Llb_Nonlin4Quantify1( p, pTemp ); + Vec_PtrFree( vSingles ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Quantifies singles belonging to one partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_Nonlin4Quantify2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 ) +{ + int fVerbose = 0; + Llb_Var_t * pVar; + Llb_Prt_t * pTemp; + Vec_Ptr_t * vSingles; + DdNode * bCube, * bFunc; + int i, RetValue, nSuppSize; +// int iPart1 = pPart1->iPart; +// int iPart2 = pPart2->iPart; + int liveBeg, liveEnd; + + // create cube to be quantified + bCube = Llb_Nonlin4CreateCube2( p, pPart1, pPart2 ); Cudd_Ref( bCube ); + +//printf( "Quantifying " ); Extra_bddPrintSupport( p->dd, bCube ); printf( "\n" ); + +if ( fVerbose ) +{ +printf( "\n" ); +printf( "\n" ); +Llb_Nonlin4Print( p ); +printf( "Conjoining partitions %d and %d.\n", pPart1->iPart, pPart2->iPart ); +Extra_bddPrintSupport( p->dd, bCube ); printf( "\n" ); +} +liveBeg = p->dd->keys - p->dd->dead; + bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube ); +liveEnd = p->dd->keys - p->dd->dead; +//printf( "%d ", liveEnd-liveBeg ); + + if ( bFunc == NULL ) + { + Cudd_RecursiveDeref( p->dd, bCube ); + return 0; + } + Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( p->dd, bCube ); + +//printf( "Creating part %d ", p->iPartFree ); Extra_bddPrintSupport( p->dd, bFunc ); printf( "\n" ); + +//printf( "Creating %d\n", p->iPartFree ); + + // create new partition + pTemp = p->pParts[p->iPartFree] = ABC_CALLOC( Llb_Prt_t, 1 ); + pTemp->iPart = p->iPartFree++; + pTemp->nSize = Cudd_DagSize(bFunc); + pTemp->bFunc = bFunc; + pTemp->vVars = Vec_IntAlloc( 8 ); + // update variables + Llb_PartForEachVar( p, pPart1, pVar, i ) + { + RetValue = Vec_IntRemove( pVar->vParts, pPart1->iPart ); + assert( RetValue ); + pVar->nScore -= pPart1->nSize; + } + // update variables + Llb_PartForEachVar( p, pPart2, pVar, i ) + { + RetValue = Vec_IntRemove( pVar->vParts, pPart2->iPart ); + assert( RetValue ); + pVar->nScore -= pPart2->nSize; + } + // add variables to the new partition + nSuppSize = 0; + Extra_SupportArray( p->dd, bFunc, p->pSupp ); + for ( i = 0; i < p->nVars; i++ ) + { + nSuppSize += p->pSupp[i]; + if ( p->pSupp[i] && Vec_IntEntry(p->vVars2Q, i) ) + { + pVar = Llb_MgrVar( p, i ); + pVar->nScore += pTemp->nSize; + Vec_IntPush( pVar->vParts, pTemp->iPart ); + Vec_IntPush( pTemp->vVars, i ); + } + } + p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize ); + // remove variables and collect partitions with singleton variables + vSingles = Vec_PtrAlloc( 0 ); + Llb_PartForEachVar( p, pPart1, pVar, i ) + { + if ( Vec_IntSize(pVar->vParts) == 0 ) + Llb_Nonlin4RemoveVar( p, pVar ); + else if ( Vec_IntSize(pVar->vParts) == 1 ) + { + if ( fVerbose ) + printf( "Adding partition %d because of var %d.\n", + Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar ); + Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); + } + } + Llb_PartForEachVar( p, pPart2, pVar, i ) + { + if ( pVar == NULL ) + continue; + if ( Vec_IntSize(pVar->vParts) == 0 ) + Llb_Nonlin4RemoveVar( p, pVar ); + else if ( Vec_IntSize(pVar->vParts) == 1 ) + { + if ( fVerbose ) + printf( "Adding partition %d because of var %d.\n", + Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar ); + Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); + } + } + // remove partitions + Llb_Nonlin4RemovePart( p, pPart1 ); + Llb_Nonlin4RemovePart( p, pPart2 ); + // remove other variables +if ( fVerbose ) +Llb_Nonlin4Print( p ); + Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i ) + { +if ( fVerbose ) +printf( "Updating partitiong %d with singlton vars.\n", pTemp->iPart ); + Llb_Nonlin4Quantify1( p, pTemp ); + } +if ( fVerbose ) +Llb_Nonlin4Print( p ); + Vec_PtrFree( vSingles ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4CutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Saig_ObjIsLi(p, pObj) ) + { + Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); + return; + } + if ( Aig_ObjIsConst1(pObj) ) + return; + assert( Aig_ObjIsNode(pObj) ); + Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); + Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Computes volume of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_Nonlin4CutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + // mark the lower cut with the traversal ID + Aig_ManIncrementTravId(p); + Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // count the upper cut + vNodes = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) + Llb_Nonlin4CutNodes_rec( p, pObj, vNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Starts non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4AddPair( Llb_Mgr_t * p, int iPart, int iVar ) +{ + if ( p->pVars[iVar] == NULL ) + { + p->pVars[iVar] = ABC_CALLOC( Llb_Var_t, 1 ); + p->pVars[iVar]->iVar = iVar; + p->pVars[iVar]->nScore = 0; + p->pVars[iVar]->vParts = Vec_IntAlloc( 8 ); + } + Vec_IntPush( p->pVars[iVar]->vParts, iPart ); + Vec_IntPush( p->pParts[iPart]->vVars, iVar ); +} + +/**Function************************************************************* + + Synopsis [Starts non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4AddPartition( Llb_Mgr_t * p, int i, DdNode * bFunc ) +{ + int k, nSuppSize; + assert( !Cudd_IsConstant(bFunc) ); +//printf( "Creating init %d\n", i ); + // create partition + p->pParts[i] = ABC_CALLOC( Llb_Prt_t, 1 ); + p->pParts[i]->iPart = i; + p->pParts[i]->bFunc = bFunc; Cudd_Ref( bFunc ); + p->pParts[i]->vVars = Vec_IntAlloc( 8 ); + // add support dependencies + nSuppSize = 0; + Extra_SupportArray( p->dd, bFunc, p->pSupp ); + for ( k = 0; k < p->nVars; k++ ) + { + nSuppSize += p->pSupp[k]; + if ( p->pSupp[k] && Vec_IntEntry(p->vVars2Q, k) ) + Llb_Nonlin4AddPair( p, i, k ); + } + p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize ); +} + +/**Function************************************************************* + + Synopsis [Checks that each var appears in at least one partition.] + + Description [] + + SideEffects [] + + SeeAlso [] +**********************************************************************/ +void Llb_Nonlin4CheckVars( Llb_Mgr_t * p ) +{ + Llb_Var_t * pVar; + int i; + Llb_MgrForEachVar( p, pVar, i ) + assert( Vec_IntSize(pVar->vParts) > 1 ); +} + +/**Function************************************************************* + + Synopsis [Find next partition to quantify] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_Nonlin4NextPartitions( Llb_Mgr_t * p, Llb_Prt_t ** ppPart1, Llb_Prt_t ** ppPart2 ) +{ + Llb_Var_t * pVar, * pVarBest = NULL; + Llb_Prt_t * pPart, * pPart1Best = NULL, * pPart2Best = NULL; + int i; + Llb_Nonlin4CheckVars( p ); + // find variable with minimum score + Llb_MgrForEachVar( p, pVar, i ) + { + if ( p->nSizeMax && pVar->nScore > p->nSizeMax ) + continue; +// if ( pVarBest == NULL || Vec_IntSize(pVarBest->vParts) * pVarBest->nScore > Vec_IntSize(pVar->vParts) * pVar->nScore ) + if ( pVarBest == NULL || pVarBest->nScore > pVar->nScore ) + pVarBest = pVar; +// printf( "%d ", pVar->nScore ); + } +//printf( "\n" ); + if ( pVarBest == NULL ) + return 0; + // find two partitions with minimum size + Llb_VarForEachPart( p, pVarBest, pPart, i ) + { + if ( pPart1Best == NULL ) + pPart1Best = pPart; + else if ( pPart2Best == NULL ) + pPart2Best = pPart; + else if ( pPart1Best->nSize > pPart->nSize || pPart2Best->nSize > pPart->nSize ) + { + if ( pPart1Best->nSize > pPart2Best->nSize ) + pPart1Best = pPart; + else + pPart2Best = pPart; + } + } +//printf( "Selecting %d and parts %d and %d\n", pVarBest->iVar, pPart1Best->nSize, pPart2Best->nSize ); +//Extra_bddPrintSupport( p->dd, pPart1Best->bFunc ); printf( "\n" ); +//Extra_bddPrintSupport( p->dd, pPart2Best->bFunc ); printf( "\n" ); + + *ppPart1 = pPart1Best; + *ppPart2 = pPart2Best; + return 1; +} + +/**Function************************************************************* + + Synopsis [Recomputes scores after variable reordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4RecomputeScores( Llb_Mgr_t * p ) +{ + Llb_Prt_t * pPart; + Llb_Var_t * pVar; + int i, k; + Llb_MgrForEachPart( p, pPart, i ) + pPart->nSize = Cudd_DagSize(pPart->bFunc); + Llb_MgrForEachVar( p, pVar, i ) + { + pVar->nScore = 0; + Llb_VarForEachPart( p, pVar, pPart, k ) + pVar->nScore += pPart->nSize; + } +} + +/**Function************************************************************* + + Synopsis [Recomputes scores after variable reordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4VerifyScores( Llb_Mgr_t * p ) +{ + Llb_Prt_t * pPart; + Llb_Var_t * pVar; + int i, k, nScore; + Llb_MgrForEachPart( p, pPart, i ) + assert( pPart->nSize == Cudd_DagSize(pPart->bFunc) ); + Llb_MgrForEachVar( p, pVar, i ) + { + nScore = 0; + Llb_VarForEachPart( p, pVar, pPart, k ) + nScore += pPart->nSize; + assert( nScore == pVar->nScore ); + } +} + +/**Function************************************************************* + + Synopsis [Starts non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Mgr_t * Llb_Nonlin4Alloc( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q, int nSizeMax ) +{ + Llb_Mgr_t * p; + DdNode * bFunc; + int i; + p = ABC_CALLOC( Llb_Mgr_t, 1 ); + p->dd = dd; + p->nSizeMax = nSizeMax; + p->vVars2Q = vVars2Q; + p->nVars = Cudd_ReadSize(dd); + p->iPartFree = Vec_PtrSize(vParts); + p->pVars = ABC_CALLOC( Llb_Var_t *, p->nVars ); + p->pParts = ABC_CALLOC( Llb_Prt_t *, 2 * p->iPartFree + 2 ); + p->pSupp = ABC_ALLOC( int, Cudd_ReadSize(dd) ); + // add pairs (refs are consumed inside) + Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i ) + Llb_Nonlin4AddPartition( p, i, bFunc ); + // add partition + if ( bCurrent ) + Llb_Nonlin4AddPartition( p, p->iPartFree++, bCurrent ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops non-linear quantification scheduling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4Free( Llb_Mgr_t * p ) +{ + Llb_Prt_t * pPart; + Llb_Var_t * pVar; + int i; + Llb_MgrForEachVar( p, pVar, i ) + Llb_Nonlin4RemoveVar( p, pVar ); + Llb_MgrForEachPart( p, pPart, i ) + Llb_Nonlin4RemovePart( p, pPart ); + ABC_FREE( p->pVars ); + ABC_FREE( p->pParts ); + ABC_FREE( p->pSupp ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_Nonlin4Image( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q ) +{ + Llb_Prt_t * pPart, * pPart1, * pPart2; + Llb_Mgr_t * p; + DdNode * bFunc, * bTemp; + int i, nReorders; + // start the manager + p = Llb_Nonlin4Alloc( dd, vParts, bCurrent, vVars2Q, 0 ); + // remove singles + Llb_MgrForEachPart( p, pPart, i ) + if ( Llb_Nonlin4HasSingletonVars(p, pPart) ) + Llb_Nonlin4Quantify1( p, pPart ); + // compute scores + Llb_Nonlin4RecomputeScores( p ); + // iteratively quantify variables + while ( Llb_Nonlin4NextPartitions(p, &pPart1, &pPart2) ) + { + nReorders = Cudd_ReadReorderings(dd); + if ( !Llb_Nonlin4Quantify2( p, pPart1, pPart2 ) ) + { + Llb_Nonlin4Free( p ); + return NULL; + } + if ( nReorders < Cudd_ReadReorderings(dd) ) + Llb_Nonlin4RecomputeScores( p ); +// else +// Llb_Nonlin4VerifyScores( p ); + } + // load partitions + bFunc = Cudd_ReadOne(p->dd); Cudd_Ref( bFunc ); + Llb_MgrForEachPart( p, pPart, i ) + { + bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } +// nSuppMax = p->nSuppMax; + Llb_Nonlin4Free( p ); +//printf( "\n" ); + // return + Cudd_Deref( bFunc ); + return bFunc; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_Nonlin4Group( DdManager * dd, Vec_Ptr_t * vParts, Vec_Int_t * vVars2Q, int nSizeMax ) +{ + Vec_Ptr_t * vGroups; + Llb_Prt_t * pPart, * pPart1, * pPart2; + Llb_Mgr_t * p; + int i, nReorders;//, clk = Abc_Clock(); + // start the manager + p = Llb_Nonlin4Alloc( dd, vParts, NULL, vVars2Q, nSizeMax ); + // remove singles + Llb_MgrForEachPart( p, pPart, i ) + if ( Llb_Nonlin4HasSingletonVars(p, pPart) ) + Llb_Nonlin4Quantify1( p, pPart ); + // compute scores + Llb_Nonlin4RecomputeScores( p ); + // iteratively quantify variables + while ( Llb_Nonlin4NextPartitions(p, &pPart1, &pPart2) ) + { + nReorders = Cudd_ReadReorderings(dd); + if ( !Llb_Nonlin4Quantify2( p, pPart1, pPart2 ) ) + { + Llb_Nonlin4Free( p ); + return NULL; + } + if ( nReorders < Cudd_ReadReorderings(dd) ) + Llb_Nonlin4RecomputeScores( p ); +// else +// Llb_Nonlin4VerifyScores( p ); + } + // load partitions + vGroups = Vec_PtrAlloc( 1000 ); + Llb_MgrForEachPart( p, pPart, i ) + { +//printf( "Iteration %d ", pPart->iPart ); + if ( Cudd_IsConstant(pPart->bFunc) ) + { +//printf( "Constant\n" ); + assert( !Cudd_IsComplement(pPart->bFunc) ); + continue; + } +//printf( "\n" ); + Vec_PtrPush( vGroups, pPart->bFunc ); + Cudd_Ref( pPart->bFunc ); +//printf( "Part %d ", pPart->iPart ); +//Extra_bddPrintSupport( p->dd, pPart->bFunc ); printf( "\n" ); + } + Llb_Nonlin4Free( p ); +//Abc_PrintTime( 1, "Reparametrization time", Abc_Clock() - clk ); + return vGroups; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb4Map.c b/src/bdd/llb/llb4Map.c new file mode 100644 index 00000000..4487ce25 --- /dev/null +++ b/src/bdd/llb/llb4Map.c @@ -0,0 +1,123 @@ +/**CFile**************************************************************** + + FileName [llb2Map.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Non-linear quantification scheduling.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Map.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" +#include "base/abc/abc.h" +#include "map/if/if.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns internal nodes used in the mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_AigMap( Aig_Man_t * pAig, int nLutSize, int nLutMin ) +{ + extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); + extern If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); + extern void Gia_ManSetIfParsDefault( void * pPars ); + If_Par_t Pars, * pPars = &Pars; + If_Man_t * pIfMan; + If_Obj_t * pAnd; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode; + Vec_Int_t * vNodes; + Aig_Obj_t * pObj; + int i; + + // create ABC network + pNtk = Abc_NtkFromAigPhase( pAig ); + assert( Abc_NtkIsStrash(pNtk) ); + + // derive mapping parameters + Gia_ManSetIfParsDefault( pPars ); + pPars->nLutSize = nLutSize; + + // get timing information + pPars->pTimesArr = Abc_NtkGetCiArrivalFloats(pNtk); + pPars->pTimesReq = Abc_NtkGetCoRequiredFloats(pNtk); + + // perform LUT mapping + pIfMan = Abc_NtkToIf( pNtk, pPars ); + if ( pIfMan == NULL ) + { + Abc_NtkDelete( pNtk ); + return NULL; + } + if ( !If_ManPerformMapping( pIfMan ) ) + { + Abc_NtkDelete( pNtk ); + If_ManStop( pIfMan ); + return NULL; + } + + // mark nodes in the AIG used in the mapping + Aig_ManCleanMarkA( pAig ); + Aig_ManForEachNode( pAig, pObj, i ) + { + pNode = (Abc_Obj_t *)pObj->pData; + if ( pNode == NULL ) + continue; + pAnd = (If_Obj_t *)pNode->pCopy; + if ( pAnd == NULL ) + continue; + if ( pAnd->nRefs > 0 && (int)If_ObjCutBest(pAnd)->nLeaves >= nLutMin ) + pObj->fMarkA = 1; + } + Abc_NtkDelete( pNtk ); + If_ManStop( pIfMan ); + + // unmark flop drivers + Saig_ManForEachLi( pAig, pObj, i ) + Aig_ObjFanin0(pObj)->fMarkA = 0; + + // collect mapping + vNodes = Vec_IntAlloc( 100 ); + Aig_ManForEachNode( pAig, pObj, i ) + if ( pObj->fMarkA ) + Vec_IntPush( vNodes, Aig_ObjId(pObj) ); + Aig_ManCleanMarkA( pAig ); + return vNodes; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb4Nonlin.c b/src/bdd/llb/llb4Nonlin.c new file mode 100644 index 00000000..a9421358 --- /dev/null +++ b/src/bdd/llb/llb4Nonlin.c @@ -0,0 +1,1185 @@ +/**CFile**************************************************************** + + FileName [llb2Nonlin.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Non-linear quantification scheduling.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Nonlin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" +#include "base/abc/abc.h" +#include "aig/gia/giaAig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Llb_Mnx_t_ Llb_Mnx_t; +struct Llb_Mnx_t_ +{ + // user info + Aig_Man_t * pAig; // AIG manager + Gia_ParLlb_t * pPars; // parameters + + // intermediate BDDs + DdManager * dd; // BDD manager + DdNode * bBad; // bad states in terms of CIs + DdNode * bReached; // reached states + DdNode * bCurrent; // from states + DdNode * bNext; // to states + Vec_Ptr_t * vRings; // onion rings in ddR + Vec_Ptr_t * vRoots; // BDDs for partitions + + // structural info + Vec_Int_t * vOrder; // for each object ID, its BDD variable number or -1 + Vec_Int_t * vVars2Q; // 1 if variable is quantifiable; 0 othervise + + abctime timeImage; + abctime timeRemap; + abctime timeReo; + abctime timeOther; + abctime timeTotal; +}; + +//extern int timeBuild, timeAndEx, timeOther; +//extern int nSuppMax; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes bad in working manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_Nonlin4ComputeBad( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder ) +{ + Vec_Ptr_t * vNodes; + DdNode * bBdd, * bBdd0, * bBdd1, * bTemp, * bResult, * bCube; + Aig_Obj_t * pObj; + int i; + Aig_ManCleanData( pAig ); + // assign elementary variables + Aig_ManConst1(pAig)->pData = Cudd_ReadOne(dd); + Aig_ManForEachCi( pAig, pObj, i ) + pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + // compute internal nodes + vNodes = Aig_ManDfsNodes( pAig, (Aig_Obj_t **)Vec_PtrArray(pAig->vCos), Saig_ManPoNum(pAig) ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) ) + continue; + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); + bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); + if ( bBdd == NULL ) + { + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + if ( Aig_ObjIsNode(pObj) && pObj->pData != NULL ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + Vec_PtrFree( vNodes ); + return NULL; + } + Cudd_Ref( bBdd ); + pObj->pData = bBdd; + } + // quantify PIs of each PO + bResult = Cudd_ReadLogicZero( dd ); Cudd_Ref( bResult ); + Saig_ManForEachPo( pAig, pObj, i ) + { + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bResult = Cudd_bddOr( dd, bTemp = bResult, bBdd0 ); + if ( bResult == NULL ) + { + Cudd_RecursiveDeref( dd, bTemp ); + break; + } + Cudd_Ref( bResult ); + Cudd_RecursiveDeref( dd, bTemp ); + } + // deref + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + if ( Aig_ObjIsNode(pObj) && pObj->pData != NULL ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + Vec_PtrFree( vNodes ); + if ( bResult ) + { + bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube ); + Saig_ManForEachPi( pAig, pObj, i ) + { + bCube = Cudd_bddAnd( dd, bTemp = bCube, (DdNode *)pObj->pData ); + if ( bCube == NULL ) + { + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bResult ); + bResult = NULL; + break; + } + Cudd_Ref( bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + } + if ( bResult != NULL ) + { + bResult = Cudd_bddExistAbstract( dd, bTemp = bResult, bCube ); Cudd_Ref( bResult ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + Cudd_Deref( bResult ); + } + } +//if ( bResult ) +//printf( "Bad state = %d.\n", Cudd_DagSize(bResult) ); + return bResult; +} + +/**Function************************************************************* + + Synopsis [Derives BDDs for the partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_Nonlin4DerivePartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder ) +{ + Vec_Ptr_t * vRoots; + Aig_Obj_t * pObj; + DdNode * bBdd, * bBdd0, * bBdd1, * bPart; + int i; + Aig_ManCleanData( pAig ); + // assign elementary variables + Aig_ManConst1(pAig)->pData = Cudd_ReadOne(dd); + Aig_ManForEachCi( pAig, pObj, i ) + pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + Aig_ManForEachNode( pAig, pObj, i ) + if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) + { + pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + Cudd_Ref( (DdNode *)pObj->pData ); + } + Saig_ManForEachLi( pAig, pObj, i ) + pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + // compute intermediate BDDs + vRoots = Vec_PtrAlloc( 100 ); + Aig_ManForEachNode( pAig, pObj, i ) + { + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); + bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); + if ( bBdd == NULL ) + goto finish; + Cudd_Ref( bBdd ); + if ( pObj->pData == NULL ) + { + pObj->pData = bBdd; + continue; + } + // create new partition + bPart = Cudd_bddXnor( dd, (DdNode *)pObj->pData, bBdd ); + if ( bPart == NULL ) + goto finish; + Cudd_Ref( bPart ); + Cudd_RecursiveDeref( dd, bBdd ); + Vec_PtrPush( vRoots, bPart ); +//printf( "%d ", Cudd_DagSize(bPart) ); + } + // compute register output BDDs + Saig_ManForEachLi( pAig, pObj, i ) + { + bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bPart = Cudd_bddXnor( dd, (DdNode *)pObj->pData, bBdd0 ); + if ( bPart == NULL ) + goto finish; + Cudd_Ref( bPart ); + Vec_PtrPush( vRoots, bPart ); +//printf( "%d ", Cudd_DagSize(bPart) ); + } +//printf( "\n" ); + Aig_ManForEachNode( pAig, pObj, i ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + return vRoots; + // early termination +finish: + Aig_ManForEachNode( pAig, pObj, i ) + if ( pObj->pData ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + Vec_PtrForEachEntry( DdNode *, vRoots, bPart, i ) + Cudd_RecursiveDeref( dd, bPart ); + Vec_PtrFree( vRoots ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Find simple variable ordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_Nonlin4CreateOrderSimple( Aig_Man_t * pAig ) +{ + Vec_Int_t * vOrder; + Aig_Obj_t * pObj; + int i, Counter = 0; + vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) ); + Aig_ManForEachCi( pAig, pObj, i ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); + Saig_ManForEachLi( pAig, pObj, i ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); + return vOrder; +} + +/**Function************************************************************* + + Synopsis [Find good static variable ordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4CreateOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter ) +{ + Aig_Obj_t * pFanin0, * pFanin1; + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return; + Aig_ObjSetTravIdCurrent( pAig, pObj ); + assert( Llb_ObjBddVar(vOrder, pObj) < 0 ); + if ( Aig_ObjIsCi(pObj) ) + { +// if ( Saig_ObjIsLo(pAig, pObj) ) +// Vec_IntWriteEntry( vOrder, Aig_ObjId(Saig_ObjLoToLi(pAig, pObj)), (*pCounter)++ ); + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); + return; + } + // try fanins with higher level first + pFanin0 = Aig_ObjFanin0(pObj); + pFanin1 = Aig_ObjFanin1(pObj); +// if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) ) + if ( pFanin0->Level > pFanin1->Level ) + { + Llb_Nonlin4CreateOrder_rec( pAig, pFanin0, vOrder, pCounter ); + Llb_Nonlin4CreateOrder_rec( pAig, pFanin1, vOrder, pCounter ); + } + else + { + Llb_Nonlin4CreateOrder_rec( pAig, pFanin1, vOrder, pCounter ); + Llb_Nonlin4CreateOrder_rec( pAig, pFanin0, vOrder, pCounter ); + } + if ( pObj->fMarkA ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); +} + +/**Function************************************************************* + + Synopsis [Collect nodes with the given fanout count.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_Nonlin4CollectHighRefNodes( Aig_Man_t * pAig, int nFans ) +{ + Vec_Int_t * vNodes; + Aig_Obj_t * pObj; + int i; + Aig_ManCleanMarkA( pAig ); + Aig_ManForEachNode( pAig, pObj, i ) + if ( Aig_ObjRefs(pObj) >= nFans ) + pObj->fMarkA = 1; + // unmark flop drivers + Saig_ManForEachLi( pAig, pObj, i ) + Aig_ObjFanin0(pObj)->fMarkA = 0; + // collect mapping + vNodes = Vec_IntAlloc( 100 ); + Aig_ManForEachNode( pAig, pObj, i ) + if ( pObj->fMarkA ) + Vec_IntPush( vNodes, Aig_ObjId(pObj) ); + Aig_ManCleanMarkA( pAig ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Find good static variable ordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_Nonlin4CreateOrder( Aig_Man_t * pAig ) +{ + Vec_Int_t * vNodes = NULL; + Vec_Int_t * vOrder; + Aig_Obj_t * pObj; + int i, Counter = 0; +/* + // mark internal nodes to be used + Aig_ManCleanMarkA( pAig ); + vNodes = Llb_Nonlin4CollectHighRefNodes( pAig, 4 ); + Aig_ManForEachObjVec( vNodes, pAig, pObj, i ) + pObj->fMarkA = 1; +printf( "Techmapping added %d pivots.\n", Vec_IntSize(vNodes) ); +*/ + // collect nodes in the order + vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) ); + Aig_ManIncrementTravId( pAig ); + Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); + Saig_ManForEachLi( pAig, pObj, i ) + { + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); + Llb_Nonlin4CreateOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter ); + } + Aig_ManForEachCi( pAig, pObj, i ) + if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) + { +// if ( Saig_ObjIsLo(pAig, pObj) ) +// Vec_IntWriteEntry( vOrder, Aig_ObjId(Saig_ObjLoToLi(pAig, pObj)), Counter++ ); + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); + } + assert( Counter <= Aig_ManCiNum(pAig) + Aig_ManRegNum(pAig) + (vNodes?Vec_IntSize(vNodes):0) ); + Aig_ManCleanMarkA( pAig ); + Vec_IntFreeP( &vNodes ); + return vOrder; +} + + +/**Function************************************************************* + + Synopsis [Creates quantifiable varaibles for both types of traversal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_Nonlin4CreateVars2Q( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fBackward ) +{ + Vec_Int_t * vVars2Q; + Aig_Obj_t * pObjLi, * pObjLo; + int i; + vVars2Q = Vec_IntAlloc( 0 ); + Vec_IntFill( vVars2Q, Cudd_ReadSize(dd), 1 ); + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, fBackward ? pObjLo : pObjLi), 0 ); + return vVars2Q; +} + +/**Function************************************************************* + + Synopsis [Compute initial state in terms of current state variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4SetupVarMap( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder ) +{ + DdNode ** pVarsX, ** pVarsY; + Aig_Obj_t * pObjLo, * pObjLi; + int i; + pVarsX = ABC_ALLOC( DdNode *, Cudd_ReadSize(dd) ); + pVarsY = ABC_ALLOC( DdNode *, Cudd_ReadSize(dd) ); + Saig_ManForEachLiLo( pAig, pObjLo, pObjLi, i ) + { + assert( Llb_ObjBddVar(vOrder, pObjLo) >= 0 ); + assert( Llb_ObjBddVar(vOrder, pObjLi) >= 0 ); + pVarsX[i] = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLo) ); + pVarsY[i] = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLi) ); + } + Cudd_SetVarMap( dd, pVarsX, pVarsY, Aig_ManRegNum(pAig) ); + ABC_FREE( pVarsX ); + ABC_FREE( pVarsY ); +} + +/**Function************************************************************* + + Synopsis [Compute initial state in terms of current state variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_Nonlin4ComputeInitState( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fBackward ) +{ + Aig_Obj_t * pObjLi, * pObjLo; + DdNode * bRes, * bVar, * bTemp; + int i; + abctime TimeStop; + TimeStop = dd->TimeStop; dd->TimeStop = 0; + bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + { + bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, fBackward? pObjLi : pObjLo) ); + bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bRes ); + dd->TimeStop = TimeStop; + return bRes; +} + +/**Function************************************************************* + + Synopsis [Compute initial state in terms of current state variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_Nonlin4ComputeCube( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, char * pValues, int Flag ) +{ + Aig_Obj_t * pObjLo, * pObjLi, * pObjTemp; + DdNode * bRes, * bVar, * bTemp; + int i; + abctime TimeStop; + TimeStop = dd->TimeStop; dd->TimeStop = 0; + bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + { + if ( Flag ) + pObjTemp = pObjLo, pObjLo = pObjLi, pObjLi = pObjTemp; + // get the correspoding flop input variable + bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLi) ); + if ( pValues[Llb_ObjBddVar(vOrder, pObjLo)] != 1 ) + bVar = Cudd_Not(bVar); + // create cube + bRes = Cudd_bddAnd( dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bRes ); + dd->TimeStop = TimeStop; + return bRes; +} + +/**Function************************************************************* + + Synopsis [Compute initial state in terms of current state variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4RecordState( Aig_Man_t * pAig, Vec_Int_t * vOrder, unsigned * pState, char * pValues, int fBackward ) +{ + Aig_Obj_t * pObjLo, * pObjLi; + int i; + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + if ( pValues[Llb_ObjBddVar(vOrder, fBackward? pObjLi : pObjLo)] == 1 ) + Abc_InfoSetBit( pState, i ); +} + +/**Function************************************************************* + + Synopsis [Multiply every partition by the cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_Nonlin4Multiply( DdManager * dd, DdNode * bCube, Vec_Ptr_t * vParts ) +{ + Vec_Ptr_t * vNew; + DdNode * bTemp, * bFunc; + int i; + vNew = Vec_PtrAlloc( Vec_PtrSize(vParts) ); + Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i ) + { + bTemp = Cudd_bddAnd( dd, bFunc, bCube ); Cudd_Ref( bTemp ); + Vec_PtrPush( vNew, bTemp ); + } + return vNew; +} + +/**Function************************************************************* + + Synopsis [Multiply every partition by the cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4Deref( DdManager * dd, Vec_Ptr_t * vParts ) +{ + DdNode * bFunc; + int i; + Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i ) + Cudd_RecursiveDeref( dd, bFunc ); + Vec_PtrFree( vParts ); +} + +/**Function************************************************************* + + Synopsis [Derives counter-example by backward reachability.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_Nonlin4DeriveCex( Llb_Mnx_t * p, int fBackward, int fVerbose ) +{ + Vec_Int_t * vVars2Q; + Vec_Ptr_t * vStates, * vRootsNew; + Aig_Obj_t * pObj; + DdNode * bState = NULL, * bImage, * bOneCube, * bRing; + int i, v, RetValue;//, clk = Abc_Clock(); + char * pValues; + assert( Vec_PtrSize(p->vRings) > 0 ); + // disable the timeout + p->dd->TimeStop = 0; + + // start the state set + vStates = Vec_PtrAllocSimInfo( Vec_PtrSize(p->vRings), Abc_BitWordNum(Aig_ManRegNum(p->pAig)) ); + Vec_PtrCleanSimInfo( vStates, 0, Abc_BitWordNum(Aig_ManRegNum(p->pAig)) ); + if ( fBackward ) + Vec_PtrReverseOrder( vStates ); + + // get the last cube + pValues = ABC_ALLOC( char, Cudd_ReadSize(p->dd) ); + bOneCube = Cudd_bddIntersect( p->dd, (DdNode *)Vec_PtrEntryLast(p->vRings), p->bBad ); Cudd_Ref( bOneCube ); + RetValue = Cudd_bddPickOneCube( p->dd, bOneCube, pValues ); + Cudd_RecursiveDeref( p->dd, bOneCube ); + assert( RetValue ); + + // record the cube + Llb_Nonlin4RecordState( p->pAig, p->vOrder, (unsigned *)Vec_PtrEntryLast(vStates), pValues, fBackward ); + + // write state in terms of NS variables + if ( Vec_PtrSize(p->vRings) > 1 ) + { + bState = Llb_Nonlin4ComputeCube( p->dd, p->pAig, p->vOrder, pValues, fBackward ); Cudd_Ref( bState ); + } + // perform backward analysis + vVars2Q = Llb_Nonlin4CreateVars2Q( p->dd, p->pAig, p->vOrder, !fBackward ); + Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v ) + { + if ( v == Vec_PtrSize(p->vRings) - 1 ) + continue; + + // preprocess partitions + vRootsNew = Llb_Nonlin4Multiply( p->dd, bState, p->vRoots ); + Cudd_RecursiveDeref( p->dd, bState ); + + // compute the next states + bImage = Llb_Nonlin4Image( p->dd, vRootsNew, NULL, vVars2Q ); Cudd_Ref( bImage ); + Llb_Nonlin4Deref( p->dd, vRootsNew ); + + // intersect with the previous set + bOneCube = Cudd_bddIntersect( p->dd, bImage, bRing ); Cudd_Ref( bOneCube ); + Cudd_RecursiveDeref( p->dd, bImage ); + + // find any assignment of the BDD + RetValue = Cudd_bddPickOneCube( p->dd, bOneCube, pValues ); + Cudd_RecursiveDeref( p->dd, bOneCube ); + assert( RetValue ); + + // record the cube + Llb_Nonlin4RecordState( p->pAig, p->vOrder, (unsigned *)Vec_PtrEntry(vStates, v), pValues, fBackward ); + + // check that we get the init state + if ( v == 0 ) + { + Saig_ManForEachLo( p->pAig, pObj, i ) + assert( fBackward || pValues[Llb_ObjBddVar(p->vOrder, pObj)] == 0 ); + break; + } + + // write state in terms of NS variables + bState = Llb_Nonlin4ComputeCube( p->dd, p->pAig, p->vOrder, pValues, fBackward ); Cudd_Ref( bState ); + } + Vec_IntFree( vVars2Q ); + ABC_FREE( pValues ); + if ( fBackward ) + Vec_PtrReverseOrder( vStates ); +// if ( fVerbose ) +// Abc_PrintTime( 1, "BDD-based cex generation time", Abc_Clock() - clk ); + return vStates; +} + + +/**Function************************************************************* + + Synopsis [Perform reachability with hints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_Nonlin4Reachability( Llb_Mnx_t * p ) +{ + DdNode * bAux; + int nIters, nBddSizeFr = 0, nBddSizeTo = 0, nBddSizeTo2 = 0; + abctime clkTemp, clkIter, clk = Abc_Clock(); + assert( Aig_ManRegNum(p->pAig) > 0 ); + + if ( p->pPars->fBackward ) + { + // create bad state in the ring manager + if ( !p->pPars->fSkipOutCheck ) + { + p->bBad = Llb_Nonlin4ComputeInitState( p->dd, p->pAig, p->vOrder, p->pPars->fBackward ); Cudd_Ref( p->bBad ); + } + // create init state + if ( p->pPars->fCluster ) + p->bCurrent = p->dd->bFunc, p->dd->bFunc = NULL; + else + { + p->bCurrent = Llb_Nonlin4ComputeBad( p->dd, p->pAig, p->vOrder ); + if ( p->bCurrent == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + Cudd_Ref( p->bCurrent ); + } + // remap into the next states + p->bCurrent = Cudd_bddVarMap( p->dd, bAux = p->bCurrent ); + if ( p->bCurrent == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during remapping bad states.\n", p->pPars->TimeLimit ); + Cudd_RecursiveDeref( p->dd, bAux ); + p->pPars->iFrame = -1; + return -1; + } + Cudd_Ref( p->bCurrent ); + Cudd_RecursiveDeref( p->dd, bAux ); + } + else + { + // create bad state in the ring manager + if ( !p->pPars->fSkipOutCheck ) + { + if ( p->pPars->fCluster ) + p->bBad = p->dd->bFunc, p->dd->bFunc = NULL; + else + { + p->bBad = Llb_Nonlin4ComputeBad( p->dd, p->pAig, p->vOrder ); + if ( p->bBad == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = -1; + return -1; + } + Cudd_Ref( p->bBad ); + } + } + else if ( p->dd->bFunc ) + Cudd_RecursiveDeref( p->dd, p->dd->bFunc ), p->dd->bFunc = NULL; + // compute the starting set of states + p->bCurrent = Llb_Nonlin4ComputeInitState( p->dd, p->pAig, p->vOrder, p->pPars->fBackward ); Cudd_Ref( p->bCurrent ); + } + // perform iterations + p->bReached = p->bCurrent; Cudd_Ref( p->bReached ); + for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ ) + { + clkIter = Abc_Clock(); + // check the runtime limit + if ( p->pPars->TimeLimit && Abc_Clock() > p->pPars->TimeTarget ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + return -1; + } + + // save the onion ring + Vec_PtrPush( p->vRings, p->bCurrent ); Cudd_Ref( p->bCurrent ); + + // check it for bad states + if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->dd, p->bCurrent, Cudd_Not(p->bBad) ) ) + { + Vec_Ptr_t * vStates; + assert( p->pAig->pSeqModel == NULL ); + vStates = Llb_Nonlin4DeriveCex( p, p->pPars->fBackward, p->pPars->fVerbose ); + p->pAig->pSeqModel = Llb4_Nonlin4TransformCex( p->pAig, vStates, -1, p->pPars->fVerbose ); + Vec_PtrFreeP( &vStates ); + if ( !p->pPars->fSilent ) + { + Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", p->pAig->pSeqModel->iPo, p->pAig->pName, nIters ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + p->pPars->iFrame = nIters - 1; + return 0; + } + + // compute the next states + clkTemp = Abc_Clock(); + p->bNext = Llb_Nonlin4Image( p->dd, p->vRoots, p->bCurrent, p->vVars2Q ); + if ( p->bNext == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in quantification.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + return -1; + } + Cudd_Ref( p->bNext ); + p->timeImage += Abc_Clock() - clkTemp; + + // remap into current states + clkTemp = Abc_Clock(); + p->bNext = Cudd_bddVarMap( p->dd, bAux = p->bNext ); + if ( p->bNext == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during remapping next states.\n", p->pPars->TimeLimit ); + Cudd_RecursiveDeref( p->dd, bAux ); + p->pPars->iFrame = nIters - 1; + return -1; + } + Cudd_Ref( p->bNext ); + Cudd_RecursiveDeref( p->dd, bAux ); + p->timeRemap += Abc_Clock() - clkTemp; + + // collect statistics + if ( p->pPars->fVerbose ) + { + nBddSizeFr = Cudd_DagSize( p->bCurrent ); + nBddSizeTo = Cudd_DagSize( bAux ); + nBddSizeTo2 = Cudd_DagSize( p->bNext ); + } + Cudd_RecursiveDeref( p->dd, p->bCurrent ); p->bCurrent = NULL; + + // derive new states + p->bCurrent = Cudd_bddAnd( p->dd, p->bNext, Cudd_Not(p->bReached) ); + if ( p->bCurrent == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + return -1; + } + Cudd_Ref( p->bCurrent ); + Cudd_RecursiveDeref( p->dd, p->bNext ); p->bNext = NULL; + if ( Cudd_IsConstant(p->bCurrent) ) + break; +/* + // reduce BDD size using constrain // Cudd_bddRestrict + p->bCurrent = Cudd_bddRestrict( p->dd, bAux = p->bCurrent, Cudd_Not(p->bReached) ); + Cudd_Ref( p->bCurrent ); +printf( "Before = %d. After = %d.\n", Cudd_DagSize(bAux), Cudd_DagSize(p->bCurrent) ); + Cudd_RecursiveDeref( p->dd, bAux ); +*/ + + // add to the reached set + p->bReached = Cudd_bddOr( p->dd, bAux = p->bReached, p->bCurrent ); + if ( p->bReached == NULL ) + { + if ( !p->pPars->fSilent ) + printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); + p->pPars->iFrame = nIters - 1; + Cudd_RecursiveDeref( p->dd, bAux ); + return -1; + } + Cudd_Ref( p->bReached ); + Cudd_RecursiveDeref( p->dd, bAux ); + + + // report the results + if ( p->pPars->fVerbose ) + { + printf( "I =%5d : ", nIters ); + printf( "Fr =%7d ", nBddSizeFr ); + printf( "ImNs =%7d ", nBddSizeTo ); + printf( "ImCs =%7d ", nBddSizeTo2 ); + printf( "Rea =%7d ", Cudd_DagSize(p->bReached) ); + printf( "(%4d %4d) ", Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) ); + Abc_PrintTime( 1, "T", Abc_Clock() - clkIter ); + } +/* + if ( pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(p->dd, bReached, Saig_ManRegNum(p->pAig) ); +// Extra_bddPrint( p->dd, bReached );printf( "\n" ); + printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); + fflush( stdout ); + } +*/ + if ( nIters == p->pPars->nIterMax - 1 ) + { + if ( !p->pPars->fSilent ) + printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nIterMax ); + p->pPars->iFrame = nIters; + return -1; + } + } + + // report the stats + if ( p->pPars->fVerbose ) + { + double nMints = Cudd_CountMinterm(p->dd, p->bReached, Saig_ManRegNum(p->pAig) ); + if ( p->bCurrent && Cudd_IsConstant(p->bCurrent) ) + printf( "Reachability analysis completed after %d frames.\n", nIters ); + else + printf( "Reachability analysis is stopped after %d frames.\n", nIters ); + printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); + fflush( stdout ); + } + if ( p->bCurrent == NULL || !Cudd_IsConstant(p->bCurrent) ) + { + if ( !p->pPars->fSilent ) + printf( "Verified only for states reachable in %d frames. ", nIters ); + p->pPars->iFrame = p->pPars->nIterMax; + return -1; // undecided + } + // report + if ( !p->pPars->fSilent ) + printf( "The miter is proved unreachable after %d iterations. ", nIters ); + if ( !p->pPars->fSilent ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + p->pPars->iFrame = nIters - 1; + return 1; // unreachable +} + +/**Function************************************************************* + + Synopsis [Reorders BDDs in the working manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4Reorder( DdManager * dd, int fTwice, int fVerbose ) +{ + abctime clk = Abc_Clock(); + if ( fVerbose ) + Abc_Print( 1, "Reordering... Before =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + if ( fVerbose ) + Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + if ( fTwice ) + { + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + if ( fVerbose ) + Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + } + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Llb_Mnx_t * Llb_MnxStart( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) +{ + Llb_Mnx_t * p; + + p = ABC_CALLOC( Llb_Mnx_t, 1 ); + p->pAig = pAig; + p->pPars = pPars; + + // compute time to stop + p->pPars->TimeTarget = p->pPars->TimeLimit ? p->pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0; + + if ( pPars->fCluster ) + { +// Llb_Nonlin4Cluster( p->pAig, &p->dd, &p->vOrder, &p->vRoots, pPars->nBddMax, pPars->fVerbose ); +// Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); + Llb4_Nonlin4Sweep( p->pAig, pPars->nBddMax, pPars->nClusterMax, &p->dd, &p->vOrder, &p->vRoots, pPars->fVerbose ); + // set the stop time parameter + p->dd->TimeStop = p->pPars->TimeTarget; + } + else + { +// p->vOrder = Llb_Nonlin4CreateOrderSimple( pAig ); + p->vOrder = Llb_Nonlin4CreateOrder( pAig ); + p->dd = Cudd_Init( Vec_IntCountPositive(p->vOrder) + 1, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); + Cudd_SetMaxGrowth( p->dd, 1.05 ); + // set the stop time parameter + p->dd->TimeStop = p->pPars->TimeTarget; + p->vRoots = Llb_Nonlin4DerivePartitions( p->dd, pAig, p->vOrder ); + } + + Llb_Nonlin4SetupVarMap( p->dd, pAig, p->vOrder ); + p->vVars2Q = Llb_Nonlin4CreateVars2Q( p->dd, pAig, p->vOrder, p->pPars->fBackward ); + p->vRings = Vec_PtrAlloc( 100 ); + + if ( pPars->fReorder ) + Llb_Nonlin4Reorder( p->dd, 0, 1 ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MnxStop( Llb_Mnx_t * p ) +{ + DdNode * bTemp; + int i; + if ( p->pPars->fVerbose ) + { + p->timeReo = Cudd_ReadReorderingTime(p->dd); + p->timeOther = p->timeTotal - p->timeImage - p->timeRemap; + ABC_PRTP( "Image ", p->timeImage, p->timeTotal ); + ABC_PRTP( "Remap ", p->timeRemap, p->timeTotal ); + ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); + ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); + ABC_PRTP( " reo ", p->timeReo, p->timeTotal ); + } + // remove BDDs + if ( p->bBad ) + Cudd_RecursiveDeref( p->dd, p->bBad ); + if ( p->bReached ) + Cudd_RecursiveDeref( p->dd, p->bReached ); + if ( p->bCurrent ) + Cudd_RecursiveDeref( p->dd, p->bCurrent ); + if ( p->bNext ) + Cudd_RecursiveDeref( p->dd, p->bNext ); + if ( p->vRings ) + Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i ) + Cudd_RecursiveDeref( p->dd, bTemp ); + if ( p->vRoots ) + Vec_PtrForEachEntry( DdNode *, p->vRoots, bTemp, i ) + Cudd_RecursiveDeref( p->dd, bTemp ); + // remove arrays + Vec_PtrFreeP( &p->vRings ); + Vec_PtrFreeP( &p->vRoots ); +//Cudd_PrintInfo( p->dd, stdout ); + Extra_StopManager( p->dd ); + Vec_IntFreeP( &p->vOrder ); + Vec_IntFreeP( &p->vVars2Q ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_MnxCheckNextStateVars( Llb_Mnx_t * p ) +{ + Aig_Obj_t * pObj; + int i, Counter0 = 0, Counter1 = 0; + Saig_ManForEachLi( p->pAig, pObj, i ) + if ( Saig_ObjIsLo(p->pAig, Aig_ObjFanin0(pObj)) ) + { + if ( Aig_ObjFaninC0(pObj) ) + Counter0++; + else + Counter1++; + } + printf( "Total = %d. Direct LO = %d. Compl LO = %d.\n", Aig_ManRegNum(p->pAig), Counter1, Counter0 ); +} + +/**Function************************************************************* + + Synopsis [Finds balanced cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) +{ + Llb_Mnx_t * pMnn; + int RetValue = -1; + if ( pPars->fVerbose ) + Aig_ManPrintStats( pAig ); + if ( pPars->fCluster && Aig_ManObjNum(pAig) >= (1 << 15) ) + { + printf( "The number of objects is more than 2^15. Clustering cannot be used.\n" ); + return RetValue; + } + { + abctime clk = Abc_Clock(); + pMnn = Llb_MnxStart( pAig, pPars ); +//Llb_MnxCheckNextStateVars( pMnn ); + if ( !pPars->fSkipReach ) + RetValue = Llb_Nonlin4Reachability( pMnn ); + pMnn->timeTotal = Abc_Clock() - clk; + Llb_MnxStop( pMnn ); + } + return RetValue; +} + + +/**Function************************************************************* + + Synopsis [Takes an AIG and returns an AIG representing reachable states.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Llb_ReachableStates( Aig_Man_t * pAig ) +{ + extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); + Vec_Int_t * vPermute; + Vec_Ptr_t * vNames; + Gia_ParLlb_t Pars, * pPars = &Pars; + DdManager * dd; + DdNode * bReached; + Llb_Mnx_t * pMnn; + Abc_Ntk_t * pNtk, * pNtkMuxes; + Aig_Obj_t * pObj; + int i, RetValue; + abctime clk = Abc_Clock(); + + // create parameters + Llb_ManSetDefaultParams( pPars ); + pPars->fSkipOutCheck = 1; + pPars->fCluster = 0; + pPars->fReorder = 0; + pPars->fSilent = 1; + pPars->nBddMax = 100; + pPars->nClusterMax = 500; + + // run reachability + pMnn = Llb_MnxStart( pAig, pPars ); + RetValue = Llb_Nonlin4Reachability( pMnn ); + assert( RetValue == 1 ); + + // print BDD +// Extra_bddPrint( pMnn->dd, pMnn->bReached ); +// Extra_bddPrintSupport( pMnn->dd, pMnn->bReached ); +// printf( "\n" ); + + // collect flop output variables + vPermute = Vec_IntStartFull( Cudd_ReadSize(pMnn->dd) ); + Saig_ManForEachLo( pAig, pObj, i ) + Vec_IntWriteEntry( vPermute, Llb_ObjBddVar(pMnn->vOrder, pObj), i ); + + // transfer the reached state BDD into the new manager + dd = Cudd_Init( Saig_ManRegNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + bReached = Extra_TransferPermute( pMnn->dd, dd, pMnn->bReached, Vec_IntArray(vPermute) ); Cudd_Ref( bReached ); + Vec_IntFree( vPermute ); + assert( Cudd_ReadSize(dd) == Saig_ManRegNum(pAig) ); + + // quit reachability engine + pMnn->timeTotal = Abc_Clock() - clk; + Llb_MnxStop( pMnn ); + + // derive the network + vNames = Abc_NodeGetFakeNames( Saig_ManRegNum(pAig) ); + pNtk = Abc_NtkDeriveFromBdd( dd, bReached, "reached", vNames ); + Abc_NodeFreeNames( vNames ); + Cudd_RecursiveDeref( dd, bReached ); + Cudd_Quit( dd ); + + // convert + pNtkMuxes = Abc_NtkBddToMuxes( pNtk ); + Abc_NtkDelete( pNtk ); + pNtk = Abc_NtkStrash( pNtkMuxes, 0, 1, 0 ); + Abc_NtkDelete( pNtkMuxes ); + pAig = Abc_NtkToDar( pNtk, 0, 0 ); + Abc_NtkDelete( pNtk ); + return pAig; +} +Gia_Man_t * Llb_ReachableStatesGia( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Aig_Man_t * pAig, * pReached; + pAig = Gia_ManToAigSimple( p ); + pReached = Llb_ReachableStates( pAig ); + Aig_ManStop( pAig ); + pNew = Gia_ManFromAigSimple( pReached ); + Aig_ManStop( pReached ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llb4Sweep.c b/src/bdd/llb/llb4Sweep.c new file mode 100644 index 00000000..6b318572 --- /dev/null +++ b/src/bdd/llb/llb4Sweep.c @@ -0,0 +1,589 @@ +/**CFile**************************************************************** + + FileName [llb2Sweep.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD based reachability.] + + Synopsis [Non-linear quantification scheduling.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: llb2Sweep.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "llbInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Find good static variable ordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4SweepOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter, int fSaveAll ) +{ + Aig_Obj_t * pFanin0, * pFanin1; + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return; + Aig_ObjSetTravIdCurrent( pAig, pObj ); + assert( Llb_ObjBddVar(vOrder, pObj) < 0 ); + if ( Aig_ObjIsCi(pObj) ) + { + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); + return; + } + // try fanins with higher level first + pFanin0 = Aig_ObjFanin0(pObj); + pFanin1 = Aig_ObjFanin1(pObj); +// if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) ) + if ( pFanin0->Level > pFanin1->Level ) + { + Llb_Nonlin4SweepOrder_rec( pAig, pFanin0, vOrder, pCounter, fSaveAll ); + Llb_Nonlin4SweepOrder_rec( pAig, pFanin1, vOrder, pCounter, fSaveAll ); + } + else + { + Llb_Nonlin4SweepOrder_rec( pAig, pFanin1, vOrder, pCounter, fSaveAll ); + Llb_Nonlin4SweepOrder_rec( pAig, pFanin0, vOrder, pCounter, fSaveAll ); + } + if ( fSaveAll || pObj->fMarkA ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); +} + +/**Function************************************************************* + + Synopsis [Find good static variable ordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_Nonlin4SweepOrder( Aig_Man_t * pAig, int * pCounter, int fSaveAll ) +{ + Vec_Int_t * vOrder; + Aig_Obj_t * pObj; + int i, Counter = 0; + // collect nodes in the order + vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) ); + Aig_ManIncrementTravId( pAig ); + Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); + Aig_ManForEachCo( pAig, pObj, i ) + { + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); + Llb_Nonlin4SweepOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter, fSaveAll ); + } + Aig_ManForEachCi( pAig, pObj, i ) + if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); +// assert( Counter == Aig_ManObjNum(pAig) - 1 ); // no dangling nodes + if ( pCounter ) + *pCounter = Counter - Aig_ManCiNum(pAig) - Aig_ManCoNum(pAig); + return vOrder; +} + + +/**Function************************************************************* + + Synopsis [Performs BDD sweep on the netlist.] + + Description [Returns AIG with internal cut points labeled with fMarkA.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Llb4_Nonlin4SweepCutpoints( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nBddLimit, int fVerbose ) +{ + DdManager * dd; + DdNode * bFunc0, * bFunc1, * bFunc; + Aig_Obj_t * pObj; + int i, Counter = 0, Counter1 = 0; + dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + // assign elementary variables + Aig_ManCleanData( pAig ); + Aig_ManForEachCi( pAig, pObj, i ) + pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + // sweep internal nodes + Aig_ManForEachNode( pAig, pObj, i ) + { +/* + if ( pObj->nRefs >= 4 ) + { + bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); Cudd_Ref( bFunc ); + pObj->pData = bFunc; + Counter1++; + continue; + } +*/ + bFunc0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bFunc1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); + bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); + if ( Cudd_DagSize(bFunc) > nBddLimit ) + { +// if ( fVerbose ) +// printf( "Node %5d : Beg =%5d. ", i, Cudd_DagSize(bFunc) ); + + // add cutpoint at a larger one + Cudd_RecursiveDeref( dd, bFunc ); + if ( Cudd_DagSize(bFunc0) >= Cudd_DagSize(bFunc1) ) + { + Cudd_RecursiveDeref( dd, (DdNode *)Aig_ObjFanin0(pObj)->pData ); + bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, Aig_ObjFanin0(pObj)) ); + Aig_ObjFanin0(pObj)->pData = bFunc; Cudd_Ref( bFunc ); + Aig_ObjFanin0(pObj)->fMarkA = 1; + +// if ( fVerbose ) +// printf( "Ref =%3d ", Aig_ObjFanin0(pObj)->nRefs ); + } + else + { + Cudd_RecursiveDeref( dd, (DdNode *)Aig_ObjFanin1(pObj)->pData ); + bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, Aig_ObjFanin1(pObj)) ); + Aig_ObjFanin1(pObj)->pData = bFunc; Cudd_Ref( bFunc ); + Aig_ObjFanin1(pObj)->fMarkA = 1; + +// if ( fVerbose ) +// printf( "Ref =%3d ", Aig_ObjFanin1(pObj)->nRefs ); + } + // perform new operation + bFunc0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + bFunc1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); + bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); +// assert( Cudd_DagSize(bFunc) <= nBddLimit ); + +// if ( fVerbose ) +// printf( "End =%5d.\n", Cudd_DagSize(bFunc) ); + Counter++; + } + pObj->pData = bFunc; +//printf( "%d ", Cudd_DagSize(bFunc) ); + } +//printf( "\n" ); + // clean up + Aig_ManForEachNode( pAig, pObj, i ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + Extra_StopManager( dd ); +// Aig_ManCleanMarkA( pAig ); + if ( fVerbose ) + printf( "Added %d cut points. Used %d high fanout points.\n", Counter, Counter1 ); + return Counter + Counter1; +} + +/**Function************************************************************* + + Synopsis [Derives BDDs for the partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb_Nonlin4SweepPartitions_rec( DdManager * dd, Aig_Obj_t * pObj, Vec_Int_t * vOrder, Vec_Ptr_t * vRoots ) +{ + DdNode * bBdd, * bBdd0, * bBdd1, * bPart, * vVar; + if ( Aig_ObjIsConst1(pObj) ) + return Cudd_ReadOne(dd); + if ( Aig_ObjIsCi(pObj) ) + return Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + if ( pObj->pData ) + return (DdNode *)pObj->pData; + if ( Aig_ObjIsCo(pObj) ) + { + bBdd0 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) ); + bPart = Cudd_bddXnor( dd, Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ), bBdd0 ); Cudd_Ref( bPart ); + Vec_PtrPush( vRoots, bPart ); + return NULL; + } + bBdd0 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin1(pObj), vOrder, vRoots), Aig_ObjFaninC1(pObj) ); + bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bBdd ); + if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) + { + vVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + bPart = Cudd_bddXnor( dd, vVar, bBdd ); Cudd_Ref( bPart ); + Vec_PtrPush( vRoots, bPart ); + Cudd_RecursiveDeref( dd, bBdd ); + bBdd = vVar; Cudd_Ref( vVar ); + } + pObj->pData = bBdd; + return bBdd; +} + +/**Function************************************************************* + + Synopsis [Derives BDDs for the partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Llb_Nonlin4SweepPartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fTransition ) +{ + Vec_Ptr_t * vRoots; + Aig_Obj_t * pObj; + int i; + Aig_ManCleanData( pAig ); + vRoots = Vec_PtrAlloc( 100 ); + if ( fTransition ) + { + Saig_ManForEachLi( pAig, pObj, i ) + Llb_Nonlin4SweepPartitions_rec( dd, pObj, vOrder, vRoots ); + } + else + { + Saig_ManForEachPo( pAig, pObj, i ) + Llb_Nonlin4SweepPartitions_rec( dd, pObj, vOrder, vRoots ); + } + Aig_ManForEachNode( pAig, pObj, i ) + if ( pObj->pData ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + return vRoots; +} + +/**Function************************************************************* + + Synopsis [Get bad state monitor.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Llb4_Nonlin4SweepBadMonitor( Aig_Man_t * pAig, Vec_Int_t * vOrder, DdManager * dd ) +{ + Aig_Obj_t * pObj; + DdNode * bRes, * bVar, * bTemp; + int i; + abctime TimeStop; + TimeStop = dd->TimeStop; dd->TimeStop = 0; + bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); + Saig_ManForEachPo( pAig, pObj, i ) + { + bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); + bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bRes ); + dd->TimeStop = TimeStop; + return Cudd_Not(bRes); +} + +/**Function************************************************************* + + Synopsis [Creates quantifiable variables for both types of traversal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Llb_Nonlin4SweepVars2Q( Aig_Man_t * pAig, Vec_Int_t * vOrder, int fAddLis ) +{ + Vec_Int_t * vVars2Q; + Aig_Obj_t * pObj; + int i; + vVars2Q = Vec_IntAlloc( 0 ); + Vec_IntFill( vVars2Q, Aig_ManObjNumMax(pAig), 1 ); + // add flop outputs + Saig_ManForEachLo( pAig, pObj, i ) + Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 ); + // add flop inputs + if ( fAddLis ) + Saig_ManForEachLi( pAig, pObj, i ) + Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 ); + return vVars2Q; +} + +/**Function************************************************************* + + Synopsis [Multiply every partition by the cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4SweepDeref( DdManager * dd, Vec_Ptr_t * vParts ) +{ + DdNode * bFunc; + int i; + Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i ) + Cudd_RecursiveDeref( dd, bFunc ); + Vec_PtrFree( vParts ); +} + +/**Function************************************************************* + + Synopsis [Multiply every partition by the cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4SweepPrint( Vec_Ptr_t * vFuncs ) +{ + DdNode * bFunc; + int i; + printf( "(%d) ", Vec_PtrSize(vFuncs) ); + Vec_PtrForEachEntry( DdNode *, vFuncs, bFunc, i ) + printf( "%d ", Cudd_DagSize(bFunc) ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Computes bad states.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdManager * Llb4_Nonlin4SweepBadStates( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nVars ) +{ + DdManager * dd; + Vec_Ptr_t * vParts; + Vec_Int_t * vVars2Q; + DdNode * bMonitor, * bImage; + // get quantifiable variables + vVars2Q = Llb_Nonlin4SweepVars2Q( pAig, vOrder, 0 ); + // start BDD manager and create partitions + dd = Cudd_Init( nVars, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + vParts = Llb_Nonlin4SweepPartitions( dd, pAig, vOrder, 0 ); +//printf( "Outputs: " ); +//Llb_Nonlin4SweepPrint( vParts ); + // compute image of the partitions + bMonitor = Llb4_Nonlin4SweepBadMonitor( pAig, vOrder, dd ); Cudd_Ref( bMonitor ); + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + bImage = Llb_Nonlin4Image( dd, vParts, bMonitor, vVars2Q ); Cudd_Ref( bImage ); + Cudd_RecursiveDeref( dd, bMonitor ); + Llb_Nonlin4SweepDeref( dd, vParts ); + Vec_IntFree( vVars2Q ); + // save image and return + dd->bFunc = bImage; + return dd; +} + +/**Function************************************************************* + + Synopsis [Computes clusters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdManager * Llb4_Nonlin4SweepGroups( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nVars, Vec_Ptr_t ** pvGroups, int nBddLimitClp, int fVerbose ) +{ + DdManager * dd; + Vec_Ptr_t * vParts; + Vec_Int_t * vVars2Q; + // get quantifiable variables + vVars2Q = Llb_Nonlin4SweepVars2Q( pAig, vOrder, 1 ); + // start BDD manager and create partitions + dd = Cudd_Init( nVars, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + vParts = Llb_Nonlin4SweepPartitions( dd, pAig, vOrder, 1 ); +//printf( "Transitions: " ); +//Llb_Nonlin4SweepPrint( vParts ); + // compute image of the partitions + + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + *pvGroups = Llb_Nonlin4Group( dd, vParts, vVars2Q, nBddLimitClp ); + Llb_Nonlin4SweepDeref( dd, vParts ); +// *pvGroups = vParts; + +if ( fVerbose ) +{ +printf( "Groups: " ); +Llb_Nonlin4SweepPrint( *pvGroups ); +} + + Vec_IntFree( vVars2Q ); + return dd; +} + + +/**Function************************************************************* + + Synopsis [Creates quantifiable variables for both types of traversal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb_Nonlin4SweepPrintSuppProfile( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups, int fVerbose ) +{ + Aig_Obj_t * pObj; + int i, * pSupp; + int nSuppAll = 0, nSuppPi = 0, nSuppPo = 0, nSuppLi = 0, nSuppLo = 0, nSuppAnd = 0; + + pSupp = ABC_CALLOC( int, Cudd_ReadSize(dd) ); + Extra_VectorSupportArray( dd, (DdNode **)Vec_PtrArray(vGroups), Vec_PtrSize(vGroups), pSupp ); + + Aig_ManForEachObj( pAig, pObj, i ) + { + if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) + continue; + // remove variables that do not participate + if ( pSupp[Llb_ObjBddVar(vOrder, pObj)] == 0 ) + { + if ( Aig_ObjIsNode(pObj) ) + Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), -1 ); + continue; + } + nSuppAll++; + if ( Saig_ObjIsPi(pAig, pObj) ) + nSuppPi++; + else if ( Saig_ObjIsLo(pAig, pObj) ) + nSuppLo++; + else if ( Saig_ObjIsPo(pAig, pObj) ) + nSuppPo++; + else if ( Saig_ObjIsLi(pAig, pObj) ) + nSuppLi++; + else + nSuppAnd++; + } + ABC_FREE( pSupp ); + + if ( fVerbose ) + { + printf( "Groups =%3d ", Vec_PtrSize(vGroups) ); + printf( "Variables: all =%4d ", nSuppAll ); + printf( "pi =%4d ", nSuppPi ); + printf( "po =%4d ", nSuppPo ); + printf( "lo =%4d ", nSuppLo ); + printf( "li =%4d ", nSuppLi ); + printf( "and =%4d", nSuppAnd ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Performs BDD sweep on the netlist.] + + Description [Returns BDD manager, ordering, clusters, and bad states + inside dd->bFunc.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb4_Nonlin4Sweep( Aig_Man_t * pAig, int nSweepMax, int nClusterMax, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int fVerbose ) +{ + DdManager * ddBad, * ddWork; + Vec_Ptr_t * vGroups; + Vec_Int_t * vOrder; + int Counter, nCutPoints; + + // get the original ordering + Aig_ManCleanMarkA( pAig ); + vOrder = Llb_Nonlin4SweepOrder( pAig, &Counter, 1 ); + assert( Counter == Aig_ManNodeNum(pAig) ); + // mark the nodes + nCutPoints = Llb4_Nonlin4SweepCutpoints( pAig, vOrder, nSweepMax, fVerbose ); + Vec_IntFree( vOrder ); + // get better ordering + vOrder = Llb_Nonlin4SweepOrder( pAig, &Counter, 0 ); + assert( Counter == nCutPoints ); + Aig_ManCleanMarkA( pAig ); + // compute the BAD states + ddBad = Llb4_Nonlin4SweepBadStates( pAig, vOrder, nCutPoints + Aig_ManCiNum(pAig) + Aig_ManCoNum(pAig) ); + // compute the clusters + ddWork = Llb4_Nonlin4SweepGroups( pAig, vOrder, nCutPoints + Aig_ManCiNum(pAig) + Aig_ManCoNum(pAig), &vGroups, nClusterMax, fVerbose ); + // transfer the result from the Bad manager +//printf( "Bad before = %d.\n", Cudd_DagSize(ddBad->bFunc) ); + ddWork->bFunc = Cudd_bddTransfer( ddBad, ddWork, ddBad->bFunc ); Cudd_Ref( ddWork->bFunc ); + Cudd_RecursiveDeref( ddBad, ddBad->bFunc ); ddBad->bFunc = NULL; + Extra_StopManager( ddBad ); + // update ordering to exclude quantified variables +//printf( "Bad after = %d.\n", Cudd_DagSize(ddWork->bFunc) ); + + Llb_Nonlin4SweepPrintSuppProfile( ddWork, pAig, vOrder, vGroups, fVerbose ); + + // return the result + *pdd = ddWork; + *pvOrder = vOrder; + *pvGroups = vGroups; +} + +/**Function************************************************************* + + Synopsis [Performs BDD sweep on the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Llb4_Nonlin4SweepExperiment( Aig_Man_t * pAig ) +{ + DdManager * dd; + Vec_Int_t * vOrder; + Vec_Ptr_t * vGroups; + Llb4_Nonlin4Sweep( pAig, 100, 500, &dd, &vOrder, &vGroups, 1 ); + + Llb_Nonlin4SweepDeref( dd, vGroups ); + + Cudd_RecursiveDeref( dd, dd->bFunc ); + Extra_StopManager( dd ); + Vec_IntFree( vOrder ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/bdd/llb/llbInt.h b/src/bdd/llb/llbInt.h new file mode 100644 index 00000000..238da04e --- /dev/null +++ b/src/bdd/llb/llbInt.h @@ -0,0 +1,212 @@ +/**CFile**************************************************************** + + FileName [llbInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [BDD-based reachability.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 8, 2010.] + + Revision [$Id: llbInt.h,v 1.00 2010/05/08 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__llb__llbInt_h +#define ABC__aig__llb__llbInt_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include "aig/aig/aig.h" +#include "aig/saig/saig.h" +#include "proof/ssw/ssw.h" +#include "llb.h" + +#include "bdd/extrab/extraBdd.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_HEADER_START + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Llb_Man_t_ Llb_Man_t; +typedef struct Llb_Mtr_t_ Llb_Mtr_t; +typedef struct Llb_Grp_t_ Llb_Grp_t; + +struct Llb_Man_t_ +{ + Gia_ParLlb_t * pPars; // parameters + Aig_Man_t * pAigGlo; // initial AIG manager (owned by the caller) + Aig_Man_t * pAig; // derived AIG manager (created in this package) + DdManager * dd; // BDD manager + DdManager * ddG; // BDD manager + DdManager * ddR; // BDD manager + Vec_Int_t * vObj2Var; // mapping AIG ObjId into BDD var index + Vec_Int_t * vVar2Obj; // mapping BDD var index into AIG ObjId + Vec_Ptr_t * vGroups; // group Id into group pointer + Llb_Mtr_t * pMatrix; // dependency matrix + // image computation + Vec_Ptr_t * vRings; // onion rings + Vec_Int_t * vVarBegs; // the first group where the var appears + Vec_Int_t * vVarEnds; // the last group where the var appears + // variable mapping + Vec_Int_t * vNs2Glo; // next state variables into global variables + Vec_Int_t * vCs2Glo; // next state variables into global variables + Vec_Int_t * vGlo2Cs; // global variables into current state variables + Vec_Int_t * vGlo2Ns; // global variables into current state variables + // flow computation +// Vec_Int_t * vMem; +// Vec_Ptr_t * vTops; +// Vec_Ptr_t * vBots; +// Vec_Ptr_t * vCuts; +}; + +struct Llb_Mtr_t_ +{ + int nPis; // number of primary inputs + int nFfs; // number of flip-flops + int nRows; // number of rows + int nCols; // number of columns + int * pColSums; // sum of values in a column + Llb_Grp_t ** pColGrps; // group structure for each col + int * pRowSums; // sum of values in a row + char ** pMatrix; // dependency matrix + Llb_Man_t * pMan; // manager + // partial product + char * pProdVars; // variables in the partial product + int * pProdNums; // var counts in the remaining partitions +}; + +struct Llb_Grp_t_ +{ + int Id; // group ID + Vec_Ptr_t * vIns; // input AIG objs + Vec_Ptr_t * vOuts; // output AIG objs + Vec_Ptr_t * vNodes; // internal AIG objs + Llb_Man_t * pMan; // manager + Llb_Grp_t * pPrev; // previous group + Llb_Grp_t * pNext; // next group +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Llb_ObjBddVar( Vec_Int_t * vOrder, Aig_Obj_t * pObj ) { return Vec_IntEntry(vOrder, Aig_ObjId(pObj)); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== llbConstr.c ======================================================*/ +extern Vec_Int_t * Llb_ManDeriveConstraints( Aig_Man_t * p ); +extern void Llb_ManPrintEntries( Aig_Man_t * p, Vec_Int_t * vCands ); +/*=== llbCore.c ======================================================*/ +extern int Llb_ManModelCheckAig( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars, Vec_Int_t * vHints, DdManager ** pddGlo ); +/*=== llbCluster.c ======================================================*/ +extern void Llb_ManCluster( Llb_Mtr_t * p ); +/*=== llbDump.c ======================================================*/ +extern void Llb_ManDumpReached( DdManager * ddG, DdNode * bReached, char * pModel, char * pFileName ); +/*=== llbFlow.c ======================================================*/ +extern Vec_Ptr_t * Llb_ManFlow( Aig_Man_t * p, Vec_Ptr_t * vSources, int * pnFlow ); +/*=== llbHint.c ======================================================*/ +extern int Llb_ManReachabilityWithHints( Llb_Man_t * p ); +extern int Llb_ManModelCheckAigWithHints( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars ); +/*=== llbMan.c =======================================================*/ +extern void Llb_ManPrepareVarMap( Llb_Man_t * p ); +extern Llb_Man_t * Llb_ManStart( Aig_Man_t * pAigGlo, Aig_Man_t * pAig, Gia_ParLlb_t * pPars ); +extern void Llb_ManStop( Llb_Man_t * p ); +/*=== llbMatrix.c ====================================================*/ +extern void Llb_MtrVerifyMatrix( Llb_Mtr_t * p ); +extern Llb_Mtr_t * Llb_MtrCreate( Llb_Man_t * p ); +extern void Llb_MtrFree( Llb_Mtr_t * p ); +extern void Llb_MtrPrint( Llb_Mtr_t * p, int fOrder ); +extern void Llb_MtrPrintMatrixStats( Llb_Mtr_t * p ); +/*=== llbPart.c ======================================================*/ +extern Llb_Grp_t * Llb_ManGroupAlloc( Llb_Man_t * pMan ); +extern void Llb_ManGroupStop( Llb_Grp_t * p ); +extern void Llb_ManPrepareGroups( Llb_Man_t * pMan ); +extern Llb_Grp_t * Llb_ManGroupsCombine( Llb_Grp_t * p1, Llb_Grp_t * p2 ); +extern Llb_Grp_t * Llb_ManGroupCreateFromCuts( Llb_Man_t * pMan, Vec_Int_t * vCut1, Vec_Int_t * vCut2 ); +extern void Llb_ManPrepareVarLimits( Llb_Man_t * p ); +/*=== llbPivot.c =====================================================*/ +extern int Llb_ManTracePaths( Aig_Man_t * p, Aig_Obj_t * pPivot ); +extern Vec_Int_t * Llb_ManMarkPivotNodes( Aig_Man_t * p, int fUseInternal ); +/*=== llbReach.c =====================================================*/ +extern int Llb_ManReachability( Llb_Man_t * p, Vec_Int_t * vHints, DdManager ** pddGlo ); +/*=== llbSched.c =====================================================*/ +extern void Llb_MtrSchedule( Llb_Mtr_t * p ); + +/*=== llb2Bad.c ======================================================*/ +extern DdNode * Llb_BddComputeBad( Aig_Man_t * pInit, DdManager * dd, abctime TimeOut ); +extern DdNode * Llb_BddQuantifyPis( Aig_Man_t * pInit, DdManager * dd, DdNode * bFunc ); +/*=== llb2Core.c ======================================================*/ +extern DdNode * Llb_CoreComputeCube( DdManager * dd, Vec_Int_t * vVars, int fUseVarIndex, char * pValues ); +extern int Llb_CoreExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, abctime TimeTarget ); +/*=== llb2Driver.c ======================================================*/ +extern Vec_Int_t * Llb_DriverCountRefs( Aig_Man_t * p ); +extern Vec_Int_t * Llb_DriverCollectNs( Aig_Man_t * pAig, Vec_Int_t * vDriRefs ); +extern Vec_Int_t * Llb_DriverCollectCs( Aig_Man_t * pAig ); +extern DdNode * Llb_DriverPhaseCube( Aig_Man_t * pAig, Vec_Int_t * vDriRefs, DdManager * dd ); +extern DdManager * Llb_DriverLastPartition( Aig_Man_t * p, Vec_Int_t * vVarsNs, abctime TimeTarget ); +/*=== llb2Image.c ======================================================*/ +extern Vec_Ptr_t * Llb_ImgSupports( Aig_Man_t * p, Vec_Ptr_t * vDdMans, Vec_Int_t * vStart, Vec_Int_t * vStop, int fAddPis, int fVerbose ); +extern void Llb_ImgSchedule( Vec_Ptr_t * vSupps, Vec_Ptr_t ** pvQuant0, Vec_Ptr_t ** pvQuant1, int fVerbose ); +extern DdManager * Llb_ImgPartition( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, abctime TimeTarget ); +extern void Llb_ImgQuantifyFirst( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, Vec_Ptr_t * vQuant0, int fVerbose ); +extern void Llb_ImgQuantifyReset( Vec_Ptr_t * vDdMans ); +extern DdNode * Llb_ImgComputeImage( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, DdManager * dd, DdNode * bInit, + Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1, Vec_Int_t * vDriRefs, + abctime TimeTarget, int fBackward, int fReorder, int fVerbose ); + +extern DdManager * Llb_NonlinImageStart( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, int * pOrder, int fFirst, abctime TimeTarget ); +extern DdNode * Llb_NonlinImageCompute( DdNode * bCurrent, int fReorder, int fDrop, int fVerbose, int * pOrder ); +extern void Llb_NonlinImageQuit(); + +/*=== llb3Image.c =======================================================*/ +extern DdNode * Llb_NonlinImage( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, + DdManager * dd, DdNode * bCurrent, int fReorder, int fVerbose, int * pOrder ); +/*=== llb3Nonlin.c ======================================================*/ +extern DdNode * Llb_NonlinComputeInitState( Aig_Man_t * pAig, DdManager * dd ); + + +/*=== llb4Cex.c =======================================================*/ +extern Abc_Cex_t * Llb4_Nonlin4TransformCex( Aig_Man_t * pAig, Vec_Ptr_t * vStates, int iCexPo, int fVerbose ); +/*=== llb4Cluster.c =======================================================*/ +//extern void Llb_Nonlin4Cluster( Aig_Man_t * pAig, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int nBddMax, int fVerbose ); +/*=== llb4Image.c =======================================================*/ +extern DdNode * Llb_Nonlin4Image( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q ); +extern Vec_Ptr_t * Llb_Nonlin4Group( DdManager * dd, Vec_Ptr_t * vParts, Vec_Int_t * vVars2Q, int nSizeMax ); +/*=== llb4Map.c =========================================================*/ +//extern Vec_Int_t * Llb_AigMap( Aig_Man_t * pAig, int nLutSize, int nLutMin ); +/*=== llb4Nonlin.c ======================================================*/ +//extern int Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ); +/*=== llb4Sweep.c ======================================================*/ +extern void Llb4_Nonlin4Sweep( Aig_Man_t * pAig, int nSweepMax, int nClusterMax, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int fVerbose ); + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/bdd/llb/module.make b/src/bdd/llb/module.make new file mode 100644 index 00000000..6d253d50 --- /dev/null +++ b/src/bdd/llb/module.make @@ -0,0 +1,22 @@ +SRC += src/bdd/llb/llb1Cluster.c \ + src/bdd/llb/llb1Constr.c \ + src/bdd/llb/llb1Core.c \ + src/bdd/llb/llb1Group.c \ + src/bdd/llb/llb1Hint.c \ + src/bdd/llb/llb1Man.c \ + src/bdd/llb/llb1Matrix.c \ + src/bdd/llb/llb1Pivot.c \ + src/bdd/llb/llb1Reach.c \ + src/bdd/llb/llb1Sched.c \ + src/bdd/llb/llb2Bad.c \ + src/bdd/llb/llb2Core.c \ + src/bdd/llb/llb2Driver.c \ + src/bdd/llb/llb2Dump.c \ + src/bdd/llb/llb2Flow.c \ + src/bdd/llb/llb2Image.c \ + src/bdd/llb/llb3Image.c \ + src/bdd/llb/llb3Nonlin.c \ + src/bdd/llb/llb4Cex.c \ + src/bdd/llb/llb4Image.c \ + src/bdd/llb/llb4Nonlin.c \ + src/bdd/llb/llb4Sweep.c diff --git a/src/bdd/parse/module.make b/src/bdd/parse/module.make deleted file mode 100644 index 4f590f01..00000000 --- a/src/bdd/parse/module.make +++ /dev/null @@ -1,3 +0,0 @@ -SRC += src/bdd/parse/parseCore.c \ - src/bdd/parse/parseEqn.c \ - src/bdd/parse/parseStack.c diff --git a/src/bdd/parse/parse.h b/src/bdd/parse/parse.h deleted file mode 100644 index 584ec30a..00000000 --- a/src/bdd/parse/parse.h +++ /dev/null @@ -1,62 +0,0 @@ -/**CFile**************************************************************** - - FileName [parse.h] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Parsing symbolic Boolean formulas into BDDs.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 8, 2003.] - - Revision [$Id: parse.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef ABC__bdd__parse__parse_h -#define ABC__bdd__parse__parse_h - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// GLOBAL VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== parseCore.c =============================================================*/ -extern DdNode * Parse_FormulaParser( FILE * pOutput, char * pFormula, int nVars, int nRanks, - char * ppVarNames[], DdManager * dd, DdNode * pbVars[] ); - - - -ABC_NAMESPACE_HEADER_END - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/parse/parseCore.c b/src/bdd/parse/parseCore.c deleted file mode 100644 index f451d3aa..00000000 --- a/src/bdd/parse/parseCore.c +++ /dev/null @@ -1,536 +0,0 @@ -/**CFile**************************************************************** - - FileNameIn [parseCore.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Boolean formula parser.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: parseCore.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -/* - Some aspects of Boolean Formula Parser: - - 1) The names in the boolean formulas can be any strings of symbols - that start with char or underscore and contain chars, digits - and underscores: For example: 1) a&b <+> c'&d => a + b; - 2) a1 b2 c3' dummy' + (a2+b2')c3 dummy - 2) Constant values 0 and 1 can be used just like normal variables - 3) Any boolean operator (listed below) and parentheses can be used - any number of times provided there are equal number of opening - and closing parentheses. - 4) By default, absence of an operator between vars and before and - after parentheses is taken for AND. - 5) Both complementation prefix and complementation suffix can be - used at the same time (but who needs this?) - 6) Spaces (tabs, end-of-lines) may be inserted anywhere, - except between characters of the operations: <=>, =>, <=, <+> - 7) The stack size is defined by macro STACKSIZE and is used by the - stack constructor. -*/ - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#include "parseInt.h" - -ABC_NAMESPACE_IMPL_START - - -// the list of operation symbols to be used in expressions -#define PARSE_SYM_OPEN '(' // opening parenthesis -#define PARSE_SYM_CLOSE ')' // closing parenthesis -#define PARSE_SYM_LOWER '[' // shifts one rank down -#define PARSE_SYM_RAISE ']' // shifts one rank up -#define PARSE_SYM_CONST0 '0' // constant 0 -#define PARSE_SYM_CONST1 '1' // constant 1 -#define PARSE_SYM_NEGBEF1 '!' // negation before the variable -#define PARSE_SYM_NEGBEF2 '~' // negation before the variable -#define PARSE_SYM_NEGAFT '\'' // negation after the variable -#define PARSE_SYM_AND1 '&' // logic AND -#define PARSE_SYM_AND2 '*' // logic AND -#define PARSE_SYM_XOR1 '<' // logic EXOR (the 1st symbol) -#define PARSE_SYM_XOR2 '+' // logic EXOR (the 2nd symbol) -#define PARSE_SYM_XOR3 '>' // logic EXOR (the 3rd symbol) -#define PARSE_SYM_XOR '^' // logic XOR -#define PARSE_SYM_OR1 '+' // logic OR -#define PARSE_SYM_OR2 '|' // logic OR -#define PARSE_SYM_EQU1 '<' // equvalence (the 1st symbol) -#define PARSE_SYM_EQU2 '=' // equvalence (the 2nd symbol) -#define PARSE_SYM_EQU3 '>' // equvalence (the 3rd symbol) -#define PARSE_SYM_FLR1 '=' // implication (the 1st symbol) -#define PARSE_SYM_FLR2 '>' // implication (the 2nd symbol) -#define PARSE_SYM_FLL1 '<' // backward imp (the 1st symbol) -#define PARSE_SYM_FLL2 '=' // backward imp (the 2nd symbol) -// PARSE_SYM_FLR1 and PARSE_SYM_FLR2 should be the same as PARSE_SYM_EQU2 and PARSE_SYM_EQU3! - -// the list of opcodes (also specifying operation precedence) -#define PARSE_OPER_NEG 10 // negation -#define PARSE_OPER_AND 9 // logic AND -#define PARSE_OPER_XOR 8 // logic EXOR (a'b | ab') -#define PARSE_OPER_OR 7 // logic OR -#define PARSE_OPER_EQU 6 // equvalence (a'b'| ab ) -#define PARSE_OPER_FLR 5 // implication ( a' | b ) -#define PARSE_OPER_FLL 4 // backward imp ( 'b | a ) -#define PARSE_OPER_MARK 1 // OpStack token standing for an opening parenthesis - -// these are values of the internal Flag -#define PARSE_FLAG_START 1 // after the opening parenthesis -#define PARSE_FLAG_VAR 2 // after operation is received -#define PARSE_FLAG_OPER 3 // after operation symbol is received -#define PARSE_FLAG_ERROR 4 // when error is detected - -#define STACKSIZE 1000 - -static DdNode * Parse_ParserPerformTopOp( DdManager * dd, Parse_StackFn_t * pStackFn, int Oper ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Derives the BDD corresponding to the formula in language L.] - - Description [Takes the stream to output messages, the formula, the number - variables and the rank in the formula. The array of variable names is also - given. The BDD manager and the elementary 0-rank variable are the last two - arguments. The manager should have at least as many variables as - nVars * (nRanks + 1). The 0-rank variables should have numbers larger - than the variables of other ranks.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Parse_FormulaParser( FILE * pOutput, char * pFormulaInit, int nVars, int nRanks, - char * ppVarNames[], DdManager * dd, DdNode * pbVars[] ) -{ - char * pFormula; - Parse_StackFn_t * pStackFn; - Parse_StackOp_t * pStackOp; - DdNode * bFunc, * bTemp; - char * pTemp; - int nParans, fFound, Flag; - int Oper, Oper1, Oper2; - int i, fLower; - int v = -1; // Suppress "might be used uninitialized" - - // make sure that the number of vars and ranks is correct - if ( nVars * (nRanks + 1) > dd->size ) - { - printf( "Parse_FormulaParser(): The BDD manager does not have enough variables.\n" ); - return NULL; - } - - // make sure that the number of opening and closing parentheses is the same - nParans = 0; - for ( pTemp = pFormulaInit; *pTemp; pTemp++ ) - if ( *pTemp == '(' ) - nParans++; - else if ( *pTemp == ')' ) - nParans--; - if ( nParans != 0 ) - { - fprintf( pOutput, "Parse_FormulaParser(): Different number of opening and closing parentheses ().\n" ); - return NULL; - } - - nParans = 0; - for ( pTemp = pFormulaInit; *pTemp; pTemp++ ) - if ( *pTemp == '[' ) - nParans++; - else if ( *pTemp == ']' ) - nParans--; - if ( nParans != 0 ) - { - fprintf( pOutput, "Parse_FormulaParser(): Different number of opening and closing brackets [].\n" ); - return NULL; - } - - // copy the formula - pFormula = ABC_ALLOC( char, strlen(pFormulaInit) + 3 ); - sprintf( pFormula, "(%s)", pFormulaInit ); - - // start the stacks - pStackFn = Parse_StackFnStart( STACKSIZE ); - pStackOp = Parse_StackOpStart( STACKSIZE ); - - Flag = PARSE_FLAG_START; - fLower = 0; - for ( pTemp = pFormula; *pTemp; pTemp++ ) - { - switch ( *pTemp ) - { - // skip all spaces, tabs, and end-of-lines - case ' ': - case '\t': - case '\r': - case '\n': - continue; - - // treat Constant 0 as a variable - case PARSE_SYM_CONST0: - Parse_StackFnPush( pStackFn, b0 ); Cudd_Ref( b0 ); - if ( Flag == PARSE_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParser(): No operation symbol before constant 0.\n" ); - Flag = PARSE_FLAG_ERROR; - break; - } - Flag = PARSE_FLAG_VAR; - break; - - // the same for Constant 1 - case PARSE_SYM_CONST1: - Parse_StackFnPush( pStackFn, b1 ); Cudd_Ref( b1 ); - if ( Flag == PARSE_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParser(): No operation symbol before constant 1.\n" ); - Flag = PARSE_FLAG_ERROR; - break; - } - Flag = PARSE_FLAG_VAR; - break; - - case PARSE_SYM_NEGBEF1: - case PARSE_SYM_NEGBEF2: - if ( Flag == PARSE_FLAG_VAR ) - {// if NEGBEF follows a variable, AND is assumed - Parse_StackOpPush( pStackOp, PARSE_OPER_AND ); - Flag = PARSE_FLAG_OPER; - } - Parse_StackOpPush( pStackOp, PARSE_OPER_NEG ); - break; - - case PARSE_SYM_NEGAFT: - if ( Flag != PARSE_FLAG_VAR ) - {// if there is no variable before NEGAFT, it is an error - fprintf( pOutput, "Parse_FormulaParser(): No variable is specified before the negation suffix.\n" ); - Flag = PARSE_FLAG_ERROR; - break; - } - else // if ( Flag == PARSE_FLAG_VAR ) - Parse_StackFnPush( pStackFn, Cudd_Not( Parse_StackFnPop(pStackFn) ) ); - break; - - case PARSE_SYM_AND1: - case PARSE_SYM_AND2: - case PARSE_SYM_OR1: - case PARSE_SYM_OR2: - case PARSE_SYM_XOR: - if ( Flag != PARSE_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParser(): There is no variable before AND, EXOR, or OR.\n" ); - Flag = PARSE_FLAG_ERROR; - break; - } - if ( *pTemp == PARSE_SYM_AND1 || *pTemp == PARSE_SYM_AND2 ) - Parse_StackOpPush( pStackOp, PARSE_OPER_AND ); - else if ( *pTemp == PARSE_SYM_OR1 || *pTemp == PARSE_SYM_OR2 ) - Parse_StackOpPush( pStackOp, PARSE_OPER_OR ); - else //if ( Str[Pos] == PARSE_SYM_XOR ) - Parse_StackOpPush( pStackOp, PARSE_OPER_XOR ); - Flag = PARSE_FLAG_OPER; - break; - - case PARSE_SYM_EQU1: - if ( Flag != PARSE_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParser(): There is no variable before Equivalence or Implication\n" ); - Flag = PARSE_FLAG_ERROR; break; - } - if ( pTemp[1] == PARSE_SYM_EQU2 ) - { // check what is the next symbol in the string - pTemp++; - if ( pTemp[1] == PARSE_SYM_EQU3 ) - { - pTemp++; - Parse_StackOpPush( pStackOp, PARSE_OPER_EQU ); - } - else - { - Parse_StackOpPush( pStackOp, PARSE_OPER_FLL ); - } - } - else if ( pTemp[1] == PARSE_SYM_XOR2 ) - { - pTemp++; - if ( pTemp[1] == PARSE_SYM_XOR3 ) - { - pTemp++; - Parse_StackOpPush( pStackOp, PARSE_OPER_XOR ); - } - else - { - fprintf( pOutput, "Parse_FormulaParser(): Wrong symbol after \"%c%c\"\n", PARSE_SYM_EQU1, PARSE_SYM_XOR2 ); - Flag = PARSE_FLAG_ERROR; - break; - } - } - else - { - fprintf( pOutput, "Parse_FormulaParser(): Wrong symbol after \"%c\"\n", PARSE_SYM_EQU1 ); - Flag = PARSE_FLAG_ERROR; - break; - } - Flag = PARSE_FLAG_OPER; - break; - - case PARSE_SYM_EQU2: - if ( Flag != PARSE_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParser(): There is no variable before Reverse Implication\n" ); - Flag = PARSE_FLAG_ERROR; - break; - } - if ( pTemp[1] == PARSE_SYM_EQU3 ) - { - pTemp++; - Parse_StackOpPush( pStackOp, PARSE_OPER_FLR ); - } - else - { - fprintf( pOutput, "Parse_FormulaParser(): Wrong symbol after \"%c\"\n", PARSE_SYM_EQU2 ); - Flag = PARSE_FLAG_ERROR; - break; - } - Flag = PARSE_FLAG_OPER; - break; - - case PARSE_SYM_LOWER: - case PARSE_SYM_OPEN: - if ( Flag == PARSE_FLAG_VAR ) - Parse_StackOpPush( pStackOp, PARSE_OPER_AND ); - Parse_StackOpPush( pStackOp, PARSE_OPER_MARK ); - // after an opening bracket, it feels like starting over again - Flag = PARSE_FLAG_START; - break; - - case PARSE_SYM_RAISE: - fLower = 1; - case PARSE_SYM_CLOSE: - if ( !Parse_StackOpIsEmpty( pStackOp ) ) - { - while ( 1 ) - { - if ( Parse_StackOpIsEmpty( pStackOp ) ) - { - fprintf( pOutput, "Parse_FormulaParser(): There is no opening parenthesis\n" ); - Flag = PARSE_FLAG_ERROR; - break; - } - Oper = Parse_StackOpPop( pStackOp ); - if ( Oper == PARSE_OPER_MARK ) - break; - - // perform the given operation - if ( Parse_ParserPerformTopOp( dd, pStackFn, Oper ) == NULL ) - { - fprintf( pOutput, "Parse_FormulaParser(): Unknown operation\n" ); - ABC_FREE( pFormula ); - return NULL; - } - } - - if ( fLower ) - { - bFunc = (DdNode *)Parse_StackFnPop( pStackFn ); - bFunc = Extra_bddMove( dd, bTemp = bFunc, -nVars ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bTemp ); - Parse_StackFnPush( pStackFn, bFunc ); - } - } - else - { - fprintf( pOutput, "Parse_FormulaParser(): There is no opening parenthesis\n" ); - Flag = PARSE_FLAG_ERROR; - break; - } - if ( Flag != PARSE_FLAG_ERROR ) - Flag = PARSE_FLAG_VAR; - fLower = 0; - break; - - - default: - // scan the next name -/* - fFound = 0; - for ( i = 0; pTemp[i] && pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n'; i++ ) - { - for ( v = 0; v < nVars; v++ ) - if ( strncmp( pTemp, ppVarNames[v], i+1 ) == 0 && strlen(ppVarNames[v]) == (unsigned)(i+1) ) - { - pTemp += i; - fFound = 1; - break; - } - if ( fFound ) - break; - } -*/ - // bug fix by SV (9/11/08) - fFound = 0; - for ( i = 0; pTemp[i] && pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n' && - pTemp[i] != PARSE_SYM_AND1 && pTemp[i] != PARSE_SYM_AND2 && pTemp[i] != PARSE_SYM_XOR1 && - pTemp[i] != PARSE_SYM_XOR2 && pTemp[i] != PARSE_SYM_XOR3 && pTemp[i] != PARSE_SYM_XOR && - pTemp[i] != PARSE_SYM_OR1 && pTemp[i] != PARSE_SYM_OR2 && pTemp[i] != PARSE_SYM_CLOSE && - pTemp[i] != PARSE_SYM_NEGAFT; - i++ ) - {} - for ( v = 0; v < nVars; v++ ) - { - if ( strncmp( pTemp, ppVarNames[v], i ) == 0 && strlen(ppVarNames[v]) == (unsigned)(i) ) - { - pTemp += i-1; - fFound = 1; - break; - } - } - - if ( !fFound ) - { - fprintf( pOutput, "Parse_FormulaParser(): The parser cannot find var \"%s\" in the input var list.\n", pTemp ); - Flag = PARSE_FLAG_ERROR; - break; - } - // assume operation AND, if vars follow one another - if ( Flag == PARSE_FLAG_VAR ) - Parse_StackOpPush( pStackOp, PARSE_OPER_AND ); - Parse_StackFnPush( pStackFn, pbVars[v] ); Cudd_Ref( pbVars[v] ); - Flag = PARSE_FLAG_VAR; - break; - } - - if ( Flag == PARSE_FLAG_ERROR ) - break; // error exit - else if ( Flag == PARSE_FLAG_START ) - continue; // go on parsing - else if ( Flag == PARSE_FLAG_VAR ) - while ( 1 ) - { // check if there are negations in the OpStack - if ( Parse_StackOpIsEmpty(pStackOp) ) - break; - Oper = Parse_StackOpPop( pStackOp ); - if ( Oper != PARSE_OPER_NEG ) - { - Parse_StackOpPush( pStackOp, Oper ); - break; - } - else - { - Parse_StackFnPush( pStackFn, Cudd_Not(Parse_StackFnPop(pStackFn)) ); - } - } - else // if ( Flag == PARSE_FLAG_OPER ) - while ( 1 ) - { // execute all the operations in the OpStack - // with precedence higher or equal than the last one - Oper1 = Parse_StackOpPop( pStackOp ); // the last operation - if ( Parse_StackOpIsEmpty(pStackOp) ) - { // if it is the only operation, push it back - Parse_StackOpPush( pStackOp, Oper1 ); - break; - } - Oper2 = Parse_StackOpPop( pStackOp ); // the operation before the last one - if ( Oper2 >= Oper1 ) - { // if Oper2 precedence is higher or equal, execute it -// Parse_StackPush( pStackFn, Operation( FunStack.Pop(), FunStack.Pop(), Oper2 ) ); - if ( Parse_ParserPerformTopOp( dd, pStackFn, Oper2 ) == NULL ) - { - fprintf( pOutput, "Parse_FormulaParser(): Unknown operation\n" ); - ABC_FREE( pFormula ); - return NULL; - } - Parse_StackOpPush( pStackOp, Oper1 ); // push the last operation back - } - else - { // if Oper2 precedence is lower, push them back and done - Parse_StackOpPush( pStackOp, Oper2 ); - Parse_StackOpPush( pStackOp, Oper1 ); - break; - } - } - } - - if ( Flag != PARSE_FLAG_ERROR ) - { - if ( !Parse_StackFnIsEmpty(pStackFn) ) - { - bFunc = (DdNode *)Parse_StackFnPop(pStackFn); - if ( Parse_StackFnIsEmpty(pStackFn) ) - if ( Parse_StackOpIsEmpty(pStackOp) ) - { - Parse_StackFnFree(pStackFn); - Parse_StackOpFree(pStackOp); - Cudd_Deref( bFunc ); - ABC_FREE( pFormula ); - return bFunc; - } - else - fprintf( pOutput, "Parse_FormulaParser(): Something is left in the operation stack\n" ); - else - fprintf( pOutput, "Parse_FormulaParser(): Something is left in the function stack\n" ); - } - else - fprintf( pOutput, "Parse_FormulaParser(): The input string is empty\n" ); - } - ABC_FREE( pFormula ); - return NULL; -} - -/**Function************************************************************* - - Synopsis [Performs the operation on the top entries in the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Parse_ParserPerformTopOp( DdManager * dd, Parse_StackFn_t * pStackFn, int Oper ) -{ - DdNode * bArg1, * bArg2, * bFunc; - // perform the given operation - bArg2 = (DdNode *)Parse_StackFnPop( pStackFn ); - bArg1 = (DdNode *)Parse_StackFnPop( pStackFn ); - if ( Oper == PARSE_OPER_AND ) - bFunc = Cudd_bddAnd( dd, bArg1, bArg2 ); - else if ( Oper == PARSE_OPER_XOR ) - bFunc = Cudd_bddXor( dd, bArg1, bArg2 ); - else if ( Oper == PARSE_OPER_OR ) - bFunc = Cudd_bddOr( dd, bArg1, bArg2 ); - else if ( Oper == PARSE_OPER_EQU ) - bFunc = Cudd_bddXnor( dd, bArg1, bArg2 ); - else if ( Oper == PARSE_OPER_FLR ) - bFunc = Cudd_bddOr( dd, Cudd_Not(bArg1), bArg2 ); - else if ( Oper == PARSE_OPER_FLL ) - bFunc = Cudd_bddOr( dd, Cudd_Not(bArg2), bArg1 ); - else - return NULL; - Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bArg1 ); - Cudd_RecursiveDeref( dd, bArg2 ); - Parse_StackFnPush( pStackFn, bFunc ); - return bFunc; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// -ABC_NAMESPACE_IMPL_END - diff --git a/src/bdd/parse/parseEqn.c b/src/bdd/parse/parseEqn.c deleted file mode 100644 index ac32e528..00000000 --- a/src/bdd/parse/parseEqn.c +++ /dev/null @@ -1,358 +0,0 @@ -/**CFile**************************************************************** - - FileNameIn [parseEqn.c] - - PackageName [ABC: Logic synthesis and verification system.] - - Synopsis [Boolean formula parser.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - December 18, 2006.] - - Revision [$Id: parseEqn.c,v 1.0 2006/12/18 00:00:00 alanmi Exp $] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#include "parseInt.h" -#include "misc/vec/vec.h" -#include "aig/hop/hop.h" - -ABC_NAMESPACE_IMPL_START - - -// the list of operation symbols to be used in expressions -#define PARSE_EQN_SYM_OPEN '(' // opening parenthesis -#define PARSE_EQN_SYM_CLOSE ')' // closing parenthesis -#define PARSE_EQN_SYM_CONST0 '0' // constant 0 -#define PARSE_EQN_SYM_CONST1 '1' // constant 1 -#define PARSE_EQN_SYM_NEG '!' // negation before the variable -#define PARSE_EQN_SYM_AND '*' // logic AND -#define PARSE_EQN_SYM_OR '+' // logic OR - -// the list of opcodes (also specifying operation precedence) -#define PARSE_EQN_OPER_NEG 10 // negation -#define PARSE_EQN_OPER_AND 9 // logic AND -#define PARSE_EQN_OPER_OR 7 // logic OR -#define PARSE_EQN_OPER_MARK 1 // OpStack token standing for an opening parenthesis - -// these are values of the internal Flag -#define PARSE_EQN_FLAG_START 1 // after the opening parenthesis -#define PARSE_EQN_FLAG_VAR 2 // after operation is received -#define PARSE_EQN_FLAG_OPER 3 // after operation symbol is received -#define PARSE_EQN_FLAG_ERROR 4 // when error is detected - -#define PARSE_EQN_STACKSIZE 1000 - -static Hop_Obj_t * Parse_ParserPerformTopOp( Hop_Man_t * pMan, Parse_StackFn_t * pStackFn, int Oper ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Derives the AIG corresponding to the equation.] - - Description [Takes the stream to output messages, the formula, the vector - of variable names and the AIG manager.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Parse_FormulaParserEqn( FILE * pOutput, char * pFormInit, Vec_Ptr_t * vVarNames, Hop_Man_t * pMan ) -{ - char * pFormula; - Parse_StackFn_t * pStackFn; - Parse_StackOp_t * pStackOp; - Hop_Obj_t * gFunc; - char * pTemp, * pName; - int nParans, fFound, Flag; - int Oper, Oper1, Oper2; - int i, v; - - // make sure that the number of opening and closing parentheses is the same - nParans = 0; - for ( pTemp = pFormInit; *pTemp; pTemp++ ) - if ( *pTemp == '(' ) - nParans++; - else if ( *pTemp == ')' ) - nParans--; - if ( nParans != 0 ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): Different number of opening and closing parentheses ().\n" ); - return NULL; - } - - // copy the formula - pFormula = ABC_ALLOC( char, strlen(pFormInit) + 3 ); - sprintf( pFormula, "(%s)", pFormInit ); - - // start the stacks - pStackFn = Parse_StackFnStart( PARSE_EQN_STACKSIZE ); - pStackOp = Parse_StackOpStart( PARSE_EQN_STACKSIZE ); - - Flag = PARSE_EQN_FLAG_START; - for ( pTemp = pFormula; *pTemp; pTemp++ ) - { - switch ( *pTemp ) - { - // skip all spaces, tabs, and end-of-lines - case ' ': - case '\t': - case '\r': - case '\n': - continue; - case PARSE_EQN_SYM_CONST0: - Parse_StackFnPush( pStackFn, Hop_ManConst0(pMan) ); // Cudd_Ref( b0 ); - if ( Flag == PARSE_EQN_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): No operation symbol before constant 0.\n" ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - Flag = PARSE_EQN_FLAG_VAR; - break; - case PARSE_EQN_SYM_CONST1: - Parse_StackFnPush( pStackFn, Hop_ManConst1(pMan) ); // Cudd_Ref( b1 ); - if ( Flag == PARSE_EQN_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): No operation symbol before constant 1.\n" ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - Flag = PARSE_EQN_FLAG_VAR; - break; - case PARSE_EQN_SYM_NEG: - if ( Flag == PARSE_EQN_FLAG_VAR ) - {// if NEGBEF follows a variable, AND is assumed - Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_AND ); - Flag = PARSE_EQN_FLAG_OPER; - } - Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_NEG ); - break; - case PARSE_EQN_SYM_AND: - case PARSE_EQN_SYM_OR: - if ( Flag != PARSE_EQN_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): There is no variable before AND, EXOR, or OR.\n" ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - if ( *pTemp == PARSE_EQN_SYM_AND ) - Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_AND ); - else //if ( *pTemp == PARSE_EQN_SYM_OR ) - Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_OR ); - Flag = PARSE_EQN_FLAG_OPER; - break; - case PARSE_EQN_SYM_OPEN: - if ( Flag == PARSE_EQN_FLAG_VAR ) - { -// Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_AND ); - fprintf( pOutput, "Parse_FormulaParserEqn(): An opening parenthesis follows a var without operation sign.\n" ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_MARK ); - // after an opening bracket, it feels like starting over again - Flag = PARSE_EQN_FLAG_START; - break; - case PARSE_EQN_SYM_CLOSE: - if ( !Parse_StackOpIsEmpty( pStackOp ) ) - { - while ( 1 ) - { - if ( Parse_StackOpIsEmpty( pStackOp ) ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): There is no opening parenthesis\n" ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - Oper = Parse_StackOpPop( pStackOp ); - if ( Oper == PARSE_EQN_OPER_MARK ) - break; - - // perform the given operation - if ( Parse_ParserPerformTopOp( pMan, pStackFn, Oper ) == NULL ) - { - Parse_StackFnFree( pStackFn ); - Parse_StackOpFree( pStackOp ); - fprintf( pOutput, "Parse_FormulaParserEqn(): Unknown operation\n" ); - ABC_FREE( pFormula ); - return NULL; - } - } - } - else - { - fprintf( pOutput, "Parse_FormulaParserEqn(): There is no opening parenthesis\n" ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - if ( Flag != PARSE_EQN_FLAG_ERROR ) - Flag = PARSE_EQN_FLAG_VAR; - break; - - - default: - // scan the next name - for ( i = 0; pTemp[i] && - pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n' && - pTemp[i] != PARSE_EQN_SYM_AND && pTemp[i] != PARSE_EQN_SYM_OR && pTemp[i] != PARSE_EQN_SYM_CLOSE; i++ ) - { - if ( pTemp[i] == PARSE_EQN_SYM_NEG || pTemp[i] == PARSE_EQN_SYM_OPEN ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): The negation sign or an opening parenthesis inside the variable name.\n" ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - } - // variable name is found - fFound = 0; - Vec_PtrForEachEntry( char *, vVarNames, pName, v ) - if ( strncmp(pTemp, pName, i) == 0 && strlen(pName) == (unsigned)i ) - { - pTemp += i-1; - fFound = 1; - break; - } - if ( !fFound ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): The parser cannot find var \"%s\" in the input var list.\n", pTemp ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - if ( Flag == PARSE_EQN_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): The variable name \"%s\" follows another var without operation sign.\n", pTemp ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - Parse_StackFnPush( pStackFn, Hop_IthVar( pMan, v ) ); // Cudd_Ref( pbVars[v] ); - Flag = PARSE_EQN_FLAG_VAR; - break; - } - - if ( Flag == PARSE_EQN_FLAG_ERROR ) - break; // error exit - else if ( Flag == PARSE_EQN_FLAG_START ) - continue; // go on parsing - else if ( Flag == PARSE_EQN_FLAG_VAR ) - while ( 1 ) - { // check if there are negations in the OpStack - if ( Parse_StackOpIsEmpty(pStackOp) ) - break; - Oper = Parse_StackOpPop( pStackOp ); - if ( Oper != PARSE_EQN_OPER_NEG ) - { - Parse_StackOpPush( pStackOp, Oper ); - break; - } - else - { - Parse_StackFnPush( pStackFn, Hop_Not((Hop_Obj_t *)Parse_StackFnPop(pStackFn)) ); - } - } - else // if ( Flag == PARSE_EQN_FLAG_OPER ) - while ( 1 ) - { // execute all the operations in the OpStack - // with precedence higher or equal than the last one - Oper1 = Parse_StackOpPop( pStackOp ); // the last operation - if ( Parse_StackOpIsEmpty(pStackOp) ) - { // if it is the only operation, push it back - Parse_StackOpPush( pStackOp, Oper1 ); - break; - } - Oper2 = Parse_StackOpPop( pStackOp ); // the operation before the last one - if ( Oper2 >= Oper1 ) - { // if Oper2 precedence is higher or equal, execute it - if ( Parse_ParserPerformTopOp( pMan, pStackFn, Oper2 ) == NULL ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): Unknown operation\n" ); - ABC_FREE( pFormula ); - Parse_StackFnFree( pStackFn ); - Parse_StackOpFree( pStackOp ); - return NULL; - } - Parse_StackOpPush( pStackOp, Oper1 ); // push the last operation back - } - else - { // if Oper2 precedence is lower, push them back and done - Parse_StackOpPush( pStackOp, Oper2 ); - Parse_StackOpPush( pStackOp, Oper1 ); - break; - } - } - } - - if ( Flag != PARSE_EQN_FLAG_ERROR ) - { - if ( !Parse_StackFnIsEmpty(pStackFn) ) - { - gFunc = (Hop_Obj_t *)Parse_StackFnPop(pStackFn); - if ( Parse_StackFnIsEmpty(pStackFn) ) - if ( Parse_StackOpIsEmpty(pStackOp) ) - { - Parse_StackFnFree(pStackFn); - Parse_StackOpFree(pStackOp); -// Cudd_Deref( gFunc ); - ABC_FREE( pFormula ); - return gFunc; - } - else - fprintf( pOutput, "Parse_FormulaParserEqn(): Something is left in the operation stack\n" ); - else - fprintf( pOutput, "Parse_FormulaParserEqn(): Something is left in the function stack\n" ); - } - else - fprintf( pOutput, "Parse_FormulaParserEqn(): The input string is empty\n" ); - } - ABC_FREE( pFormula ); - return NULL; -} - -/**Function************************************************************* - - Synopsis [Performs the operation on the top entries in the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Parse_ParserPerformTopOp( Hop_Man_t * pMan, Parse_StackFn_t * pStackFn, int Oper ) -{ - Hop_Obj_t * gArg1, * gArg2, * gFunc; - // perform the given operation - gArg2 = (Hop_Obj_t *)Parse_StackFnPop( pStackFn ); - gArg1 = (Hop_Obj_t *)Parse_StackFnPop( pStackFn ); - if ( Oper == PARSE_EQN_OPER_AND ) - gFunc = Hop_And( pMan, gArg1, gArg2 ); - else if ( Oper == PARSE_EQN_OPER_OR ) - gFunc = Hop_Or( pMan, gArg1, gArg2 ); - else - return NULL; -// Cudd_Ref( gFunc ); -// Cudd_RecursiveDeref( dd, gArg1 ); -// Cudd_RecursiveDeref( dd, gArg2 ); - Parse_StackFnPush( pStackFn, gFunc ); - return gFunc; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// -ABC_NAMESPACE_IMPL_END - diff --git a/src/bdd/parse/parseInt.h b/src/bdd/parse/parseInt.h deleted file mode 100644 index 80ed945a..00000000 --- a/src/bdd/parse/parseInt.h +++ /dev/null @@ -1,79 +0,0 @@ -/**CFile**************************************************************** - - FileName [parseInt.h] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Parsing symbolic Boolean formulas into BDDs.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 8, 2003.] - - Revision [$Id: parseInt.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef ABC__bdd__parse__parseInt_h -#define ABC__bdd__parse__parseInt_h - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - - -#include -#include "misc/extra/extraBdd.h" -#include "parse.h" - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct ParseStackFnStruct Parse_StackFn_t; // the function stack -typedef struct ParseStackOpStruct Parse_StackOp_t; // the operation stack - -//////////////////////////////////////////////////////////////////////// -/// GLOBAL VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== parseStack.c =============================================================*/ -extern Parse_StackFn_t * Parse_StackFnStart ( int nDepth ); -extern int Parse_StackFnIsEmpty( Parse_StackFn_t * p ); -extern void Parse_StackFnPush ( Parse_StackFn_t * p, void * bFunc ); -extern void * Parse_StackFnPop ( Parse_StackFn_t * p ); -extern void Parse_StackFnFree ( Parse_StackFn_t * p ); - -extern Parse_StackOp_t * Parse_StackOpStart ( int nDepth ); -extern int Parse_StackOpIsEmpty( Parse_StackOp_t * p ); -extern void Parse_StackOpPush ( Parse_StackOp_t * p, int Oper ); -extern int Parse_StackOpPop ( Parse_StackOp_t * p ); -extern void Parse_StackOpFree ( Parse_StackOp_t * p ); - - - -ABC_NAMESPACE_HEADER_END - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/parse/parseStack.c b/src/bdd/parse/parseStack.c deleted file mode 100644 index 2e6d266d..00000000 --- a/src/bdd/parse/parseStack.c +++ /dev/null @@ -1,248 +0,0 @@ -/**CFile**************************************************************** - - FileName [parseStack.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Stacks used by the formula parser.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - August 18, 2003.] - - Revision [$Id: parseStack.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "parseInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -struct ParseStackFnStruct -{ - void ** pData; // the array of elements - int Top; // the index - int Size; // the stack size -}; - -struct ParseStackOpStruct -{ - int * pData; // the array of elements - int Top; // the index - int Size; // the stack size -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Parse_StackFn_t * Parse_StackFnStart( int nDepth ) -{ - Parse_StackFn_t * p; - p = ABC_ALLOC( Parse_StackFn_t, 1 ); - memset( p, 0, sizeof(Parse_StackFn_t) ); - p->pData = ABC_ALLOC( void *, nDepth ); - p->Size = nDepth; - return p; -} - -/**Function************************************************************* - - Synopsis [Checks whether the stack is empty.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Parse_StackFnIsEmpty( Parse_StackFn_t * p ) -{ - return (int)(p->Top == 0); -} - -/**Function************************************************************* - - Synopsis [Pushes an entry into the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Parse_StackFnPush( Parse_StackFn_t * p, void * bFunc ) -{ - if ( p->Top >= p->Size ) - { - printf( "Parse_StackFnPush(): Stack size is too small!\n" ); - return; - } - p->pData[ p->Top++ ] = bFunc; -} - -/**Function************************************************************* - - Synopsis [Pops an entry out of the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Parse_StackFnPop( Parse_StackFn_t * p ) -{ - if ( p->Top == 0 ) - { - printf( "Parse_StackFnPush(): Trying to extract data from the empty stack!\n" ); - return NULL; - } - return p->pData[ --p->Top ]; -} - -/**Function************************************************************* - - Synopsis [Deletes the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Parse_StackFnFree( Parse_StackFn_t * p ) -{ - ABC_FREE( p->pData ); - ABC_FREE( p ); -} - - - - -/**Function************************************************************* - - Synopsis [Starts the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Parse_StackOp_t * Parse_StackOpStart( int nDepth ) -{ - Parse_StackOp_t * p; - p = ABC_ALLOC( Parse_StackOp_t, 1 ); - memset( p, 0, sizeof(Parse_StackOp_t) ); - p->pData = ABC_ALLOC( int, nDepth ); - p->Size = nDepth; - return p; -} - -/**Function************************************************************* - - Synopsis [Checks whether the stack is empty.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Parse_StackOpIsEmpty( Parse_StackOp_t * p ) -{ - return (int)(p->Top == 0); -} - -/**Function************************************************************* - - Synopsis [Pushes an entry into the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Parse_StackOpPush( Parse_StackOp_t * p, int Oper ) -{ - if ( p->Top >= p->Size ) - { - printf( "Parse_StackOpPush(): Stack size is too small!\n" ); - return; - } - p->pData[ p->Top++ ] = Oper; -} - -/**Function************************************************************* - - Synopsis [Pops an entry out of the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Parse_StackOpPop( Parse_StackOp_t * p ) -{ - if ( p->Top == 0 ) - { - printf( "Parse_StackOpPush(): Trying to extract data from the empty stack!\n" ); - return -1; - } - return p->pData[ --p->Top ]; -} - -/**Function************************************************************* - - Synopsis [Deletes the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Parse_StackOpFree( Parse_StackOp_t * p ) -{ - ABC_FREE( p->pData ); - ABC_FREE( p ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/misc/extra/extraBdd.h b/src/misc/extra/extraBdd.h deleted file mode 100644 index 3dbc6264..00000000 --- a/src/misc/extra/extraBdd.h +++ /dev/null @@ -1,317 +0,0 @@ -/**CFile**************************************************************** - - FileName [extraBdd.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [extra] - - Synopsis [Various reusable software utilities.] - - Description [This library contains a number of operators and - traversal routines developed to extend the functionality of - CUDD v.2.3.x, by Fabio Somenzi (http://vlsi.colorado.edu/~fabio/) - To compile your code with the library, #include "extra.h" - in your source files and link your project to CUDD and this - library. Use the library at your own risk and with caution. - Note that debugging of some operators still continues.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: extraBdd.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef ABC__misc__extra__extra_bdd_h -#define ABC__misc__extra__extra_bdd_h - - -#ifdef _WIN32 -#define inline __inline // compatible with MS VS 6.0 -#endif - -/*---------------------------------------------------------------------------*/ -/* Nested includes */ -/*---------------------------------------------------------------------------*/ - -#include -#include -#include -#include - -#include "misc/st/st.h" -#include "bdd/cudd/cuddInt.h" -#include "misc/extra/extra.h" - - -ABC_NAMESPACE_HEADER_START - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/* constants of the manager */ -#define b0 Cudd_Not((dd)->one) -#define b1 (dd)->one -#define z0 (dd)->zero -#define z1 (dd)->one -#define a0 (dd)->zero -#define a1 (dd)->one - -// hash key macros -#define hashKey1(a,TSIZE) \ -((ABC_PTRUINT_T)(a) % TSIZE) - -#define hashKey2(a,b,TSIZE) \ -(((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b) * DD_P1) % TSIZE) - -#define hashKey3(a,b,c,TSIZE) \ -(((((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b)) * DD_P1 + (ABC_PTRUINT_T)(c)) * DD_P2 ) % TSIZE) - -#define hashKey4(a,b,c,d,TSIZE) \ -((((((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b)) * DD_P1 + (ABC_PTRUINT_T)(c)) * DD_P2 + \ - (ABC_PTRUINT_T)(d)) * DD_P3) % TSIZE) - -#define hashKey5(a,b,c,d,e,TSIZE) \ -(((((((ABC_PTRUINT_T)(a) + (ABC_PTRUINT_T)(b)) * DD_P1 + (ABC_PTRUINT_T)(c)) * DD_P2 + \ - (ABC_PTRUINT_T)(d)) * DD_P3 + (ABC_PTRUINT_T)(e)) * DD_P1) % TSIZE) - -/*===========================================================================*/ -/* Various Utilities */ -/*===========================================================================*/ - -/*=== extraBddAuto.c ========================================================*/ - -extern DdNode * Extra_bddSpaceFromFunctionFast( DdManager * dd, DdNode * bFunc ); -extern DdNode * Extra_bddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG ); -extern DdNode * extraBddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG ); -extern DdNode * Extra_bddSpaceFromFunctionPos( DdManager * dd, DdNode * bFunc ); -extern DdNode * extraBddSpaceFromFunctionPos( DdManager * dd, DdNode * bFunc ); -extern DdNode * Extra_bddSpaceFromFunctionNeg( DdManager * dd, DdNode * bFunc ); -extern DdNode * extraBddSpaceFromFunctionNeg( DdManager * dd, DdNode * bFunc ); - -extern DdNode * Extra_bddSpaceCanonVars( DdManager * dd, DdNode * bSpace ); -extern DdNode * extraBddSpaceCanonVars( DdManager * dd, DdNode * bSpace ); - -extern DdNode * Extra_bddSpaceEquations( DdManager * dd, DdNode * bSpace ); -extern DdNode * Extra_bddSpaceEquationsNeg( DdManager * dd, DdNode * bSpace ); -extern DdNode * extraBddSpaceEquationsNeg( DdManager * dd, DdNode * bSpace ); -extern DdNode * Extra_bddSpaceEquationsPos( DdManager * dd, DdNode * bSpace ); -extern DdNode * extraBddSpaceEquationsPos( DdManager * dd, DdNode * bSpace ); - -extern DdNode * Extra_bddSpaceFromMatrixPos( DdManager * dd, DdNode * zA ); -extern DdNode * extraBddSpaceFromMatrixPos( DdManager * dd, DdNode * zA ); -extern DdNode * Extra_bddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA ); -extern DdNode * extraBddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA ); - -extern DdNode * Extra_bddSpaceReduce( DdManager * dd, DdNode * bFunc, DdNode * bCanonVars ); -extern DdNode ** Extra_bddSpaceExorGates( DdManager * dd, DdNode * bFuncRed, DdNode * zEquations ); - -/*=== extraBddCas.c =============================================================*/ - -/* performs the binary encoding of the set of function using the given vars */ -extern DdNode * Extra_bddEncodingBinary( DdManager * dd, DdNode ** pbFuncs, int nFuncs, DdNode ** pbVars, int nVars ); -/* solves the column encoding problem using a sophisticated method */ -extern DdNode * Extra_bddEncodingNonStrict( DdManager * dd, DdNode ** pbColumns, int nColumns, DdNode * bVarsCol, DdNode ** pCVars, int nMulti, int * pSimple ); -/* collects the nodes under the cut and, for each node, computes the sum of paths leading to it from the root */ -extern st__table * Extra_bddNodePathsUnderCut( DdManager * dd, DdNode * bFunc, int CutLevel ); -/* collects the nodes under the cut starting from the given set of ADD nodes */ -extern int Extra_bddNodePathsUnderCutArray( DdManager * dd, DdNode ** paNodes, DdNode ** pbCubes, int nNodes, DdNode ** paNodesRes, DdNode ** pbCubesRes, int CutLevel ); -/* find the profile of a DD (the number of edges crossing each level) */ -extern int Extra_ProfileWidth( DdManager * dd, DdNode * F, int * Profile, int CutLevel ); - -/*=== extraBddImage.c ================================================================*/ - -typedef struct Extra_ImageTree_t_ Extra_ImageTree_t; -extern Extra_ImageTree_t * Extra_bddImageStart( - DdManager * dd, DdNode * bCare, - int nParts, DdNode ** pbParts, - int nVars, DdNode ** pbVars, int fVerbose ); -extern DdNode * Extra_bddImageCompute( Extra_ImageTree_t * pTree, DdNode * bCare ); -extern void Extra_bddImageTreeDelete( Extra_ImageTree_t * pTree ); -extern DdNode * Extra_bddImageRead( Extra_ImageTree_t * pTree ); - -typedef struct Extra_ImageTree2_t_ Extra_ImageTree2_t; -extern Extra_ImageTree2_t * Extra_bddImageStart2( - DdManager * dd, DdNode * bCare, - int nParts, DdNode ** pbParts, - int nVars, DdNode ** pbVars, int fVerbose ); -extern DdNode * Extra_bddImageCompute2( Extra_ImageTree2_t * pTree, DdNode * bCare ); -extern void Extra_bddImageTreeDelete2( Extra_ImageTree2_t * pTree ); -extern DdNode * Extra_bddImageRead2( Extra_ImageTree2_t * pTree ); - -/*=== extraBddMisc.c ========================================================*/ - -extern DdNode * Extra_TransferPermute( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute ); -extern DdNode * Extra_TransferLevelByLevel( DdManager * ddSource, DdManager * ddDestination, DdNode * f ); -extern DdNode * Extra_bddRemapUp( DdManager * dd, DdNode * bF ); -extern DdNode * Extra_bddMove( DdManager * dd, DdNode * bF, int nVars ); -extern DdNode * extraBddMove( DdManager * dd, DdNode * bF, DdNode * bFlag ); -extern void Extra_StopManager( DdManager * dd ); -extern void Extra_bddPrint( DdManager * dd, DdNode * F ); -extern void Extra_bddPrintSupport( DdManager * dd, DdNode * F ); -extern void extraDecomposeCover( DdManager* dd, DdNode* zC, DdNode** zC0, DdNode** zC1, DdNode** zC2 ); -extern int Extra_bddSuppSize( DdManager * dd, DdNode * bSupp ); -extern int Extra_bddSuppContainVar( DdManager * dd, DdNode * bS, DdNode * bVar ); -extern int Extra_bddSuppOverlapping( DdManager * dd, DdNode * S1, DdNode * S2 ); -extern int Extra_bddSuppDifferentVars( DdManager * dd, DdNode * S1, DdNode * S2, int DiffMax ); -extern int Extra_bddSuppCheckContainment( DdManager * dd, DdNode * bL, DdNode * bH, DdNode ** bLarge, DdNode ** bSmall ); -extern int * Extra_SupportArray( DdManager * dd, DdNode * F, int * support ); -extern int * Extra_VectorSupportArray( DdManager * dd, DdNode ** F, int n, int * support ); -extern DdNode * Extra_bddFindOneCube( DdManager * dd, DdNode * bF ); -extern DdNode * Extra_bddGetOneCube( DdManager * dd, DdNode * bFunc ); -extern DdNode * Extra_bddComputeRangeCube( DdManager * dd, int iStart, int iStop ); -extern DdNode * Extra_bddBitsToCube( DdManager * dd, int Code, int CodeWidth, DdNode ** pbVars, int fMsbFirst ); -extern DdNode * Extra_bddSupportNegativeCube( DdManager * dd, DdNode * f ); -extern int Extra_bddIsVar( DdNode * bFunc ); -extern DdNode * Extra_bddCreateAnd( DdManager * dd, int nVars ); -extern DdNode * Extra_bddCreateOr( DdManager * dd, int nVars ); -extern DdNode * Extra_bddCreateExor( DdManager * dd, int nVars ); -extern DdNode * Extra_zddPrimes( DdManager * dd, DdNode * F ); -extern void Extra_bddPermuteArray( DdManager * dd, DdNode ** bNodesIn, DdNode ** bNodesOut, int nNodes, int *permut ); -extern DdNode * Extra_bddComputeCube( DdManager * dd, DdNode ** bXVars, int nVars ); -extern DdNode * Extra_bddChangePolarity( DdManager * dd, DdNode * bFunc, DdNode * bVars ); -extern DdNode * extraBddChangePolarity( DdManager * dd, DdNode * bFunc, DdNode * bVars ); -extern int Extra_bddVarIsInCube( DdNode * bCube, int iVar ); -extern DdNode * Extra_bddAndPermute( DdManager * ddF, DdNode * bF, DdManager * ddG, DdNode * bG, int * pPermute ); -extern int Extra_bddCountCubes( DdManager * dd, DdNode ** pFuncs, int nFuncs, int fMode, int nLimit, int * pGuide ); -extern void Extra_zddDumpPla( DdManager * dd, DdNode * zCover, int nVars, char * pFileName ); - -#ifndef ABC_PRB -#define ABC_PRB(dd,f) printf("%s = ", #f); Extra_bddPrint(dd,f); printf("\n") -#endif - -/*=== extraBddKmap.c ================================================================*/ - -/* displays the Karnaugh Map of a function */ -extern void Extra_PrintKMap( FILE * pFile, DdManager * dd, DdNode * OnSet, DdNode * OffSet, int nVars, DdNode ** XVars, int fSuppType, char ** pVarNames ); -/* displays the Karnaugh Map of a relation */ -extern void Extra_PrintKMapRelation( FILE * pFile, DdManager * dd, DdNode * OnSet, DdNode * OffSet, int nXVars, int nYVars, DdNode ** XVars, DdNode ** YVars ); - -/*=== extraBddSymm.c =================================================================*/ - -typedef struct Extra_SymmInfo_t_ Extra_SymmInfo_t; -struct Extra_SymmInfo_t_ { - int nVars; // the number of variables in the support - int nVarsMax; // the number of variables in the DD manager - int nSymms; // the number of pair-wise symmetries - int nNodes; // the number of nodes in a ZDD (if applicable) - int * pVars; // the list of all variables present in the support - char ** pSymms; // the symmetry information -}; - -/* computes the classical symmetry information for the function - recursive */ -extern Extra_SymmInfo_t * Extra_SymmPairsCompute( DdManager * dd, DdNode * bFunc ); -/* computes the classical symmetry information for the function - using naive approach */ -extern Extra_SymmInfo_t * Extra_SymmPairsComputeNaive( DdManager * dd, DdNode * bFunc ); -extern int Extra_bddCheckVarsSymmetricNaive( DdManager * dd, DdNode * bF, int iVar1, int iVar2 ); - -/* allocates the data structure */ -extern Extra_SymmInfo_t * Extra_SymmPairsAllocate( int nVars ); -/* deallocates the data structure */ -extern void Extra_SymmPairsDissolve( Extra_SymmInfo_t * ); -/* print the contents the data structure */ -extern void Extra_SymmPairsPrint( Extra_SymmInfo_t * ); -/* converts the ZDD into the Extra_SymmInfo_t structure */ -extern Extra_SymmInfo_t * Extra_SymmPairsCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bVars ); - -/* computes the classical symmetry information as a ZDD */ -extern DdNode * Extra_zddSymmPairsCompute( DdManager * dd, DdNode * bF, DdNode * bVars ); -extern DdNode * extraZddSymmPairsCompute( DdManager * dd, DdNode * bF, DdNode * bVars ); -/* returns a singleton-set ZDD containing all variables that are symmetric with the given one */ -extern DdNode * Extra_zddGetSymmetricVars( DdManager * dd, DdNode * bF, DdNode * bG, DdNode * bVars ); -extern DdNode * extraZddGetSymmetricVars( DdManager * dd, DdNode * bF, DdNode * bG, DdNode * bVars ); -/* converts a set of variables into a set of singleton subsets */ -extern DdNode * Extra_zddGetSingletons( DdManager * dd, DdNode * bVars ); -extern DdNode * extraZddGetSingletons( DdManager * dd, DdNode * bVars ); -/* filters the set of variables using the support of the function */ -extern DdNode * Extra_bddReduceVarSet( DdManager * dd, DdNode * bVars, DdNode * bF ); -extern DdNode * extraBddReduceVarSet( DdManager * dd, DdNode * bVars, DdNode * bF ); - -/* checks the possibility that the two vars are symmetric */ -extern int Extra_bddCheckVarsSymmetric( DdManager * dd, DdNode * bF, int iVar1, int iVar2 ); -extern DdNode * extraBddCheckVarsSymmetric( DdManager * dd, DdNode * bF, DdNode * bVars ); - -/* build the set of all tuples of K variables out of N from the BDD cube */ -extern DdNode * Extra_zddTuplesFromBdd( DdManager * dd, int K, DdNode * bVarsN ); -extern DdNode * extraZddTuplesFromBdd( DdManager * dd, DdNode * bVarsK, DdNode * bVarsN ); -/* selects one subset from a ZDD representing the set of subsets */ -extern DdNode * Extra_zddSelectOneSubset( DdManager * dd, DdNode * zS ); -extern DdNode * extraZddSelectOneSubset( DdManager * dd, DdNode * zS ); - -/*=== extraBddUnate.c =================================================================*/ - -extern DdNode * Extra_bddAndTime( DdManager * dd, DdNode * f, DdNode * g, int TimeOut ); -extern DdNode * Extra_bddAndAbstractTime( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube, int TimeOut ); -extern DdNode * Extra_TransferPermuteTime( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute, int TimeOut ); - -/*=== extraBddUnate.c =================================================================*/ - -typedef struct Extra_UnateVar_t_ Extra_UnateVar_t; -struct Extra_UnateVar_t_ { - unsigned iVar : 30; // index of the variable - unsigned Pos : 1; // 1 if positive unate - unsigned Neg : 1; // 1 if negative unate -}; - -typedef struct Extra_UnateInfo_t_ Extra_UnateInfo_t; -struct Extra_UnateInfo_t_ { - int nVars; // the number of variables in the support - int nVarsMax; // the number of variables in the DD manager - int nUnate; // the number of unate variables - Extra_UnateVar_t * pVars; // the array of variables present in the support -}; - -/* allocates the data structure */ -extern Extra_UnateInfo_t * Extra_UnateInfoAllocate( int nVars ); -/* deallocates the data structure */ -extern void Extra_UnateInfoDissolve( Extra_UnateInfo_t * ); -/* print the contents the data structure */ -extern void Extra_UnateInfoPrint( Extra_UnateInfo_t * ); -/* converts the ZDD into the Extra_SymmInfo_t structure */ -extern Extra_UnateInfo_t * Extra_UnateInfoCreateFromZdd( DdManager * dd, DdNode * zUnate, DdNode * bVars ); -/* naive check of unateness of one variable */ -extern int Extra_bddCheckUnateNaive( DdManager * dd, DdNode * bF, int iVar ); - -/* computes the unateness information for the function */ -extern Extra_UnateInfo_t * Extra_UnateComputeFast( DdManager * dd, DdNode * bFunc ); -extern Extra_UnateInfo_t * Extra_UnateComputeSlow( DdManager * dd, DdNode * bFunc ); - -/* computes the classical symmetry information as a ZDD */ -extern DdNode * Extra_zddUnateInfoCompute( DdManager * dd, DdNode * bF, DdNode * bVars ); -extern DdNode * extraZddUnateInfoCompute( DdManager * dd, DdNode * bF, DdNode * bVars ); - -/* converts a set of variables into a set of singleton subsets */ -extern DdNode * Extra_zddGetSingletonsBoth( DdManager * dd, DdNode * bVars ); -extern DdNode * extraZddGetSingletonsBoth( DdManager * dd, DdNode * bVars ); - -/**AutomaticEnd***************************************************************/ - - - -ABC_NAMESPACE_HEADER_END - - - -#endif /* __EXTRA_H__ */ diff --git a/src/misc/extra/extraBddAuto.c b/src/misc/extra/extraBddAuto.c deleted file mode 100644 index 5fb38aec..00000000 --- a/src/misc/extra/extraBddAuto.c +++ /dev/null @@ -1,1563 +0,0 @@ -/**CFile**************************************************************** - - FileName [extraBddAuto.c] - - PackageName [extra] - - Synopsis [Computation of autosymmetries.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - September 1, 2003.] - - Revision [$Id: extraBddAuto.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $] - -***********************************************************************/ - -#include "extraBdd.h" - -ABC_NAMESPACE_IMPL_START - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticEnd***************************************************************/ - - -/* - LinearSpace(f) = Space(f,f) - - Space(f,g) - { - if ( f = const ) - { - if ( f = g ) return 1; - else return 0; - } - if ( g = const ) return 0; - return x' * Space(fx',gx') * Space(fx,gx) + x * Space(fx',gx) * Space(fx,gx'); - } - - Equations(s) = Pos(s) + Neg(s); - - Pos(s) - { - if ( s = 0 ) return 1; - if ( s = 1 ) return 0; - if ( sx'= 0 ) return Pos(sx) + x; - if ( sx = 0 ) return Pos(sx'); - return 1 * [Pos(sx') & Pos(sx)] + x * [Pos(sx') & Neg(sx)]; - } - - Neg(s) - { - if ( s = 0 ) return 1; - if ( s = 1 ) return 0; - if ( sx'= 0 ) return Neg(sx); - if ( sx = 0 ) return Neg(sx') + x; - return 1 * [Neg(sx') & Neg(sx)] + x * [Neg(sx') & Pos(sx)]; - } - - - SpaceP(A) - { - if ( A = 0 ) return 1; - if ( A = 1 ) return 1; - return x' * SpaceP(Ax') * SpaceP(Ax) + x * SpaceP(Ax') * SpaceN(Ax); - } - - SpaceN(A) - { - if ( A = 0 ) return 1; - if ( A = 1 ) return 0; - return x' * SpaceN(Ax') * SpaceN(Ax) + x * SpaceN(Ax') * SpaceP(Ax); - } - - - LinInd(A) - { - if ( A = const ) return 1; - if ( !LinInd(Ax') ) return 0; - if ( !LinInd(Ax) ) return 0; - if ( LinSumOdd(Ax') & LinSumEven(Ax) != 0 ) return 0; - if ( LinSumEven(Ax') & LinSumEven(Ax) != 0 ) return 0; - return 1; - } - - LinSumOdd(A) - { - if ( A = 0 ) return 0; // Odd0 ---e-- Odd1 - if ( A = 1 ) return 1; // \ o - Odd0 = LinSumOdd(Ax'); // x is absent // \ - Even0 = LinSumEven(Ax'); // x is absent // / o - Odd1 = LinSumOdd(Ax); // x is present // Even0 ---e-- Even1 - Even1 = LinSumEven(Ax); // x is absent - return 1 * [Odd0 + ExorP(Odd0, Even1)] + x * [Odd1 + ExorP(Odd1, Even0)]; - } - - LinSumEven(A) - { - if ( A = 0 ) return 0; - if ( A = 1 ) return 0; - Odd0 = LinSumOdd(Ax'); // x is absent - Even0 = LinSumEven(Ax'); // x is absent - Odd1 = LinSumOdd(Ax); // x is present - Even1 = LinSumEven(Ax); // x is absent - return 1 * [Even0 + Even1 + ExorP(Even0, Even1)] + x * [ExorP(Odd0, Odd1)]; - } - -*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddSpaceFromFunctionFast( DdManager * dd, DdNode * bFunc ) -{ - int * pSupport; - int * pPermute; - int * pPermuteBack; - DdNode ** pCompose; - DdNode * bCube, * bTemp; - DdNode * bSpace, * bFunc1, * bFunc2, * bSpaceShift; - int nSupp, Counter; - int i, lev; - - // get the support - pSupport = ABC_ALLOC( int, ddMax(dd->size,dd->sizeZ) ); - Extra_SupportArray( dd, bFunc, pSupport ); - nSupp = 0; - for ( i = 0; i < dd->size; i++ ) - if ( pSupport[i] ) - nSupp++; - - // make sure the manager has enough variables - if ( 2*nSupp > dd->size ) - { - printf( "Cannot derive linear space, because DD manager does not have enough variables.\n" ); - fflush( stdout ); - ABC_FREE( pSupport ); - return NULL; - } - - // create the permutation arrays - pPermute = ABC_ALLOC( int, dd->size ); - pPermuteBack = ABC_ALLOC( int, dd->size ); - pCompose = ABC_ALLOC( DdNode *, dd->size ); - for ( i = 0; i < dd->size; i++ ) - { - pPermute[i] = i; - pPermuteBack[i] = i; - pCompose[i] = dd->vars[i]; Cudd_Ref( pCompose[i] ); - } - - // remap the function in such a way that the variables are interleaved - Counter = 0; - bCube = b1; Cudd_Ref( bCube ); - for ( lev = 0; lev < dd->size; lev++ ) - if ( pSupport[ dd->invperm[lev] ] ) - { // var "dd->invperm[lev]" on level "lev" should go to level 2*Counter; - pPermute[ dd->invperm[lev] ] = dd->invperm[2*Counter]; - // var from level 2*Counter+1 should go back to the place of this var - pPermuteBack[ dd->invperm[2*Counter+1] ] = dd->invperm[lev]; - // the permutation should be defined in such a way that variable - // on level 2*Counter is replaced by an EXOR of itself and var on the next level - Cudd_Deref( pCompose[ dd->invperm[2*Counter] ] ); - pCompose[ dd->invperm[2*Counter] ] = - Cudd_bddXor( dd, dd->vars[ dd->invperm[2*Counter] ], dd->vars[ dd->invperm[2*Counter+1] ] ); - Cudd_Ref( pCompose[ dd->invperm[2*Counter] ] ); - // add this variable to the cube - bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[ dd->invperm[2*Counter] ] ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( dd, bTemp ); - // increment the counter - Counter ++; - } - - // permute the functions - bFunc1 = Cudd_bddPermute( dd, bFunc, pPermute ); Cudd_Ref( bFunc1 ); - // compose to gate the function depending on both vars - bFunc2 = Cudd_bddVectorCompose( dd, bFunc1, pCompose ); Cudd_Ref( bFunc2 ); - // gate the vector space - // L(a) = ForAll x [ F(x) = F(x+a) ] = Not( Exist x [ F(x) (+) F(x+a) ] ) - bSpaceShift = Cudd_bddXorExistAbstract( dd, bFunc1, bFunc2, bCube ); Cudd_Ref( bSpaceShift ); - bSpaceShift = Cudd_Not( bSpaceShift ); - // permute the space back into the original mapping - bSpace = Cudd_bddPermute( dd, bSpaceShift, pPermuteBack ); Cudd_Ref( bSpace ); - Cudd_RecursiveDeref( dd, bFunc1 ); - Cudd_RecursiveDeref( dd, bFunc2 ); - Cudd_RecursiveDeref( dd, bSpaceShift ); - Cudd_RecursiveDeref( dd, bCube ); - - for ( i = 0; i < dd->size; i++ ) - Cudd_RecursiveDeref( dd, pCompose[i] ); - ABC_FREE( pPermute ); - ABC_FREE( pPermuteBack ); - ABC_FREE( pCompose ); - ABC_FREE( pSupport ); - - Cudd_Deref( bSpace ); - return bSpace; -} - - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG ) -{ - DdNode * bRes; - do { - dd->reordered = 0; - bRes = extraBddSpaceFromFunction( dd, bF, bG ); - } while (dd->reordered == 1); - return bRes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddSpaceFromFunctionPos( DdManager * dd, DdNode * bFunc ) -{ - DdNode * bRes; - do { - dd->reordered = 0; - bRes = extraBddSpaceFromFunctionPos( dd, bFunc ); - } while (dd->reordered == 1); - return bRes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddSpaceFromFunctionNeg( DdManager * dd, DdNode * bFunc ) -{ - DdNode * bRes; - do { - dd->reordered = 0; - bRes = extraBddSpaceFromFunctionNeg( dd, bFunc ); - } while (dd->reordered == 1); - return bRes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddSpaceCanonVars( DdManager * dd, DdNode * bSpace ) -{ - DdNode * bRes; - do { - dd->reordered = 0; - bRes = extraBddSpaceCanonVars( dd, bSpace ); - } while (dd->reordered == 1); - return bRes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddSpaceReduce( DdManager * dd, DdNode * bFunc, DdNode * bCanonVars ) -{ - DdNode * bNegCube; - DdNode * bResult; - bNegCube = Extra_bddSupportNegativeCube( dd, bCanonVars ); Cudd_Ref( bNegCube ); - bResult = Cudd_Cofactor( dd, bFunc, bNegCube ); Cudd_Ref( bResult ); - Cudd_RecursiveDeref( dd, bNegCube ); - Cudd_Deref( bResult ); - return bResult; -} - - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddSpaceEquations( DdManager * dd, DdNode * bSpace ) -{ - DdNode * zRes; - DdNode * zEquPos; - DdNode * zEquNeg; - zEquPos = Extra_bddSpaceEquationsPos( dd, bSpace ); Cudd_Ref( zEquPos ); - zEquNeg = Extra_bddSpaceEquationsNeg( dd, bSpace ); Cudd_Ref( zEquNeg ); - zRes = Cudd_zddUnion( dd, zEquPos, zEquNeg ); Cudd_Ref( zRes ); - Cudd_RecursiveDerefZdd( dd, zEquPos ); - Cudd_RecursiveDerefZdd( dd, zEquNeg ); - Cudd_Deref( zRes ); - return zRes; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddSpaceEquationsPos( DdManager * dd, DdNode * bSpace ) -{ - DdNode * zRes; - do { - dd->reordered = 0; - zRes = extraBddSpaceEquationsPos( dd, bSpace ); - } while (dd->reordered == 1); - return zRes; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddSpaceEquationsNeg( DdManager * dd, DdNode * bSpace ) -{ - DdNode * zRes; - do { - dd->reordered = 0; - zRes = extraBddSpaceEquationsNeg( dd, bSpace ); - } while (dd->reordered == 1); - return zRes; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddSpaceFromMatrixPos( DdManager * dd, DdNode * zA ) -{ - DdNode * bRes; - do { - dd->reordered = 0; - bRes = extraBddSpaceFromMatrixPos( dd, zA ); - } while (dd->reordered == 1); - return bRes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA ) -{ - DdNode * bRes; - do { - dd->reordered = 0; - bRes = extraBddSpaceFromMatrixNeg( dd, zA ); - } while (dd->reordered == 1); - return bRes; -} - -/**Function************************************************************* - - Synopsis [Counts the number of literals in one combination.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_zddLitCountComb( DdManager * dd, DdNode * zComb ) -{ - int Counter; - if ( zComb == z0 ) - return 0; - Counter = 0; - for ( ; zComb != z1; zComb = cuddT(zComb) ) - Counter++; - return Counter; -} - -/**Function************************************************************* - - Synopsis [] - - Description [Returns the array of ZDDs with the number equal to the number of - vars in the DD manager. If the given var is non-canonical, this array contains - the referenced ZDD representing literals in the corresponding EXOR equation.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode ** Extra_bddSpaceExorGates( DdManager * dd, DdNode * bFuncRed, DdNode * zEquations ) -{ - DdNode ** pzRes; - int * pVarsNonCan; - DdNode * zEquRem; - int iVarNonCan; - DdNode * zExor, * zTemp; - - // get the set of non-canonical variables - pVarsNonCan = ABC_ALLOC( int, ddMax(dd->size,dd->sizeZ) ); - Extra_SupportArray( dd, bFuncRed, pVarsNonCan ); - - // allocate storage for the EXOR sets - pzRes = ABC_ALLOC( DdNode *, dd->size ); - memset( pzRes, 0, sizeof(DdNode *) * dd->size ); - - // go through all the equations - zEquRem = zEquations; Cudd_Ref( zEquRem ); - while ( zEquRem != z0 ) - { - // extract one product - zExor = Extra_zddSelectOneSubset( dd, zEquRem ); Cudd_Ref( zExor ); - // remove it from the set - zEquRem = Cudd_zddDiff( dd, zTemp = zEquRem, zExor ); Cudd_Ref( zEquRem ); - Cudd_RecursiveDerefZdd( dd, zTemp ); - - // locate the non-canonical variable - iVarNonCan = -1; - for ( zTemp = zExor; zTemp != z1; zTemp = cuddT(zTemp) ) - { - if ( pVarsNonCan[zTemp->index/2] == 1 ) - { - assert( iVarNonCan == -1 ); - iVarNonCan = zTemp->index/2; - } - } - assert( iVarNonCan != -1 ); - - if ( Extra_zddLitCountComb( dd, zExor ) > 1 ) - pzRes[ iVarNonCan ] = zExor; // takes ref - else - Cudd_RecursiveDerefZdd( dd, zExor ); - } - Cudd_RecursiveDerefZdd( dd, zEquRem ); - - ABC_FREE( pVarsNonCan ); - return pzRes; -} - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Performs the recursive steps of Extra_bddSpaceFromFunction.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * extraBddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG ) -{ - DdNode * bRes; - DdNode * bFR, * bGR; - - bFR = Cudd_Regular( bF ); - bGR = Cudd_Regular( bG ); - if ( cuddIsConstant(bFR) ) - { - if ( bF == bG ) - return b1; - else - return b0; - } - if ( cuddIsConstant(bGR) ) - return b0; - // both bFunc and bCore are not constants - - // the operation is commutative - normalize the problem - if ( (unsigned)(ABC_PTRUINT_T)bF > (unsigned)(ABC_PTRUINT_T)bG ) - return extraBddSpaceFromFunction(dd, bG, bF); - - - if ( (bRes = cuddCacheLookup2(dd, extraBddSpaceFromFunction, bF, bG)) ) - return bRes; - else - { - DdNode * bF0, * bF1; - DdNode * bG0, * bG1; - DdNode * bTemp1, * bTemp2; - DdNode * bRes0, * bRes1; - int LevelF, LevelG; - int index; - - LevelF = dd->perm[bFR->index]; - LevelG = dd->perm[bGR->index]; - if ( LevelF <= LevelG ) - { - index = dd->invperm[LevelF]; - if ( bFR != bF ) - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - } - else - { - index = dd->invperm[LevelG]; - bF0 = bF1 = bF; - } - - if ( LevelG <= LevelF ) - { - if ( bGR != bG ) - { - bG0 = Cudd_Not( cuddE(bGR) ); - bG1 = Cudd_Not( cuddT(bGR) ); - } - else - { - bG0 = cuddE(bGR); - bG1 = cuddT(bGR); - } - } - else - bG0 = bG1 = bG; - - bTemp1 = extraBddSpaceFromFunction( dd, bF0, bG0 ); - if ( bTemp1 == NULL ) - return NULL; - cuddRef( bTemp1 ); - - bTemp2 = extraBddSpaceFromFunction( dd, bF1, bG1 ); - if ( bTemp2 == NULL ) - { - Cudd_RecursiveDeref( dd, bTemp1 ); - return NULL; - } - cuddRef( bTemp2 ); - - - bRes0 = cuddBddAndRecur( dd, bTemp1, bTemp2 ); - if ( bRes0 == NULL ) - { - Cudd_RecursiveDeref( dd, bTemp1 ); - Cudd_RecursiveDeref( dd, bTemp2 ); - return NULL; - } - cuddRef( bRes0 ); - Cudd_RecursiveDeref( dd, bTemp1 ); - Cudd_RecursiveDeref( dd, bTemp2 ); - - - bTemp1 = extraBddSpaceFromFunction( dd, bF0, bG1 ); - if ( bTemp1 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - return NULL; - } - cuddRef( bTemp1 ); - - bTemp2 = extraBddSpaceFromFunction( dd, bF1, bG0 ); - if ( bTemp2 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bTemp1 ); - return NULL; - } - cuddRef( bTemp2 ); - - bRes1 = cuddBddAndRecur( dd, bTemp1, bTemp2 ); - if ( bRes1 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bTemp1 ); - Cudd_RecursiveDeref( dd, bTemp2 ); - return NULL; - } - cuddRef( bRes1 ); - Cudd_RecursiveDeref( dd, bTemp1 ); - Cudd_RecursiveDeref( dd, bTemp2 ); - - - - // consider the case when Res0 and Res1 are the same node - if ( bRes0 == bRes1 ) - bRes = bRes1; - // consider the case when Res1 is complemented - else if ( Cudd_IsComplement(bRes1) ) - { - bRes = cuddUniqueInter(dd, index, Cudd_Not(bRes1), Cudd_Not(bRes0)); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref(dd,bRes0); - Cudd_RecursiveDeref(dd,bRes1); - return NULL; - } - bRes = Cudd_Not(bRes); - } - else - { - bRes = cuddUniqueInter( dd, index, bRes1, bRes0 ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref(dd,bRes0); - Cudd_RecursiveDeref(dd,bRes1); - return NULL; - } - } - cuddDeref( bRes0 ); - cuddDeref( bRes1 ); - - // insert the result into cache - cuddCacheInsert2(dd, extraBddSpaceFromFunction, bF, bG, bRes); - return bRes; - } -} /* end of extraBddSpaceFromFunction */ - - - -/**Function************************************************************* - - Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * extraBddSpaceFromFunctionPos( DdManager * dd, DdNode * bF ) -{ - DdNode * bRes, * bFR; - statLine( dd ); - - bFR = Cudd_Regular(bF); - if ( cuddIsConstant(bFR) ) - return b1; - - if ( (bRes = cuddCacheLookup1(dd, extraBddSpaceFromFunctionPos, bF)) ) - return bRes; - else - { - DdNode * bF0, * bF1; - DdNode * bPos0, * bPos1; - DdNode * bNeg0, * bNeg1; - DdNode * bRes0, * bRes1; - - if ( bFR != bF ) // bF is complemented - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - - - bPos0 = extraBddSpaceFromFunctionPos( dd, bF0 ); - if ( bPos0 == NULL ) - return NULL; - cuddRef( bPos0 ); - - bPos1 = extraBddSpaceFromFunctionPos( dd, bF1 ); - if ( bPos1 == NULL ) - { - Cudd_RecursiveDeref( dd, bPos0 ); - return NULL; - } - cuddRef( bPos1 ); - - bRes0 = cuddBddAndRecur( dd, bPos0, bPos1 ); - if ( bRes0 == NULL ) - { - Cudd_RecursiveDeref( dd, bPos0 ); - Cudd_RecursiveDeref( dd, bPos1 ); - return NULL; - } - cuddRef( bRes0 ); - Cudd_RecursiveDeref( dd, bPos0 ); - Cudd_RecursiveDeref( dd, bPos1 ); - - - bNeg0 = extraBddSpaceFromFunctionNeg( dd, bF0 ); - if ( bNeg0 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - return NULL; - } - cuddRef( bNeg0 ); - - bNeg1 = extraBddSpaceFromFunctionNeg( dd, bF1 ); - if ( bNeg1 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bNeg0 ); - return NULL; - } - cuddRef( bNeg1 ); - - bRes1 = cuddBddAndRecur( dd, bNeg0, bNeg1 ); - if ( bRes1 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bNeg0 ); - Cudd_RecursiveDeref( dd, bNeg1 ); - return NULL; - } - cuddRef( bRes1 ); - Cudd_RecursiveDeref( dd, bNeg0 ); - Cudd_RecursiveDeref( dd, bNeg1 ); - - - // consider the case when Res0 and Res1 are the same node - if ( bRes0 == bRes1 ) - bRes = bRes1; - // consider the case when Res1 is complemented - else if ( Cudd_IsComplement(bRes1) ) - { - bRes = cuddUniqueInter( dd, bFR->index, Cudd_Not(bRes1), Cudd_Not(bRes0) ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref(dd,bRes0); - Cudd_RecursiveDeref(dd,bRes1); - return NULL; - } - bRes = Cudd_Not(bRes); - } - else - { - bRes = cuddUniqueInter( dd, bFR->index, bRes1, bRes0 ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref(dd,bRes0); - Cudd_RecursiveDeref(dd,bRes1); - return NULL; - } - } - cuddDeref( bRes0 ); - cuddDeref( bRes1 ); - - cuddCacheInsert1( dd, extraBddSpaceFromFunctionPos, bF, bRes ); - return bRes; - } -} - - - -/**Function************************************************************* - - Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * extraBddSpaceFromFunctionNeg( DdManager * dd, DdNode * bF ) -{ - DdNode * bRes, * bFR; - statLine( dd ); - - bFR = Cudd_Regular(bF); - if ( cuddIsConstant(bFR) ) - return b0; - - if ( (bRes = cuddCacheLookup1(dd, extraBddSpaceFromFunctionNeg, bF)) ) - return bRes; - else - { - DdNode * bF0, * bF1; - DdNode * bPos0, * bPos1; - DdNode * bNeg0, * bNeg1; - DdNode * bRes0, * bRes1; - - if ( bFR != bF ) // bF is complemented - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - - - bPos0 = extraBddSpaceFromFunctionNeg( dd, bF0 ); - if ( bPos0 == NULL ) - return NULL; - cuddRef( bPos0 ); - - bPos1 = extraBddSpaceFromFunctionNeg( dd, bF1 ); - if ( bPos1 == NULL ) - { - Cudd_RecursiveDeref( dd, bPos0 ); - return NULL; - } - cuddRef( bPos1 ); - - bRes0 = cuddBddAndRecur( dd, bPos0, bPos1 ); - if ( bRes0 == NULL ) - { - Cudd_RecursiveDeref( dd, bPos0 ); - Cudd_RecursiveDeref( dd, bPos1 ); - return NULL; - } - cuddRef( bRes0 ); - Cudd_RecursiveDeref( dd, bPos0 ); - Cudd_RecursiveDeref( dd, bPos1 ); - - - bNeg0 = extraBddSpaceFromFunctionPos( dd, bF0 ); - if ( bNeg0 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - return NULL; - } - cuddRef( bNeg0 ); - - bNeg1 = extraBddSpaceFromFunctionPos( dd, bF1 ); - if ( bNeg1 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bNeg0 ); - return NULL; - } - cuddRef( bNeg1 ); - - bRes1 = cuddBddAndRecur( dd, bNeg0, bNeg1 ); - if ( bRes1 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bNeg0 ); - Cudd_RecursiveDeref( dd, bNeg1 ); - return NULL; - } - cuddRef( bRes1 ); - Cudd_RecursiveDeref( dd, bNeg0 ); - Cudd_RecursiveDeref( dd, bNeg1 ); - - - // consider the case when Res0 and Res1 are the same node - if ( bRes0 == bRes1 ) - bRes = bRes1; - // consider the case when Res1 is complemented - else if ( Cudd_IsComplement(bRes1) ) - { - bRes = cuddUniqueInter( dd, bFR->index, Cudd_Not(bRes1), Cudd_Not(bRes0) ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref(dd,bRes0); - Cudd_RecursiveDeref(dd,bRes1); - return NULL; - } - bRes = Cudd_Not(bRes); - } - else - { - bRes = cuddUniqueInter( dd, bFR->index, bRes1, bRes0 ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref(dd,bRes0); - Cudd_RecursiveDeref(dd,bRes1); - return NULL; - } - } - cuddDeref( bRes0 ); - cuddDeref( bRes1 ); - - cuddCacheInsert1( dd, extraBddSpaceFromFunctionNeg, bF, bRes ); - return bRes; - } -} - - - -/**Function************************************************************* - - Synopsis [Performs the recursive step of Extra_bddSpaceCanonVars().] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * extraBddSpaceCanonVars( DdManager * dd, DdNode * bF ) -{ - DdNode * bRes, * bFR; - statLine( dd ); - - bFR = Cudd_Regular(bF); - if ( cuddIsConstant(bFR) ) - return bF; - - if ( (bRes = cuddCacheLookup1(dd, extraBddSpaceCanonVars, bF)) ) - return bRes; - else - { - DdNode * bF0, * bF1; - DdNode * bRes, * bRes0; - - if ( bFR != bF ) // bF is complemented - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - - if ( bF0 == b0 ) - { - bRes = extraBddSpaceCanonVars( dd, bF1 ); - if ( bRes == NULL ) - return NULL; - } - else if ( bF1 == b0 ) - { - bRes = extraBddSpaceCanonVars( dd, bF0 ); - if ( bRes == NULL ) - return NULL; - } - else - { - bRes0 = extraBddSpaceCanonVars( dd, bF0 ); - if ( bRes0 == NULL ) - return NULL; - cuddRef( bRes0 ); - - bRes = cuddUniqueInter( dd, bFR->index, bRes0, b0 ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref( dd,bRes0 ); - return NULL; - } - cuddDeref( bRes0 ); - } - - cuddCacheInsert1( dd, extraBddSpaceCanonVars, bF, bRes ); - return bRes; - } -} - -/**Function************************************************************* - - Synopsis [Performs the recursive step of Extra_bddSpaceEquationsPos().] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * extraBddSpaceEquationsPos( DdManager * dd, DdNode * bF ) -{ - DdNode * zRes; - statLine( dd ); - - if ( bF == b0 ) - return z1; - if ( bF == b1 ) - return z0; - - if ( (zRes = cuddCacheLookup1Zdd(dd, extraBddSpaceEquationsPos, bF)) ) - return zRes; - else - { - DdNode * bFR, * bF0, * bF1; - DdNode * zPos0, * zPos1, * zNeg1; - DdNode * zRes, * zRes0, * zRes1; - - bFR = Cudd_Regular(bF); - if ( bFR != bF ) // bF is complemented - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - - if ( bF0 == b0 ) - { - zRes1 = extraBddSpaceEquationsPos( dd, bF1 ); - if ( zRes1 == NULL ) - return NULL; - cuddRef( zRes1 ); - - // add the current element to the set - zRes = cuddZddGetNode( dd, 2*bFR->index, z1, zRes1 ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zRes1); - return NULL; - } - cuddDeref( zRes1 ); - } - else if ( bF1 == b0 ) - { - zRes = extraBddSpaceEquationsPos( dd, bF0 ); - if ( zRes == NULL ) - return NULL; - } - else - { - zPos0 = extraBddSpaceEquationsPos( dd, bF0 ); - if ( zPos0 == NULL ) - return NULL; - cuddRef( zPos0 ); - - zPos1 = extraBddSpaceEquationsPos( dd, bF1 ); - if ( zPos1 == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zPos0); - return NULL; - } - cuddRef( zPos1 ); - - zNeg1 = extraBddSpaceEquationsNeg( dd, bF1 ); - if ( zNeg1 == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zPos0); - Cudd_RecursiveDerefZdd(dd, zPos1); - return NULL; - } - cuddRef( zNeg1 ); - - - zRes0 = cuddZddIntersect( dd, zPos0, zPos1 ); - if ( zRes0 == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zNeg1); - Cudd_RecursiveDerefZdd(dd, zPos0); - Cudd_RecursiveDerefZdd(dd, zPos1); - return NULL; - } - cuddRef( zRes0 ); - - zRes1 = cuddZddIntersect( dd, zPos0, zNeg1 ); - if ( zRes1 == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zRes0); - Cudd_RecursiveDerefZdd(dd, zNeg1); - Cudd_RecursiveDerefZdd(dd, zPos0); - Cudd_RecursiveDerefZdd(dd, zPos1); - return NULL; - } - cuddRef( zRes1 ); - Cudd_RecursiveDerefZdd(dd, zNeg1); - Cudd_RecursiveDerefZdd(dd, zPos0); - Cudd_RecursiveDerefZdd(dd, zPos1); - // only zRes0 and zRes1 are refed at this point - - zRes = cuddZddGetNode( dd, 2*bFR->index, zRes1, zRes0 ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zRes0); - Cudd_RecursiveDerefZdd(dd, zRes1); - return NULL; - } - cuddDeref( zRes0 ); - cuddDeref( zRes1 ); - } - - cuddCacheInsert1( dd, extraBddSpaceEquationsPos, bF, zRes ); - return zRes; - } -} - - -/**Function************************************************************* - - Synopsis [Performs the recursive step of Extra_bddSpaceEquationsNev().] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * extraBddSpaceEquationsNeg( DdManager * dd, DdNode * bF ) -{ - DdNode * zRes; - statLine( dd ); - - if ( bF == b0 ) - return z1; - if ( bF == b1 ) - return z0; - - if ( (zRes = cuddCacheLookup1Zdd(dd, extraBddSpaceEquationsNeg, bF)) ) - return zRes; - else - { - DdNode * bFR, * bF0, * bF1; - DdNode * zPos0, * zPos1, * zNeg1; - DdNode * zRes, * zRes0, * zRes1; - - bFR = Cudd_Regular(bF); - if ( bFR != bF ) // bF is complemented - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - - if ( bF0 == b0 ) - { - zRes = extraBddSpaceEquationsNeg( dd, bF1 ); - if ( zRes == NULL ) - return NULL; - } - else if ( bF1 == b0 ) - { - zRes0 = extraBddSpaceEquationsNeg( dd, bF0 ); - if ( zRes0 == NULL ) - return NULL; - cuddRef( zRes0 ); - - // add the current element to the set - zRes = cuddZddGetNode( dd, 2*bFR->index, z1, zRes0 ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zRes0); - return NULL; - } - cuddDeref( zRes0 ); - } - else - { - zPos0 = extraBddSpaceEquationsNeg( dd, bF0 ); - if ( zPos0 == NULL ) - return NULL; - cuddRef( zPos0 ); - - zPos1 = extraBddSpaceEquationsNeg( dd, bF1 ); - if ( zPos1 == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zPos0); - return NULL; - } - cuddRef( zPos1 ); - - zNeg1 = extraBddSpaceEquationsPos( dd, bF1 ); - if ( zNeg1 == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zPos0); - Cudd_RecursiveDerefZdd(dd, zPos1); - return NULL; - } - cuddRef( zNeg1 ); - - - zRes0 = cuddZddIntersect( dd, zPos0, zPos1 ); - if ( zRes0 == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zNeg1); - Cudd_RecursiveDerefZdd(dd, zPos0); - Cudd_RecursiveDerefZdd(dd, zPos1); - return NULL; - } - cuddRef( zRes0 ); - - zRes1 = cuddZddIntersect( dd, zPos0, zNeg1 ); - if ( zRes1 == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zRes0); - Cudd_RecursiveDerefZdd(dd, zNeg1); - Cudd_RecursiveDerefZdd(dd, zPos0); - Cudd_RecursiveDerefZdd(dd, zPos1); - return NULL; - } - cuddRef( zRes1 ); - Cudd_RecursiveDerefZdd(dd, zNeg1); - Cudd_RecursiveDerefZdd(dd, zPos0); - Cudd_RecursiveDerefZdd(dd, zPos1); - // only zRes0 and zRes1 are refed at this point - - zRes = cuddZddGetNode( dd, 2*bFR->index, zRes1, zRes0 ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zRes0); - Cudd_RecursiveDerefZdd(dd, zRes1); - return NULL; - } - cuddDeref( zRes0 ); - cuddDeref( zRes1 ); - } - - cuddCacheInsert1( dd, extraBddSpaceEquationsNeg, bF, zRes ); - return zRes; - } -} - - - - -/**Function************************************************************* - - Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * extraBddSpaceFromMatrixPos( DdManager * dd, DdNode * zA ) -{ - DdNode * bRes; - statLine( dd ); - - if ( zA == z0 ) - return b1; - if ( zA == z1 ) - return b1; - - if ( (bRes = cuddCacheLookup1(dd, extraBddSpaceFromMatrixPos, zA)) ) - return bRes; - else - { - DdNode * bP0, * bP1; - DdNode * bN0, * bN1; - DdNode * bRes0, * bRes1; - - bP0 = extraBddSpaceFromMatrixPos( dd, cuddE(zA) ); - if ( bP0 == NULL ) - return NULL; - cuddRef( bP0 ); - - bP1 = extraBddSpaceFromMatrixPos( dd, cuddT(zA) ); - if ( bP1 == NULL ) - { - Cudd_RecursiveDeref( dd, bP0 ); - return NULL; - } - cuddRef( bP1 ); - - bRes0 = cuddBddAndRecur( dd, bP0, bP1 ); - if ( bRes0 == NULL ) - { - Cudd_RecursiveDeref( dd, bP0 ); - Cudd_RecursiveDeref( dd, bP1 ); - return NULL; - } - cuddRef( bRes0 ); - Cudd_RecursiveDeref( dd, bP0 ); - Cudd_RecursiveDeref( dd, bP1 ); - - - bN0 = extraBddSpaceFromMatrixPos( dd, cuddE(zA) ); - if ( bN0 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - return NULL; - } - cuddRef( bN0 ); - - bN1 = extraBddSpaceFromMatrixNeg( dd, cuddT(zA) ); - if ( bN1 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bN0 ); - return NULL; - } - cuddRef( bN1 ); - - bRes1 = cuddBddAndRecur( dd, bN0, bN1 ); - if ( bRes1 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bN0 ); - Cudd_RecursiveDeref( dd, bN1 ); - return NULL; - } - cuddRef( bRes1 ); - Cudd_RecursiveDeref( dd, bN0 ); - Cudd_RecursiveDeref( dd, bN1 ); - - - // consider the case when Res0 and Res1 are the same node - if ( bRes0 == bRes1 ) - bRes = bRes1; - // consider the case when Res1 is complemented - else if ( Cudd_IsComplement(bRes1) ) - { - bRes = cuddUniqueInter( dd, zA->index/2, Cudd_Not(bRes1), Cudd_Not(bRes0) ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref(dd,bRes0); - Cudd_RecursiveDeref(dd,bRes1); - return NULL; - } - bRes = Cudd_Not(bRes); - } - else - { - bRes = cuddUniqueInter( dd, zA->index/2, bRes1, bRes0 ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref(dd,bRes0); - Cudd_RecursiveDeref(dd,bRes1); - return NULL; - } - } - cuddDeref( bRes0 ); - cuddDeref( bRes1 ); - - cuddCacheInsert1( dd, extraBddSpaceFromMatrixPos, zA, bRes ); - return bRes; - } -} - - -/**Function************************************************************* - - Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * extraBddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA ) -{ - DdNode * bRes; - statLine( dd ); - - if ( zA == z0 ) - return b1; - if ( zA == z1 ) - return b0; - - if ( (bRes = cuddCacheLookup1(dd, extraBddSpaceFromMatrixNeg, zA)) ) - return bRes; - else - { - DdNode * bP0, * bP1; - DdNode * bN0, * bN1; - DdNode * bRes0, * bRes1; - - bP0 = extraBddSpaceFromMatrixNeg( dd, cuddE(zA) ); - if ( bP0 == NULL ) - return NULL; - cuddRef( bP0 ); - - bP1 = extraBddSpaceFromMatrixNeg( dd, cuddT(zA) ); - if ( bP1 == NULL ) - { - Cudd_RecursiveDeref( dd, bP0 ); - return NULL; - } - cuddRef( bP1 ); - - bRes0 = cuddBddAndRecur( dd, bP0, bP1 ); - if ( bRes0 == NULL ) - { - Cudd_RecursiveDeref( dd, bP0 ); - Cudd_RecursiveDeref( dd, bP1 ); - return NULL; - } - cuddRef( bRes0 ); - Cudd_RecursiveDeref( dd, bP0 ); - Cudd_RecursiveDeref( dd, bP1 ); - - - bN0 = extraBddSpaceFromMatrixNeg( dd, cuddE(zA) ); - if ( bN0 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - return NULL; - } - cuddRef( bN0 ); - - bN1 = extraBddSpaceFromMatrixPos( dd, cuddT(zA) ); - if ( bN1 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bN0 ); - return NULL; - } - cuddRef( bN1 ); - - bRes1 = cuddBddAndRecur( dd, bN0, bN1 ); - if ( bRes1 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bN0 ); - Cudd_RecursiveDeref( dd, bN1 ); - return NULL; - } - cuddRef( bRes1 ); - Cudd_RecursiveDeref( dd, bN0 ); - Cudd_RecursiveDeref( dd, bN1 ); - - - // consider the case when Res0 and Res1 are the same node - if ( bRes0 == bRes1 ) - bRes = bRes1; - // consider the case when Res1 is complemented - else if ( Cudd_IsComplement(bRes1) ) - { - bRes = cuddUniqueInter( dd, zA->index/2, Cudd_Not(bRes1), Cudd_Not(bRes0) ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref(dd,bRes0); - Cudd_RecursiveDeref(dd,bRes1); - return NULL; - } - bRes = Cudd_Not(bRes); - } - else - { - bRes = cuddUniqueInter( dd, zA->index/2, bRes1, bRes0 ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref(dd,bRes0); - Cudd_RecursiveDeref(dd,bRes1); - return NULL; - } - } - cuddDeref( bRes0 ); - cuddDeref( bRes1 ); - - cuddCacheInsert1( dd, extraBddSpaceFromMatrixNeg, zA, bRes ); - return bRes; - } -} - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - -ABC_NAMESPACE_IMPL_END - diff --git a/src/misc/extra/extraBddCas.c b/src/misc/extra/extraBddCas.c deleted file mode 100644 index 024e4462..00000000 --- a/src/misc/extra/extraBddCas.c +++ /dev/null @@ -1,1235 +0,0 @@ -/**CFile**************************************************************** - - FileName [extraBddCas.c] - - PackageName [extra] - - Synopsis [Procedures related to LUT cascade synthesis.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - September 1, 2003.] - - Revision [$Id: extraBddCas.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $] - -***********************************************************************/ - -#include "extraBdd.h" - -ABC_NAMESPACE_IMPL_START - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -// the table to store cofactor operations -#define _TABLESIZE_COF 51113 -typedef struct -{ - unsigned Sign; - DdNode * Arg1; -} _HashEntry_cof; -_HashEntry_cof HHTable1[_TABLESIZE_COF]; - -// the table to store the result of computation of the number of minterms -#define _TABLESIZE_MINT 15113 -typedef struct -{ - DdNode * Arg1; - unsigned Arg2; - unsigned Res; -} _HashEntry_mint; -_HashEntry_mint HHTable2[_TABLESIZE_MINT]; - -typedef struct -{ - int nEdges; // the number of in-coming edges of the node - DdNode * bSum; // the sum of paths of the incoming edges -} traventry; - -// the signature used for hashing -static unsigned s_Signature = 1; - -static int s_CutLevel = 0; - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -// because the proposed solution to the optimal encoding problem has exponential complexity -// we limit the depth of the branch and bound procedure to 5 levels -static int s_MaxDepth = 5; - -static int s_nVarsBest; // the number of vars in the best ordering -static int s_VarOrderBest[32]; // storing the best ordering of vars in the "simple encoding" -static int s_VarOrderCur[32]; // storing the current ordering of vars - -// the place to store the supports of the encoded function -static DdNode * s_Field[8][256]; // the size should be K, 2^K, where K is no less than MaxDepth -static DdNode * s_Encoded; // this is the original function -static DdNode * s_VarAll; // the set of all column variables -static int s_MultiStart; // the total number of encoding variables used -// the array field now stores the supports - -static DdNode ** s_pbTemp; // the temporary storage for the columns - -static int s_BackTracks; -static int s_BackTrackLimit = 100; - -static DdNode * s_Terminal; // the terminal value for counting minterms - - -static int s_EncodingVarsLevel; - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdNode * CreateTheCodes_rec( DdManager * dd, DdNode * bEncoded, int Level, DdNode ** pCVars ); -static void EvaluateEncodings_rec( DdManager * dd, DdNode * bVarsCol, int nVarsCol, int nMulti, int Level ); -// functions called from EvaluateEncodings_rec() -static DdNode * ComputeVarSetAndCountMinterms( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost ); -static DdNode * ComputeVarSetAndCountMinterms2( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost ); -unsigned Extra_CountCofactorMinterms( DdManager * dd, DdNode * bFunc, DdNode * bVarsCof, DdNode * bVarsAll ); -static unsigned Extra_CountMintermsSimple( DdNode * bFunc, unsigned max ); - -static void CountNodeVisits_rec( DdManager * dd, DdNode * aFunc, st__table * Visited ); -static void CollectNodesAndComputePaths_rec( DdManager * dd, DdNode * aFunc, DdNode * bCube, st__table * Visited, st__table * CutNodes ); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Performs the binary encoding of the set of function using the given vars.] - - Description [Performs a straight binary encoding of the set of functions using - the variable cubes formed from the given set of variables. ] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Extra_bddEncodingBinary( - DdManager * dd, - DdNode ** pbFuncs, // pbFuncs is the array of columns to be encoded - int nFuncs, // nFuncs is the number of columns in the array - DdNode ** pbVars, // pbVars is the array of variables to use for the codes - int nVars ) // nVars is the column multiplicity, [log2(nFuncs)] -{ - int i; - DdNode * bResult; - DdNode * bCube, * bTemp, * bProd; - - assert( nVars >= Abc_Base2Log(nFuncs) ); - - bResult = b0; Cudd_Ref( bResult ); - for ( i = 0; i < nFuncs; i++ ) - { - bCube = Extra_bddBitsToCube( dd, i, nVars, pbVars, 1 ); Cudd_Ref( bCube ); - bProd = Cudd_bddAnd( dd, bCube, pbFuncs[i] ); Cudd_Ref( bProd ); - Cudd_RecursiveDeref( dd, bCube ); - - bResult = Cudd_bddOr( dd, bProd, bTemp = bResult ); Cudd_Ref( bResult ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bProd ); - } - - Cudd_Deref( bResult ); - return bResult; -} /* end of Extra_bddEncodingBinary */ - - -/**Function******************************************************************** - - Synopsis [Solves the column encoding problem using a sophisticated method.] - - Description [The encoding is based on the idea of deriving functions which - depend on only one variable, which corresponds to the case of non-disjoint - decompostion. It is assumed that the variables pCVars are ordered below the variables - representing the solumns, and the first variable pCVars[0] is the topmost one.] - - SideEffects [] - - SeeAlso [Extra_bddEncodingBinary] - -******************************************************************************/ - -DdNode * -Extra_bddEncodingNonStrict( - DdManager * dd, - DdNode ** pbColumns, // pbColumns is the array of columns to be encoded; - int nColumns, // nColumns is the number of columns in the array - DdNode * bVarsCol, // bVarsCol is the cube of variables on which the columns depend - DdNode ** pCVars, // pCVars is the array of variables to use for the codes - int nMulti, // nMulti is the column multiplicity, [log2(nColumns)] - int * pSimple ) // pSimple gets the number of code variables taken from the input varibles without change -{ - DdNode * bEncoded, * bResult; - int nVarsCol = Cudd_SupportSize(dd,bVarsCol); - abctime clk; - - // cannot work with more that 32-bit codes - assert( nMulti < 32 ); - - // perform the preliminary encoding using the straight binary code - bEncoded = Extra_bddEncodingBinary( dd, pbColumns, nColumns, pCVars, nMulti ); Cudd_Ref( bEncoded ); - //printf( "Node count = %d", Cudd_DagSize(bEncoded) ); - - // set the backgroup value for counting minterms - s_Terminal = b0; - // set the level of the encoding variables - s_EncodingVarsLevel = dd->invperm[pCVars[0]->index]; - - // the current number of backtracks - s_BackTracks = 0; - // the variables that are cofactored on the topmost level where everything starts (no vars) - s_Field[0][0] = b1; - // the size of the best set of "simple" encoding variables found so far - s_nVarsBest = 0; - - // set the relation to be accessible to traversal procedures - s_Encoded = bEncoded; - // the set of all vars to be accessible to traversal procedures - s_VarAll = bVarsCol; - // the column multiplicity - s_MultiStart = nMulti; - - - clk = Abc_Clock(); - // find the simplest encoding - if ( nColumns > 2 ) - EvaluateEncodings_rec( dd, bVarsCol, nVarsCol, nMulti, 1 ); -// printf( "The number of backtracks = %d\n", s_BackTracks ); -// s_EncSearchTime += Abc_Clock() - clk; - - // allocate the temporary storage for the columns - s_pbTemp = (DdNode **)ABC_ALLOC( char, nColumns * sizeof(DdNode *) ); - -// clk = Abc_Clock(); - bResult = CreateTheCodes_rec( dd, bEncoded, 0, pCVars ); Cudd_Ref( bResult ); -// s_EncComputeTime += Abc_Clock() - clk; - - // delocate the preliminarily encoded set - Cudd_RecursiveDeref( dd, bEncoded ); -// Cudd_RecursiveDeref( dd, aEncoded ); - - ABC_FREE( s_pbTemp ); - - *pSimple = s_nVarsBest; - Cudd_Deref( bResult ); - return bResult; -} - -/**Function******************************************************************** - - Synopsis [Collects the nodes under the cut and, for each node, computes the sum of paths leading to it from the root.] - - Description [The table returned contains the set of BDD nodes pointed to under the cut - and, for each node, the BDD of the sum of paths leading to this node from the root - The sums of paths in the table are referenced. CutLevel is the first DD level - considered to be under the cut.] - - SideEffects [] - - SeeAlso [Extra_bddNodePaths] - -******************************************************************************/ - st__table * Extra_bddNodePathsUnderCut( DdManager * dd, DdNode * bFunc, int CutLevel ) -{ - st__table * Visited; // temporary table to remember the visited nodes - st__table * CutNodes; // the result goes here - st__table * Result; // the result goes here - DdNode * aFunc; - - s_CutLevel = CutLevel; - - Result = st__init_table( st__ptrcmp, st__ptrhash);; - // the terminal cases - if ( Cudd_IsConstant( bFunc ) ) - { - if ( bFunc == b1 ) - { - st__insert( Result, (char*)b1, (char*)b1 ); - Cudd_Ref( b1 ); - Cudd_Ref( b1 ); - } - else - { - st__insert( Result, (char*)b0, (char*)b0 ); - Cudd_Ref( b0 ); - Cudd_Ref( b0 ); - } - return Result; - } - - // create the ADD to simplify processing (no complemented edges) - aFunc = Cudd_BddToAdd( dd, bFunc ); Cudd_Ref( aFunc ); - - // Step 1: Start the tables and collect information about the nodes above the cut - // this information tells how many edges point to each node - Visited = st__init_table( st__ptrcmp, st__ptrhash);; - CutNodes = st__init_table( st__ptrcmp, st__ptrhash);; - - CountNodeVisits_rec( dd, aFunc, Visited ); - - // Step 2: Traverse the BDD using the visited table and compute the sum of paths - CollectNodesAndComputePaths_rec( dd, aFunc, b1, Visited, CutNodes ); - - // at this point the table of cut nodes is ready and the table of visited is useless - { - st__generator * gen; - DdNode * aNode; - traventry * p; - st__foreach_item( Visited, gen, (const char**)&aNode, (char**)&p ) - { - Cudd_RecursiveDeref( dd, p->bSum ); - ABC_FREE( p ); - } - st__free_table( Visited ); - } - - // go through the table CutNodes and create the BDD and the path to be returned - { - st__generator * gen; - DdNode * aNode, * bNode, * bSum; - st__foreach_item( CutNodes, gen, (const char**)&aNode, (char**)&bSum) - { - // aNode is not referenced, because aFunc is holding it - bNode = Cudd_addBddPattern( dd, aNode ); Cudd_Ref( bNode ); - st__insert( Result, (char*)bNode, (char*)bSum ); - // the new table takes both refs - } - st__free_table( CutNodes ); - } - - // dereference the ADD - Cudd_RecursiveDeref( dd, aFunc ); - - // return the table - return Result; - -} /* end of Extra_bddNodePathsUnderCut */ - -/**Function******************************************************************** - - Synopsis [Collects the nodes under the cut in the ADD starting from the given set of ADD nodes.] - - Description [Takes the array, paNodes, of ADD nodes to start the traversal, - the array, pbCubes, of BDD cubes to start the traversal with in each node, - and the number, nNodes, of ADD nodes and BDD cubes in paNodes and pbCubes. - Returns the number of columns found. Fills in paNodesRes (pbCubesRes) - with the set of ADD columns (BDD paths). These arrays should be allocated - by the user.] - - SideEffects [] - - SeeAlso [Extra_bddNodePaths] - -******************************************************************************/ -int Extra_bddNodePathsUnderCutArray( DdManager * dd, DdNode ** paNodes, DdNode ** pbCubes, int nNodes, DdNode ** paNodesRes, DdNode ** pbCubesRes, int CutLevel ) -{ - st__table * Visited; // temporary table to remember the visited nodes - st__table * CutNodes; // the nodes under the cut go here - int i, Counter; - - s_CutLevel = CutLevel; - - // there should be some nodes - assert( nNodes > 0 ); - if ( nNodes == 1 && Cudd_IsConstant( paNodes[0] ) ) - { - if ( paNodes[0] == a1 ) - { - paNodesRes[0] = a1; Cudd_Ref( a1 ); - pbCubesRes[0] = pbCubes[0]; Cudd_Ref( pbCubes[0] ); - } - else - { - paNodesRes[0] = a0; Cudd_Ref( a0 ); - pbCubesRes[0] = pbCubes[0]; Cudd_Ref( pbCubes[0] ); - } - return 1; - } - - // Step 1: Start the table and collect information about the nodes above the cut - // this information tells how many edges point to each node - CutNodes = st__init_table( st__ptrcmp, st__ptrhash);; - Visited = st__init_table( st__ptrcmp, st__ptrhash);; - - for ( i = 0; i < nNodes; i++ ) - CountNodeVisits_rec( dd, paNodes[i], Visited ); - - // Step 2: Traverse the BDD using the visited table and compute the sum of paths - for ( i = 0; i < nNodes; i++ ) - CollectNodesAndComputePaths_rec( dd, paNodes[i], pbCubes[i], Visited, CutNodes ); - - // at this point, the table of cut nodes is ready and the table of visited is useless - { - st__generator * gen; - DdNode * aNode; - traventry * p; - st__foreach_item( Visited, gen, (const char**)&aNode, (char**)&p ) - { - Cudd_RecursiveDeref( dd, p->bSum ); - ABC_FREE( p ); - } - st__free_table( Visited ); - } - - // go through the table CutNodes and create the BDD and the path to be returned - { - st__generator * gen; - DdNode * aNode, * bSum; - Counter = 0; - st__foreach_item( CutNodes, gen, (const char**)&aNode, (char**)&bSum) - { - paNodesRes[Counter] = aNode; Cudd_Ref( aNode ); - pbCubesRes[Counter] = bSum; - Counter++; - } - st__free_table( CutNodes ); - } - - // return the number of cofactors found - return Counter; - -} /* end of Extra_bddNodePathsUnderCutArray */ - -/**Function************************************************************* - - Synopsis [Collects all the BDD nodes into the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void extraCollectNodes( DdNode * Func, st__table * tNodes ) -{ - DdNode * FuncR; - FuncR = Cudd_Regular(Func); - if ( st__find_or_add( tNodes, (char*)FuncR, NULL ) ) - return; - if ( cuddIsConstant(FuncR) ) - return; - extraCollectNodes( cuddE(FuncR), tNodes ); - extraCollectNodes( cuddT(FuncR), tNodes ); -} - -/**Function************************************************************* - - Synopsis [Collects all the nodes of one DD into the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - st__table * Extra_CollectNodes( DdNode * Func ) -{ - st__table * tNodes; - tNodes = st__init_table( st__ptrcmp, st__ptrhash ); - extraCollectNodes( Func, tNodes ); - return tNodes; -} - -/**Function************************************************************* - - Synopsis [Updates the topmost level from which the given node is referenced.] - - Description [Takes the table which maps each BDD nodes (including the constants) - into the topmost level on which this node counts as a cofactor. Takes the topmost - level, on which this node counts as a cofactor (see Extra_ProfileWidthFast(). - Takes the node, for which the table entry should be updated.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void extraProfileUpdateTopLevel( st__table * tNodeTopRef, int TopLevelNew, DdNode * node ) -{ - int * pTopLevel; - - if ( st__find_or_add( tNodeTopRef, (char*)node, (char***)&pTopLevel ) ) - { // the node is already referenced - // the current top level should be updated if it is larger than the new level - if ( *pTopLevel > TopLevelNew ) - *pTopLevel = TopLevelNew; - } - else - { // the node is not referenced - // its level should be set to the current new level - *pTopLevel = TopLevelNew; - } -} -/**Function************************************************************* - - Synopsis [Fast computation of the BDD profile.] - - Description [The array to store the profile is given by the user and should - contain at least as many entries as there is the maximum of the BDD/ZDD - size of the manager PLUS ONE. - When we say that the widths of the DD on level L is W, we mean the following. - Let us create the cut between the level L-1 and the level L and count the number - of different DD nodes pointed to across the cut. This number is the width W. - From this it follows the on level 0, the width is equal to the number of external - pointers to the considered DDs. If there is only one DD, then the profile on - level 0 is always 1. If this DD is rooted in the topmost variable, then the width - on level 1 is always 2, etc. The width at the level equal to dd->size is the - number of terminal nodes in the DD. (Because we consider the first level #0 - and the last level #dd->size, the profile array should contain dd->size+1 entries.) - ] - - SideEffects [This procedure will not work for BDDs w/ complement edges, only for ADDs and ZDDs] - - SeeAlso [] - -***********************************************************************/ -int Extra_ProfileWidth( DdManager * dd, DdNode * Func, int * pProfile, int CutLevel ) -{ - st__generator * gen; - st__table * tNodeTopRef; // this table stores the top level from which this node is pointed to - st__table * tNodes; - DdNode * node; - DdNode * nodeR; - int LevelStart, Limit; - int i, size; - int WidthMax; - - // start the mapping table - tNodeTopRef = st__init_table( st__ptrcmp, st__ptrhash);; - // add the topmost node to the profile - extraProfileUpdateTopLevel( tNodeTopRef, 0, Func ); - - // collect all nodes - tNodes = Extra_CollectNodes( Func ); - // go though all the nodes and set the top level the cofactors are pointed from -// Cudd_ForeachNode( dd, Func, genDD, node ) - st__foreach_item( tNodes, gen, (const char**)&node, NULL ) - { -// assert( Cudd_Regular(node) ); // this procedure works only with ADD/ZDD (not BDD w/ compl.edges) - nodeR = Cudd_Regular(node); - if ( cuddIsConstant(nodeR) ) - continue; - // this node is not a constant - consider its cofactors - extraProfileUpdateTopLevel( tNodeTopRef, dd->perm[node->index]+1, cuddE(nodeR) ); - extraProfileUpdateTopLevel( tNodeTopRef, dd->perm[node->index]+1, cuddT(nodeR) ); - } - st__free_table( tNodes ); - - // clean the profile - size = ddMax(dd->size, dd->sizeZ) + 1; - for ( i = 0; i < size; i++ ) - pProfile[i] = 0; - - // create the profile - st__foreach_item( tNodeTopRef, gen, (const char**)&node, (char**)&LevelStart ) - { - nodeR = Cudd_Regular(node); - Limit = (cuddIsConstant(nodeR))? dd->size: dd->perm[nodeR->index]; - for ( i = LevelStart; i <= Limit; i++ ) - pProfile[i]++; - } - - if ( CutLevel != -1 && CutLevel != 0 ) - size = CutLevel; - - // get the max width - WidthMax = 0; - for ( i = 0; i < size; i++ ) - if ( WidthMax < pProfile[i] ) - WidthMax = pProfile[i]; - - // deref the table - st__free_table( tNodeTopRef ); - - return WidthMax; -} /* end of Extra_ProfileWidth */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Computes the non-strict codes when evaluation is finished.] - - Description [The information about the best code is stored in s_VarOrderBest, - which has s_nVarsBest entries.] - - SideEffects [None] - -******************************************************************************/ -DdNode * CreateTheCodes_rec( DdManager * dd, DdNode * bEncoded, int Level, DdNode ** pCVars ) -// bEncoded is the preliminarily encoded set of columns -// Level is the current level in the recursion -// pCVars are the variables to be used for encoding -{ - DdNode * bRes; - if ( Level == s_nVarsBest ) - { // the terminal case, when we need to remap the encoded function - // from the preliminary encoded variables to the new ones - st__table * CutNodes; - int nCols; -// double nMints; -/* -#ifdef _DEBUG - - { - DdNode * bTemp; - // make sure that the given number of variables is enough - bTemp = Cudd_bddExistAbstract( dd, bEncoded, s_VarAll ); Cudd_Ref( bTemp ); -// nMints = Cudd_CountMinterm( dd, bTemp, s_MultiStart ); - nMints = Extra_CountMintermsSimple( bTemp, (1< Extra_Power2( s_MultiStart-Level ) ) - { // the number of minterms is too large to encode the columns - // using the given minimum number of encoding variables - assert( 0 ); - } - Cudd_RecursiveDeref( dd, bTemp ); - } -#endif -*/ - // get the columns to be re-encoded - CutNodes = Extra_bddNodePathsUnderCut( dd, bEncoded, s_EncodingVarsLevel ); - // LUT size is the cut level because because the temporary encoding variables - // are above the functional variables - this is not true!!! - // the temporary variables are below! - - // put the entries from the table into the temporary array - { - st__generator * gen; - DdNode * bColumn, * bCode; - nCols = 0; - st__foreach_item( CutNodes, gen, (const char**)&bCode, (char**)&bColumn ) - { - if ( bCode == b0 ) - { // the unused part of the columns - Cudd_RecursiveDeref( dd, bColumn ); - Cudd_RecursiveDeref( dd, bCode ); - continue; - } - else - { - s_pbTemp[ nCols ] = bColumn; // takes ref - Cudd_RecursiveDeref( dd, bCode ); - nCols++; - } - } - st__free_table( CutNodes ); -// assert( nCols == (int)nMints ); - } - - // encode the columns - if ( s_MultiStart-Level == 0 ) // we reached the bottom level of recursion - { - assert( nCols == 1 ); -// assert( (int)nMints == 1 ); - bRes = s_pbTemp[0]; Cudd_Ref( bRes ); - } - else - { - bRes = Extra_bddEncodingBinary( dd, s_pbTemp, nCols, pCVars+Level, s_MultiStart-Level ); Cudd_Ref( bRes ); - } - - // deref the columns - { - int i; - for ( i = 0; i < nCols; i++ ) - Cudd_RecursiveDeref( dd, s_pbTemp[i] ); - } - } - else - { - // cofactor the problem as specified in the best solution - DdNode * bCof0, * bCof1; - DdNode * bRes0, * bRes1; - DdNode * bProd0, * bProd1; - DdNode * bTemp; - DdNode * bVarNext = dd->vars[ s_VarOrderBest[Level] ]; - - bCof0 = Cudd_Cofactor( dd, bEncoded, Cudd_Not( bVarNext ) ); Cudd_Ref( bCof0 ); - bCof1 = Cudd_Cofactor( dd, bEncoded, bVarNext ); Cudd_Ref( bCof1 ); - - // call recursively - bRes0 = CreateTheCodes_rec( dd, bCof0, Level+1, pCVars ); Cudd_Ref( bRes0 ); - bRes1 = CreateTheCodes_rec( dd, bCof1, Level+1, pCVars ); Cudd_Ref( bRes1 ); - - Cudd_RecursiveDeref( dd, bCof0 ); - Cudd_RecursiveDeref( dd, bCof1 ); - - // compose the result using the identity (bVarNext <=> pCVars[Level]) - this is wrong! - // compose the result as follows: x'y'F0 + xyF1 - bProd0 = Cudd_bddAnd( dd, Cudd_Not(bVarNext), Cudd_Not(pCVars[Level]) ); Cudd_Ref( bProd0 ); - bProd1 = Cudd_bddAnd( dd, bVarNext , pCVars[Level] ); Cudd_Ref( bProd1 ); - - bProd0 = Cudd_bddAnd( dd, bTemp = bProd0, bRes0 ); Cudd_Ref( bProd0 ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bRes0 ); - - bProd1 = Cudd_bddAnd( dd, bTemp = bProd1, bRes1 ); Cudd_Ref( bProd1 ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bRes1 ); - - bRes = Cudd_bddOr( dd, bProd0, bProd1 ); Cudd_Ref( bRes ); - - Cudd_RecursiveDeref( dd, bProd0 ); - Cudd_RecursiveDeref( dd, bProd1 ); - } - Cudd_Deref( bRes ); - return bRes; -} - -/**Function******************************************************************** - - Synopsis [Computes the current set of variables and counts the number of minterms.] - - Description [Old implementation.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void EvaluateEncodings_rec( DdManager * dd, DdNode * bVarsCol, int nVarsCol, int nMulti, int Level ) -// bVarsCol is the set of remaining variables -// nVarsCol is the number of remaining variables -// nMulti is the number of encoding variables to be used -// Level is the level of recursion, from which this function is called -// if we successfully finish this procedure, Level also stands for how many encoding variabled we saved -{ - int i, k; - int nEntries = (1<<(Level-1)); // the number of entries in the field of the previous level - DdNode * bVars0, * bVars1; // the cofactors - unsigned nMint0, nMint1; // the number of minterms - DdNode * bTempV; - DdNode * bVarTop; - int fBreak; - - - // there is no need to search above this level - if ( Level > s_MaxDepth ) - return; - - // if there are no variables left, quit the research - if ( bVarsCol == b1 ) - return; - - if ( s_BackTracks > s_BackTrackLimit ) - return; - - s_BackTracks++; - - // otherwise, go through the remaining variables - for ( bTempV = bVarsCol; bTempV != b1; bTempV = cuddT(bTempV) ) - { - // the currently tested variable - bVarTop = dd->vars[bTempV->index]; - - // put it into the array - s_VarOrderCur[Level-1] = bTempV->index; - - // go through the entries and fill them out by cofactoring - fBreak = 0; - for ( i = 0; i < nEntries; i++ ) - { - bVars0 = ComputeVarSetAndCountMinterms( dd, s_Field[Level-1][i], Cudd_Not(bVarTop), &nMint0 ); - Cudd_Ref( bVars0 ); - - if ( nMint0 > Extra_Power2( nMulti-1 ) ) - { - // there is no way to encode - dereference and return - Cudd_RecursiveDeref( dd, bVars0 ); - fBreak = 1; - break; - } - - bVars1 = ComputeVarSetAndCountMinterms( dd, s_Field[Level-1][i], bVarTop, &nMint1 ); - Cudd_Ref( bVars1 ); - - if ( nMint1 > Extra_Power2( nMulti-1 ) ) - { - // there is no way to encode - dereference and return - Cudd_RecursiveDeref( dd, bVars0 ); - Cudd_RecursiveDeref( dd, bVars1 ); - fBreak = 1; - break; - } - - // otherwise, add these two cofactors - s_Field[Level][2*i + 0] = bVars0; // takes ref - s_Field[Level][2*i + 1] = bVars1; // takes ref - } - - if ( !fBreak ) - { - DdNode * bVarsRem; - // if we ended up here, it means that the cofactors w.r.t. variable bVarTop satisfy the condition - // save this situation - if ( s_nVarsBest < Level ) - { - s_nVarsBest = Level; - // copy the variable assignment - for ( k = 0; k < Level; k++ ) - s_VarOrderBest[k] = s_VarOrderCur[k]; - } - - // call recursively - // get the new variable set - if ( nMulti-1 > 0 ) - { - bVarsRem = Cudd_bddExistAbstract( dd, bVarsCol, bVarTop ); Cudd_Ref( bVarsRem ); - EvaluateEncodings_rec( dd, bVarsRem, nVarsCol-1, nMulti-1, Level+1 ); - Cudd_RecursiveDeref( dd, bVarsRem ); - } - } - - // deref the contents of the array - for ( k = 0; k < i; k++ ) - { - Cudd_RecursiveDeref( dd, s_Field[Level][2*k + 0] ); - Cudd_RecursiveDeref( dd, s_Field[Level][2*k + 1] ); - } - - // if the solution is found, there is no need to continue - if ( s_nVarsBest == s_MaxDepth ) - return; - - // if the solution is found, there is no need to continue - if ( s_nVarsBest == s_MultiStart ) - return; - } - // at this point, we have tried all possible directions in the space of variables -} - -/**Function******************************************************************** - - Synopsis [Computes the current set of variables and counts the number of minterms.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * ComputeVarSetAndCountMinterms( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost ) -// takes bVars - the variables cofactored so far (some of them may be in negative polarity) -// bVarTop - the topmost variable w.r.t. which to cofactor (may be in negative polarity) -// returns the cost and the new set of variables (bVars & bVarTop) -{ - DdNode * bVarsRes; - - // get the resulting set of variables - bVarsRes = Cudd_bddAnd( dd, bVars, bVarTop ); Cudd_Ref( bVarsRes ); - - // increment signature before calling Cudd_CountCofactorMinterms() - s_Signature++; - *Cost = Extra_CountCofactorMinterms( dd, s_Encoded, bVarsRes, s_VarAll ); - - Cudd_Deref( bVarsRes ); -// s_CountCalls++; - return bVarsRes; -} - -/**Function******************************************************************** - - Synopsis [Computes the current set of variables and counts the number of minterms.] - - Description [The old implementation, which is approximately 4 times slower.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * ComputeVarSetAndCountMinterms2( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost ) -{ - DdNode * bVarsRes; - DdNode * bCof, * bFun; - - bVarsRes = Cudd_bddAnd( dd, bVars, bVarTop ); Cudd_Ref( bVarsRes ); - - bCof = Cudd_Cofactor( dd, s_Encoded, bVarsRes ); Cudd_Ref( bCof ); - bFun = Cudd_bddExistAbstract( dd, bCof, s_VarAll ); Cudd_Ref( bFun ); - *Cost = (unsigned)Cudd_CountMinterm( dd, bFun, s_MultiStart ); - Cudd_RecursiveDeref( dd, bFun ); - Cudd_RecursiveDeref( dd, bCof ); - - Cudd_Deref( bVarsRes ); -// s_CountCalls++; - return bVarsRes; -} - - -/**Function******************************************************************** - - Synopsis [Counts the number of encoding minterms pointed to by the cofactor of the function.] - - Description [] - - SideEffects [None] - -******************************************************************************/ -unsigned Extra_CountCofactorMinterms( DdManager * dd, DdNode * bFunc, DdNode * bVarsCof, DdNode * bVarsAll ) -// this function computes how many minterms depending on the encoding variables -// are there in the cofactor of bFunc w.r.t. variables bVarsCof -// bFunc is assumed to depend on variables s_VarsAll -// the variables s_VarsAll should be ordered above the encoding variables -{ - unsigned HKey; - DdNode * bFuncR; - - // if the function is zero, there are no minterms -// if ( bFunc == b0 ) -// return 0; - -// if ( st__lookup(Visited, (char*)bFunc, NULL) ) -// return 0; - -// HKey = hashKey2c( s_Signature, bFuncR ); -// if ( HHTable1[HKey].Sign == s_Signature && HHTable1[HKey].Arg1 == bFuncR ) // this node is visited -// return 0; - - - // check the hash-table - bFuncR = Cudd_Regular(bFunc); -// HKey = hashKey2( s_Signature, bFuncR, _TABLESIZE_COF ); - HKey = hashKey2( s_Signature, bFunc, _TABLESIZE_COF ); - for ( ; HHTable1[HKey].Sign == s_Signature; HKey = (HKey+1) % _TABLESIZE_COF ) -// if ( HHTable1[HKey].Arg1 == bFuncR ) // this node is visited - if ( HHTable1[HKey].Arg1 == bFunc ) // this node is visited - return 0; - - - // if the function is already the code - if ( dd->perm[bFuncR->index] >= s_EncodingVarsLevel ) - { -// st__insert(Visited, (char*)bFunc, NULL); - -// HHTable1[HKey].Sign = s_Signature; -// HHTable1[HKey].Arg1 = bFuncR; - - assert( HHTable1[HKey].Sign != s_Signature ); - HHTable1[HKey].Sign = s_Signature; -// HHTable1[HKey].Arg1 = bFuncR; - HHTable1[HKey].Arg1 = bFunc; - - return Extra_CountMintermsSimple( bFunc, (1<perm[bFuncR->index]; - int LevelC = cuddI(dd,bVarsCofR->index); - int LevelA = dd->perm[bVarsAll->index]; - - int LevelTop = LevelF; - - if ( LevelTop > LevelC ) - LevelTop = LevelC; - - if ( LevelTop > LevelA ) - LevelTop = LevelA; - - // the top var in the function or in cofactoring vars always belongs to the set of all vars - assert( !( LevelTop == LevelF || LevelTop == LevelC ) || LevelTop == LevelA ); - - // cofactor the function - if ( LevelTop == LevelF ) - { - if ( bFuncR != bFunc ) // bFunc is complemented - { - bFunc0 = Cudd_Not( cuddE(bFuncR) ); - bFunc1 = Cudd_Not( cuddT(bFuncR) ); - } - else - { - bFunc0 = cuddE(bFuncR); - bFunc1 = cuddT(bFuncR); - } - } - else // bVars is higher in the variable order - bFunc0 = bFunc1 = bFunc; - - // cofactor the cube - if ( LevelTop == LevelC ) - { - if ( bVarsCofR != bVarsCof ) // bFunc is complemented - { - bVarsCof0 = Cudd_Not( cuddE(bVarsCofR) ); - bVarsCof1 = Cudd_Not( cuddT(bVarsCofR) ); - } - else - { - bVarsCof0 = cuddE(bVarsCofR); - bVarsCof1 = cuddT(bVarsCofR); - } - } - else // bVars is higher in the variable order - bVarsCof0 = bVarsCof1 = bVarsCof; - - // there are two cases: - // (1) the top variable belongs to the cofactoring variables - // (2) the top variable does not belong to the cofactoring variables - - // (1) the top variable belongs to the cofactoring variables - Res = 0; - if ( LevelTop == LevelC ) - { - if ( bVarsCof1 == b0 ) // this is a negative cofactor - { - if ( bFunc0 != b0 ) - Res = Extra_CountCofactorMinterms( dd, bFunc0, bVarsCof0, cuddT(bVarsAll) ); - } - else // this is a positive cofactor - { - if ( bFunc1 != b0 ) - Res = Extra_CountCofactorMinterms( dd, bFunc1, bVarsCof1, cuddT(bVarsAll) ); - } - } - else - { - if ( bFunc0 != b0 ) - Res += Extra_CountCofactorMinterms( dd, bFunc0, bVarsCof0, cuddT(bVarsAll) ); - - if ( bFunc1 != b0 ) - Res += Extra_CountCofactorMinterms( dd, bFunc1, bVarsCof1, cuddT(bVarsAll) ); - } - -// st__insert(Visited, (char*)bFunc, NULL); - -// HHTable1[HKey].Sign = s_Signature; -// HHTable1[HKey].Arg1 = bFuncR; - - // skip through the entries with the same signatures - // (these might have been created at the time of recursive calls) - for ( ; HHTable1[HKey].Sign == s_Signature; HKey = (HKey+1) % _TABLESIZE_COF ); - assert( HHTable1[HKey].Sign != s_Signature ); - HHTable1[HKey].Sign = s_Signature; -// HHTable1[HKey].Arg1 = bFuncR; - HHTable1[HKey].Arg1 = bFunc; - - return Res; - } -} - -/**Function******************************************************************** - - Synopsis [Counts the number of minterms.] - - Description [This function counts minterms for functions up to 32 variables - using a local cache. The terminal value (s_Termina) should be adjusted for - BDDs and ADDs.] - - SideEffects [None] - -******************************************************************************/ -unsigned Extra_CountMintermsSimple( DdNode * bFunc, unsigned max ) -{ - unsigned HKey; - - // normalize - if ( Cudd_IsComplement(bFunc) ) - return max - Extra_CountMintermsSimple( Cudd_Not(bFunc), max ); - - // now it is known that the function is not complemented - if ( cuddIsConstant(bFunc) ) - return ((bFunc==s_Terminal)? 0: max); - - // check cache - HKey = hashKey2( bFunc, max, _TABLESIZE_MINT ); - if ( HHTable2[HKey].Arg1 == bFunc && HHTable2[HKey].Arg2 == max ) - return HHTable2[HKey].Res; - else - { - // min = min0/2 + min1/2; - unsigned min = (Extra_CountMintermsSimple( cuddE(bFunc), max ) >> 1) + - (Extra_CountMintermsSimple( cuddT(bFunc), max ) >> 1); - - HHTable2[HKey].Arg1 = bFunc; - HHTable2[HKey].Arg2 = max; - HHTable2[HKey].Res = min; - - return min; - } -} /* end of Extra_CountMintermsSimple */ - - -/**Function******************************************************************** - - Synopsis [Visits the nodes.] - - Description [Visits the nodes above the cut and the nodes pointed to below the cut; - collects the visited nodes, counts how many times each node is visited, and sets - the path-sum to be the constant zero BDD.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void CountNodeVisits_rec( DdManager * dd, DdNode * aFunc, st__table * Visited ) - -{ - traventry * p; - char **slot; - if ( st__find_or_add(Visited, (char*)aFunc, &slot) ) - { // the entry already exists - p = (traventry*) *slot; - // increment the counter of incoming edges - p->nEdges++; - return; - } - // this node has not been visited - assert( !Cudd_IsComplement(aFunc) ); - - // create the new traversal entry - p = (traventry *) ABC_ALLOC( char, sizeof(traventry) ); - // set the initial sum of edges to zero BDD - p->bSum = b0; Cudd_Ref( b0 ); - // set the starting number of incoming edges - p->nEdges = 1; - // set this entry into the slot - *slot = (char*)p; - - // recur if the node is above the cut - if ( cuddI(dd,aFunc->index) < s_CutLevel ) - { - CountNodeVisits_rec( dd, cuddE(aFunc), Visited ); - CountNodeVisits_rec( dd, cuddT(aFunc), Visited ); - } -} /* end of CountNodeVisits_rec */ - - -/**Function******************************************************************** - - Synopsis [Revisits the nodes and computes the paths.] - - Description [This function visits the nodes above the cut having the goal of - summing all the incomming BDD edges; when this function comes across the node - below the cut, it saves this node in the CutNode table.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void CollectNodesAndComputePaths_rec( DdManager * dd, DdNode * aFunc, DdNode * bCube, st__table * Visited, st__table * CutNodes ) -{ - // find the node in the visited table - DdNode * bTemp; - traventry * p; - char **slot; - if ( st__find_or_add(Visited, (char*)aFunc, &slot) ) - { // the node is found - // get the pointer to the traversal entry - p = (traventry*) *slot; - - // make sure that the counter of incoming edges is positive - assert( p->nEdges > 0 ); - - // add the cube to the currently accumulated cubes - p->bSum = Cudd_bddOr( dd, bTemp = p->bSum, bCube ); Cudd_Ref( p->bSum ); - Cudd_RecursiveDeref( dd, bTemp ); - - // decrement the number of visits - p->nEdges--; - - // if more visits to this node are expected, return - if ( p->nEdges ) - return; - else // if ( p->nEdges == 0 ) - { // this is the last visit - propagate the cube - - // check where this node is - if ( cuddI(dd,aFunc->index) < s_CutLevel ) - { // the node is above the cut - DdNode * bCube0, * bCube1; - - // get the top-most variable - DdNode * bVarTop = dd->vars[aFunc->index]; - - // compute the propagated cubes - bCube0 = Cudd_bddAnd( dd, p->bSum, Cudd_Not( bVarTop ) ); Cudd_Ref( bCube0 ); - bCube1 = Cudd_bddAnd( dd, p->bSum, bVarTop ); Cudd_Ref( bCube1 ); - - // call recursively - CollectNodesAndComputePaths_rec( dd, cuddE(aFunc), bCube0, Visited, CutNodes ); - CollectNodesAndComputePaths_rec( dd, cuddT(aFunc), bCube1, Visited, CutNodes ); - - // dereference the cubes - Cudd_RecursiveDeref( dd, bCube0 ); - Cudd_RecursiveDeref( dd, bCube1 ); - return; - } - else - { // the node is below the cut - // add this node to the cut node table, if it is not yet there - -// DdNode * bNode; -// bNode = Cudd_addBddPattern( dd, aFunc ); Cudd_Ref( bNode ); - if ( st__find_or_add(CutNodes, (char*)aFunc, &slot) ) - { // the node exists - should never happen - assert( 0 ); - } - *slot = (char*) p->bSum; Cudd_Ref( p->bSum ); - // the table takes the reference of bNode - return; - } - } - } - - // the node does not exist in the visited table - should never happen - assert(0); - -} /* end of CollectNodesAndComputePaths_rec */ - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// -ABC_NAMESPACE_IMPL_END - diff --git a/src/misc/extra/extraBddImage.c b/src/misc/extra/extraBddImage.c deleted file mode 100644 index 46afb4f2..00000000 --- a/src/misc/extra/extraBddImage.c +++ /dev/null @@ -1,1162 +0,0 @@ -/**CFile**************************************************************** - - FileName [extraBddImage.c] - - PackageName [extra] - - Synopsis [Various reusable software utilities.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 1, 2003.] - - Revision [$Id: extraBddImage.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "extraBdd.h" - -ABC_NAMESPACE_IMPL_START - - -/* - The ideas implemented in this file are inspired by the paper: - Pankaj Chauhan, Edmund Clarke, Somesh Jha, Jim Kukula, Tom Shiple, - Helmut Veith, Dong Wang. Non-linear Quantification Scheduling in - Image Computation. ICCAD, 2001. -*/ - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -typedef struct Extra_ImageNode_t_ Extra_ImageNode_t; -typedef struct Extra_ImagePart_t_ Extra_ImagePart_t; -typedef struct Extra_ImageVar_t_ Extra_ImageVar_t; - -struct Extra_ImageTree_t_ -{ - Extra_ImageNode_t * pRoot; // the root of quantification tree - Extra_ImageNode_t * pCare; // the leaf node with the care set - DdNode * bCareSupp; // the cube to quantify from the care - int fVerbose; // the verbosity flag - int nNodesMax; // the max number of nodes in one iter - int nNodesMaxT; // the overall max number of nodes - int nIter; // the number of iterations with this tree -}; - -struct Extra_ImageNode_t_ -{ - DdManager * dd; // the manager - DdNode * bCube; // the cube to quantify - DdNode * bImage; // the partial image - Extra_ImageNode_t * pNode1; // the first branch - Extra_ImageNode_t * pNode2; // the second branch - Extra_ImagePart_t * pPart; // the partition (temporary) -}; - -struct Extra_ImagePart_t_ -{ - DdNode * bFunc; // the partition - DdNode * bSupp; // the support of this partition - int nNodes; // the number of BDD nodes - short nSupp; // the number of support variables - short iPart; // the number of this partition -}; - -struct Extra_ImageVar_t_ -{ - int iNum; // the BDD index of this variable - DdNode * bParts; // the partition numbers - int nParts; // the number of partitions -}; - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static Extra_ImagePart_t ** Extra_CreateParts( DdManager * dd, - int nParts, DdNode ** pbParts, DdNode * bCare ); -static Extra_ImageVar_t ** Extra_CreateVars( DdManager * dd, - int nParts, Extra_ImagePart_t ** pParts, - int nVars, DdNode ** pbVarsNs ); -static Extra_ImageNode_t ** Extra_CreateNodes( DdManager * dd, - int nParts, Extra_ImagePart_t ** pParts, - int nVars, Extra_ImageVar_t ** pVars ); -static void Extra_DeleteParts_rec( Extra_ImageNode_t * pNode ); -static int Extra_BuildTreeNode( DdManager * dd, - int nNodes, Extra_ImageNode_t ** pNodes, - int nVars, Extra_ImageVar_t ** pVars ); -static Extra_ImageNode_t * Extra_MergeTopNodes( DdManager * dd, - int nNodes, Extra_ImageNode_t ** pNodes ); -static void Extra_bddImageTreeDelete_rec( Extra_ImageNode_t * pNode ); -static void Extra_bddImageCompute_rec( Extra_ImageTree_t * pTree, Extra_ImageNode_t * pNode ); -static int Extra_FindBestVariable( DdManager * dd, - int nNodes, Extra_ImageNode_t ** pNodes, - int nVars, Extra_ImageVar_t ** pVars ); -static void Extra_FindBestPartitions( DdManager * dd, DdNode * bParts, - int nNodes, Extra_ImageNode_t ** pNodes, - int * piNode1, int * piNode2 ); -static Extra_ImageNode_t * Extra_CombineTwoNodes( DdManager * dd, DdNode * bCube, - Extra_ImageNode_t * pNode1, Extra_ImageNode_t * pNode2 ); - -static void Extra_bddImagePrintLatchDependency( DdManager * dd, DdNode * bCare, - int nParts, DdNode ** pbParts, - int nVars, DdNode ** pbVars ); -static void Extra_bddImagePrintLatchDependencyOne( DdManager * dd, DdNode * bFunc, - DdNode * bVarsCs, DdNode * bVarsNs, int iPart ); - -static void Extra_bddImagePrintTree( Extra_ImageTree_t * pTree ); -static void Extra_bddImagePrintTree_rec( Extra_ImageNode_t * pNode, int nOffset ); - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function************************************************************* - - Synopsis [Starts the image computation using tree-based scheduling.] - - Description [This procedure starts the image computation. It uses - the given care set to test-run the image computation and creates the - quantification tree by scheduling variable quantifications. The tree can - be used to compute images for other care sets without rescheduling. - In this case, Extra_bddImageCompute() should be called.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Extra_ImageTree_t * Extra_bddImageStart( - DdManager * dd, DdNode * bCare, // the care set - int nParts, DdNode ** pbParts, // the partitions for image computation - int nVars, DdNode ** pbVars, int fVerbose ) // the NS and parameter variables (not quantified!) -{ - Extra_ImageTree_t * pTree; - Extra_ImagePart_t ** pParts; - Extra_ImageVar_t ** pVars; - Extra_ImageNode_t ** pNodes; - int v; - - if ( fVerbose && dd->size <= 80 ) - Extra_bddImagePrintLatchDependency( dd, bCare, nParts, pbParts, nVars, pbVars ); - - // create variables, partitions and leaf nodes - pParts = Extra_CreateParts( dd, nParts, pbParts, bCare ); - pVars = Extra_CreateVars( dd, nParts + 1, pParts, nVars, pbVars ); - pNodes = Extra_CreateNodes( dd, nParts + 1, pParts, dd->size, pVars ); - - // create the tree - pTree = ABC_ALLOC( Extra_ImageTree_t, 1 ); - memset( pTree, 0, sizeof(Extra_ImageTree_t) ); - pTree->pCare = pNodes[nParts]; - pTree->fVerbose = fVerbose; - - // process the nodes - while ( Extra_BuildTreeNode( dd, nParts + 1, pNodes, dd->size, pVars ) ); - - // make sure the variables are gone - for ( v = 0; v < dd->size; v++ ) - assert( pVars[v] == NULL ); - ABC_FREE( pVars ); - - // merge the topmost nodes - while ( (pTree->pRoot = Extra_MergeTopNodes( dd, nParts + 1, pNodes )) == NULL ); - - // make sure the nodes are gone - for ( v = 0; v < nParts + 1; v++ ) - assert( pNodes[v] == NULL ); - ABC_FREE( pNodes ); - -// if ( fVerbose ) -// Extra_bddImagePrintTree( pTree ); - - // set the support of the care set - pTree->bCareSupp = Cudd_Support( dd, bCare ); Cudd_Ref( pTree->bCareSupp ); - - // clean the partitions - Extra_DeleteParts_rec( pTree->pRoot ); - ABC_FREE( pParts ); - return pTree; -} - -/**Function************************************************************* - - Synopsis [Compute the image.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddImageCompute( Extra_ImageTree_t * pTree, DdNode * bCare ) -{ - DdManager * dd = pTree->pCare->dd; - DdNode * bSupp, * bRem; - - pTree->nIter++; - - // make sure the supports are okay - bSupp = Cudd_Support( dd, bCare ); Cudd_Ref( bSupp ); - if ( bSupp != pTree->bCareSupp ) - { - bRem = Cudd_bddExistAbstract( dd, bSupp, pTree->bCareSupp ); Cudd_Ref( bRem ); - if ( bRem != b1 ) - { -printf( "Original care set support: " ); -ABC_PRB( dd, pTree->bCareSupp ); -printf( "Current care set support: " ); -ABC_PRB( dd, bSupp ); - Cudd_RecursiveDeref( dd, bSupp ); - Cudd_RecursiveDeref( dd, bRem ); - printf( "The care set depends on some vars that were not in the care set during scheduling.\n" ); - return NULL; - } - Cudd_RecursiveDeref( dd, bRem ); - } - Cudd_RecursiveDeref( dd, bSupp ); - - // remove the previous image - Cudd_RecursiveDeref( dd, pTree->pCare->bImage ); - pTree->pCare->bImage = bCare; Cudd_Ref( bCare ); - - // compute the image - pTree->nNodesMax = 0; - Extra_bddImageCompute_rec( pTree, pTree->pRoot ); - if ( pTree->nNodesMaxT < pTree->nNodesMax ) - pTree->nNodesMaxT = pTree->nNodesMax; - -// if ( pTree->fVerbose ) -// printf( "Iter %2d : Max nodes = %5d.\n", pTree->nIter, pTree->nNodesMax ); - return pTree->pRoot->bImage; -} - -/**Function************************************************************* - - Synopsis [Delete the tree.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_bddImageTreeDelete( Extra_ImageTree_t * pTree ) -{ - if ( pTree->bCareSupp ) - Cudd_RecursiveDeref( pTree->pRoot->dd, pTree->bCareSupp ); - Extra_bddImageTreeDelete_rec( pTree->pRoot ); - ABC_FREE( pTree ); -} - -/**Function************************************************************* - - Synopsis [Reads the image from the tree.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddImageRead( Extra_ImageTree_t * pTree ) -{ - return pTree->pRoot->bImage; -} - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of static Functions */ -/*---------------------------------------------------------------------------*/ - -/**Function************************************************************* - - Synopsis [Creates partitions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Extra_ImagePart_t ** Extra_CreateParts( DdManager * dd, - int nParts, DdNode ** pbParts, DdNode * bCare ) -{ - Extra_ImagePart_t ** pParts; - int i; - - // start the partitions - pParts = ABC_ALLOC( Extra_ImagePart_t *, nParts + 1 ); - // create structures for each variable - for ( i = 0; i < nParts; i++ ) - { - pParts[i] = ABC_ALLOC( Extra_ImagePart_t, 1 ); - pParts[i]->bFunc = pbParts[i]; Cudd_Ref( pParts[i]->bFunc ); - pParts[i]->bSupp = Cudd_Support( dd, pParts[i]->bFunc ); Cudd_Ref( pParts[i]->bSupp ); - pParts[i]->nSupp = Extra_bddSuppSize( dd, pParts[i]->bSupp ); - pParts[i]->nNodes = Cudd_DagSize( pParts[i]->bFunc ); - pParts[i]->iPart = i; - } - // add the care set as the last partition - pParts[nParts] = ABC_ALLOC( Extra_ImagePart_t, 1 ); - pParts[nParts]->bFunc = bCare; Cudd_Ref( pParts[nParts]->bFunc ); - pParts[nParts]->bSupp = Cudd_Support( dd, pParts[nParts]->bFunc ); Cudd_Ref( pParts[nParts]->bSupp ); - pParts[nParts]->nSupp = Extra_bddSuppSize( dd, pParts[nParts]->bSupp ); - pParts[nParts]->nNodes = Cudd_DagSize( pParts[nParts]->bFunc ); - pParts[nParts]->iPart = nParts; - return pParts; -} - -/**Function************************************************************* - - Synopsis [Creates variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Extra_ImageVar_t ** Extra_CreateVars( DdManager * dd, - int nParts, Extra_ImagePart_t ** pParts, - int nVars, DdNode ** pbVars ) -{ - Extra_ImageVar_t ** pVars; - DdNode ** pbFuncs; - DdNode * bCubeNs, * bSupp, * bParts, * bTemp, * bSuppTemp; - int nVarsTotal, iVar, p, Counter; - - // put all the functions into one array - pbFuncs = ABC_ALLOC( DdNode *, nParts ); - for ( p = 0; p < nParts; p++ ) - pbFuncs[p] = pParts[p]->bSupp; - bSupp = Cudd_VectorSupport( dd, pbFuncs, nParts ); Cudd_Ref( bSupp ); - ABC_FREE( pbFuncs ); - - // remove the NS vars - bCubeNs = Cudd_bddComputeCube( dd, pbVars, NULL, nVars ); Cudd_Ref( bCubeNs ); - bSupp = Cudd_bddExistAbstract( dd, bTemp = bSupp, bCubeNs ); Cudd_Ref( bSupp ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bCubeNs ); - - // get the number of I and CS variables to be quantified - nVarsTotal = Extra_bddSuppSize( dd, bSupp ); - - // start the variables - pVars = ABC_ALLOC( Extra_ImageVar_t *, dd->size ); - memset( pVars, 0, sizeof(Extra_ImageVar_t *) * dd->size ); - // create structures for each variable - for ( bSuppTemp = bSupp; bSuppTemp != b1; bSuppTemp = cuddT(bSuppTemp) ) - { - iVar = bSuppTemp->index; - pVars[iVar] = ABC_ALLOC( Extra_ImageVar_t, 1 ); - pVars[iVar]->iNum = iVar; - // collect all the parts this var belongs to - Counter = 0; - bParts = b1; Cudd_Ref( bParts ); - for ( p = 0; p < nParts; p++ ) - if ( Cudd_bddLeq( dd, pParts[p]->bSupp, dd->vars[bSuppTemp->index] ) ) - { - bParts = Cudd_bddAnd( dd, bTemp = bParts, dd->vars[p] ); Cudd_Ref( bParts ); - Cudd_RecursiveDeref( dd, bTemp ); - Counter++; - } - pVars[iVar]->bParts = bParts; // takes ref - pVars[iVar]->nParts = Counter; - } - Cudd_RecursiveDeref( dd, bSupp ); - return pVars; -} - -/**Function************************************************************* - - Synopsis [Creates variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Extra_ImageNode_t ** Extra_CreateNodes( DdManager * dd, - int nParts, Extra_ImagePart_t ** pParts, - int nVars, Extra_ImageVar_t ** pVars ) -{ - Extra_ImageNode_t ** pNodes; - Extra_ImageNode_t * pNode; - DdNode * bTemp; - int i, v, iPart; -/* - DdManager * dd; // the manager - DdNode * bCube; // the cube to quantify - DdNode * bImage; // the partial image - Extra_ImageNode_t * pNode1; // the first branch - Extra_ImageNode_t * pNode2; // the second branch - Extra_ImagePart_t * pPart; // the partition (temporary) -*/ - // start the partitions - pNodes = ABC_ALLOC( Extra_ImageNode_t *, nParts ); - // create structures for each leaf nodes - for ( i = 0; i < nParts; i++ ) - { - pNodes[i] = ABC_ALLOC( Extra_ImageNode_t, 1 ); - memset( pNodes[i], 0, sizeof(Extra_ImageNode_t) ); - pNodes[i]->dd = dd; - pNodes[i]->pPart = pParts[i]; - } - // find the quantification cubes for each leaf node - for ( v = 0; v < nVars; v++ ) - { - if ( pVars[v] == NULL ) - continue; - assert( pVars[v]->nParts > 0 ); - if ( pVars[v]->nParts > 1 ) - continue; - iPart = pVars[v]->bParts->index; - if ( pNodes[iPart]->bCube == NULL ) - { - pNodes[iPart]->bCube = dd->vars[v]; - Cudd_Ref( dd->vars[v] ); - } - else - { - pNodes[iPart]->bCube = Cudd_bddAnd( dd, bTemp = pNodes[iPart]->bCube, dd->vars[v] ); - Cudd_Ref( pNodes[iPart]->bCube ); - Cudd_RecursiveDeref( dd, bTemp ); - } - // remove these variables - Cudd_RecursiveDeref( dd, pVars[v]->bParts ); - ABC_FREE( pVars[v] ); - } - - // assign the leaf node images - for ( i = 0; i < nParts; i++ ) - { - pNode = pNodes[i]; - if ( pNode->bCube ) - { - // update the partition - pParts[i]->bFunc = Cudd_bddExistAbstract( dd, bTemp = pParts[i]->bFunc, pNode->bCube ); - Cudd_Ref( pParts[i]->bFunc ); - Cudd_RecursiveDeref( dd, bTemp ); - // update the support the partition - pParts[i]->bSupp = Cudd_bddExistAbstract( dd, bTemp = pParts[i]->bSupp, pNode->bCube ); - Cudd_Ref( pParts[i]->bSupp ); - Cudd_RecursiveDeref( dd, bTemp ); - // update the numbers - pParts[i]->nSupp = Extra_bddSuppSize( dd, pParts[i]->bSupp ); - pParts[i]->nNodes = Cudd_DagSize( pParts[i]->bFunc ); - // get rid of the cube - // save the last (care set) quantification cube - if ( i < nParts - 1 ) - { - Cudd_RecursiveDeref( dd, pNode->bCube ); - pNode->bCube = NULL; - } - } - // copy the function - pNode->bImage = pParts[i]->bFunc; Cudd_Ref( pNode->bImage ); - } -/* - for ( i = 0; i < nParts; i++ ) - { - pNode = pNodes[i]; -ABC_PRB( dd, pNode->bCube ); -ABC_PRB( dd, pNode->pPart->bFunc ); -ABC_PRB( dd, pNode->pPart->bSupp ); -printf( "\n" ); - } -*/ - return pNodes; -} - - -/**Function************************************************************* - - Synopsis [Delete the partitions from the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_DeleteParts_rec( Extra_ImageNode_t * pNode ) -{ - Extra_ImagePart_t * pPart; - if ( pNode->pNode1 ) - Extra_DeleteParts_rec( pNode->pNode1 ); - if ( pNode->pNode2 ) - Extra_DeleteParts_rec( pNode->pNode2 ); - pPart = pNode->pPart; - Cudd_RecursiveDeref( pNode->dd, pPart->bFunc ); - Cudd_RecursiveDeref( pNode->dd, pPart->bSupp ); - ABC_FREE( pNode->pPart ); -} - -/**Function************************************************************* - - Synopsis [Delete the partitions from the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_bddImageTreeDelete_rec( Extra_ImageNode_t * pNode ) -{ - if ( pNode->pNode1 ) - Extra_bddImageTreeDelete_rec( pNode->pNode1 ); - if ( pNode->pNode2 ) - Extra_bddImageTreeDelete_rec( pNode->pNode2 ); - if ( pNode->bCube ) - Cudd_RecursiveDeref( pNode->dd, pNode->bCube ); - if ( pNode->bImage ) - Cudd_RecursiveDeref( pNode->dd, pNode->bImage ); - assert( pNode->pPart == NULL ); - ABC_FREE( pNode ); -} - -/**Function************************************************************* - - Synopsis [Recompute the image.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_bddImageCompute_rec( Extra_ImageTree_t * pTree, Extra_ImageNode_t * pNode ) -{ - DdManager * dd = pNode->dd; - DdNode * bTemp; - int nNodes; - - // trivial case - if ( pNode->pNode1 == NULL ) - { - if ( pNode->bCube ) - { - pNode->bImage = Cudd_bddExistAbstract( dd, bTemp = pNode->bImage, pNode->bCube ); - Cudd_Ref( pNode->bImage ); - Cudd_RecursiveDeref( dd, bTemp ); - } - return; - } - - // compute the children - if ( pNode->pNode1 ) - Extra_bddImageCompute_rec( pTree, pNode->pNode1 ); - if ( pNode->pNode2 ) - Extra_bddImageCompute_rec( pTree, pNode->pNode2 ); - - // clean the old image - if ( pNode->bImage ) - Cudd_RecursiveDeref( dd, pNode->bImage ); - pNode->bImage = NULL; - - // compute the new image - if ( pNode->bCube ) - pNode->bImage = Cudd_bddAndAbstract( dd, - pNode->pNode1->bImage, pNode->pNode2->bImage, pNode->bCube ); - else - pNode->bImage = Cudd_bddAnd( dd, pNode->pNode1->bImage, pNode->pNode2->bImage ); - Cudd_Ref( pNode->bImage ); - - if ( pTree->fVerbose ) - { - nNodes = Cudd_DagSize( pNode->bImage ); - if ( pTree->nNodesMax < nNodes ) - pTree->nNodesMax = nNodes; - } -} - -/**Function************************************************************* - - Synopsis [Builds the tree.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_BuildTreeNode( DdManager * dd, - int nNodes, Extra_ImageNode_t ** pNodes, - int nVars, Extra_ImageVar_t ** pVars ) -{ - Extra_ImageNode_t * pNode1, * pNode2; - Extra_ImageVar_t * pVar; - Extra_ImageNode_t * pNode; - DdNode * bCube, * bTemp, * bSuppTemp, * bParts; - int iNode1, iNode2; - int iVarBest, nSupp, v; - - // find the best variable - iVarBest = Extra_FindBestVariable( dd, nNodes, pNodes, nVars, pVars ); - if ( iVarBest == -1 ) - return 0; - - pVar = pVars[iVarBest]; - - // this var cannot appear in one partition only - nSupp = Extra_bddSuppSize( dd, pVar->bParts ); - assert( nSupp == pVar->nParts ); - assert( nSupp != 1 ); - - // if it appears in only two partitions, quantify it - if ( pVar->nParts == 2 ) - { - // get the nodes - iNode1 = pVar->bParts->index; - iNode2 = cuddT(pVar->bParts)->index; - pNode1 = pNodes[iNode1]; - pNode2 = pNodes[iNode2]; - - // get the quantification cube - bCube = dd->vars[pVar->iNum]; Cudd_Ref( bCube ); - // add the variables that appear only in these partitions - for ( v = 0; v < nVars; v++ ) - if ( pVars[v] && v != iVarBest && pVars[v]->bParts == pVars[iVarBest]->bParts ) - { - // add this var - bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[pVars[v]->iNum] ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( dd, bTemp ); - // clean this var - Cudd_RecursiveDeref( dd, pVars[v]->bParts ); - ABC_FREE( pVars[v] ); - } - // clean the best var - Cudd_RecursiveDeref( dd, pVars[iVarBest]->bParts ); - ABC_FREE( pVars[iVarBest] ); - - // combines two nodes - pNode = Extra_CombineTwoNodes( dd, bCube, pNode1, pNode2 ); - Cudd_RecursiveDeref( dd, bCube ); - } - else // if ( pVar->nParts > 2 ) - { - // find two smallest BDDs that have this var - Extra_FindBestPartitions( dd, pVar->bParts, nNodes, pNodes, &iNode1, &iNode2 ); - pNode1 = pNodes[iNode1]; - pNode2 = pNodes[iNode2]; - - // it is not possible that a var appears only in these two - // otherwise, it would have a different cost - bParts = Cudd_bddAnd( dd, dd->vars[iNode1], dd->vars[iNode2] ); Cudd_Ref( bParts ); - for ( v = 0; v < nVars; v++ ) - if ( pVars[v] && pVars[v]->bParts == bParts ) - assert( 0 ); - Cudd_RecursiveDeref( dd, bParts ); - - // combines two nodes - pNode = Extra_CombineTwoNodes( dd, b1, pNode1, pNode2 ); - } - - // clean the old nodes - pNodes[iNode1] = pNode; - pNodes[iNode2] = NULL; - - // update the variables that appear in pNode[iNode2] - for ( bSuppTemp = pNode2->pPart->bSupp; bSuppTemp != b1; bSuppTemp = cuddT(bSuppTemp) ) - { - pVar = pVars[bSuppTemp->index]; - if ( pVar == NULL ) // this variable is not be quantified - continue; - // quantify this var - assert( Cudd_bddLeq( dd, pVar->bParts, dd->vars[iNode2] ) ); - pVar->bParts = Cudd_bddExistAbstract( dd, bTemp = pVar->bParts, dd->vars[iNode2] ); Cudd_Ref( pVar->bParts ); - Cudd_RecursiveDeref( dd, bTemp ); - // add the new var - pVar->bParts = Cudd_bddAnd( dd, bTemp = pVar->bParts, dd->vars[iNode1] ); Cudd_Ref( pVar->bParts ); - Cudd_RecursiveDeref( dd, bTemp ); - // update the score - pVar->nParts = Extra_bddSuppSize( dd, pVar->bParts ); - } - return 1; -} - - -/**Function************************************************************* - - Synopsis [Merges the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Extra_ImageNode_t * Extra_MergeTopNodes( - DdManager * dd, int nNodes, Extra_ImageNode_t ** pNodes ) -{ - Extra_ImageNode_t * pNode; - int n1 = -1, n2 = -1, n; - - // find the first and the second non-empty spots - for ( n = 0; n < nNodes; n++ ) - if ( pNodes[n] ) - { - if ( n1 == -1 ) - n1 = n; - else if ( n2 == -1 ) - { - n2 = n; - break; - } - } - assert( n1 != -1 ); - // check the situation when only one such node is detected - if ( n2 == -1 ) - { - // save the node - pNode = pNodes[n1]; - // clean the node - pNodes[n1] = NULL; - return pNode; - } - - // combines two nodes - pNode = Extra_CombineTwoNodes( dd, b1, pNodes[n1], pNodes[n2] ); - - // clean the old nodes - pNodes[n1] = pNode; - pNodes[n2] = NULL; - return NULL; -} - -/**Function************************************************************* - - Synopsis [Merges two nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Extra_ImageNode_t * Extra_CombineTwoNodes( DdManager * dd, DdNode * bCube, - Extra_ImageNode_t * pNode1, Extra_ImageNode_t * pNode2 ) -{ - Extra_ImageNode_t * pNode; - Extra_ImagePart_t * pPart; - - // create a new partition - pPart = ABC_ALLOC( Extra_ImagePart_t, 1 ); - memset( pPart, 0, sizeof(Extra_ImagePart_t) ); - // create the function - pPart->bFunc = Cudd_bddAndAbstract( dd, pNode1->pPart->bFunc, pNode2->pPart->bFunc, bCube ); - Cudd_Ref( pPart->bFunc ); - // update the support the partition - pPart->bSupp = Cudd_bddAndAbstract( dd, pNode1->pPart->bSupp, pNode2->pPart->bSupp, bCube ); - Cudd_Ref( pPart->bSupp ); - // update the numbers - pPart->nSupp = Extra_bddSuppSize( dd, pPart->bSupp ); - pPart->nNodes = Cudd_DagSize( pPart->bFunc ); - pPart->iPart = -1; -/* -ABC_PRB( dd, pNode1->pPart->bSupp ); -ABC_PRB( dd, pNode2->pPart->bSupp ); -ABC_PRB( dd, pPart->bSupp ); -*/ - // create a new node - pNode = ABC_ALLOC( Extra_ImageNode_t, 1 ); - memset( pNode, 0, sizeof(Extra_ImageNode_t) ); - pNode->dd = dd; - pNode->pPart = pPart; - pNode->pNode1 = pNode1; - pNode->pNode2 = pNode2; - // compute the image - pNode->bImage = Cudd_bddAndAbstract( dd, pNode1->bImage, pNode2->bImage, bCube ); - Cudd_Ref( pNode->bImage ); - // save the cube - if ( bCube != b1 ) - { - pNode->bCube = bCube; Cudd_Ref( bCube ); - } - return pNode; -} - -/**Function************************************************************* - - Synopsis [Computes the best variable.] - - Description [The variables is the best if the sum of squares of the - BDD sizes of the partitions, in which it participates, is the minimum.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_FindBestVariable( DdManager * dd, - int nNodes, Extra_ImageNode_t ** pNodes, - int nVars, Extra_ImageVar_t ** pVars ) -{ - DdNode * bTemp; - int iVarBest, v; - double CostBest, CostCur; - - CostBest = 100000000000000.0; - iVarBest = -1; - for ( v = 0; v < nVars; v++ ) - if ( pVars[v] ) - { - CostCur = 0; - for ( bTemp = pVars[v]->bParts; bTemp != b1; bTemp = cuddT(bTemp) ) - CostCur += pNodes[bTemp->index]->pPart->nNodes * - pNodes[bTemp->index]->pPart->nNodes; - if ( CostBest > CostCur ) - { - CostBest = CostCur; - iVarBest = v; - } - } - return iVarBest; -} - -/**Function************************************************************* - - Synopsis [Computes two smallest partions that have this var.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_FindBestPartitions( DdManager * dd, DdNode * bParts, - int nNodes, Extra_ImageNode_t ** pNodes, - int * piNode1, int * piNode2 ) -{ - DdNode * bTemp; - int iPart1, iPart2; - int CostMin1, CostMin2, Cost; - - // go through the partitions - iPart1 = iPart2 = -1; - CostMin1 = CostMin2 = 1000000; - for ( bTemp = bParts; bTemp != b1; bTemp = cuddT(bTemp) ) - { - Cost = pNodes[bTemp->index]->pPart->nNodes; - if ( CostMin1 > Cost ) - { - CostMin2 = CostMin1; iPart2 = iPart1; - CostMin1 = Cost; iPart1 = bTemp->index; - } - else if ( CostMin2 > Cost ) - { - CostMin2 = Cost; iPart2 = bTemp->index; - } - } - - *piNode1 = iPart1; - *piNode2 = iPart2; -} - -/**Function************************************************************* - - Synopsis [Prints the latch dependency matrix.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_bddImagePrintLatchDependency( - DdManager * dd, DdNode * bCare, // the care set - int nParts, DdNode ** pbParts, // the partitions for image computation - int nVars, DdNode ** pbVars ) // the NS and parameter variables (not quantified!) -{ - int i; - DdNode * bVarsCs, * bVarsNs; - - bVarsCs = Cudd_Support( dd, bCare ); Cudd_Ref( bVarsCs ); - bVarsNs = Cudd_bddComputeCube( dd, pbVars, NULL, nVars ); Cudd_Ref( bVarsNs ); - - printf( "The latch dependency matrix:\n" ); - printf( "Partitions = %d Variables: total = %d non-quantifiable = %d\n", - nParts, dd->size, nVars ); - printf( " : " ); - for ( i = 0; i < dd->size; i++ ) - printf( "%d", i % 10 ); - printf( "\n" ); - - for ( i = 0; i < nParts; i++ ) - Extra_bddImagePrintLatchDependencyOne( dd, pbParts[i], bVarsCs, bVarsNs, i ); - Extra_bddImagePrintLatchDependencyOne( dd, bCare, bVarsCs, bVarsNs, nParts ); - - Cudd_RecursiveDeref( dd, bVarsCs ); - Cudd_RecursiveDeref( dd, bVarsNs ); -} - -/**Function************************************************************* - - Synopsis [Prints one row of the latch dependency matrix.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_bddImagePrintLatchDependencyOne( - DdManager * dd, DdNode * bFunc, // the function - DdNode * bVarsCs, DdNode * bVarsNs, // the current/next state vars - int iPart ) -{ - DdNode * bSupport; - int v; - bSupport = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupport ); - printf( " %3d : ", iPart ); - for ( v = 0; v < dd->size; v++ ) - { - if ( Cudd_bddLeq( dd, bSupport, dd->vars[v] ) ) - { - if ( Cudd_bddLeq( dd, bVarsCs, dd->vars[v] ) ) - printf( "c" ); - else if ( Cudd_bddLeq( dd, bVarsNs, dd->vars[v] ) ) - printf( "n" ); - else - printf( "i" ); - } - else - printf( "." ); - } - printf( "\n" ); - Cudd_RecursiveDeref( dd, bSupport ); -} - - -/**Function************************************************************* - - Synopsis [Prints the tree for quenstification scheduling.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_bddImagePrintTree( Extra_ImageTree_t * pTree ) -{ - printf( "The quantification scheduling tree:\n" ); - Extra_bddImagePrintTree_rec( pTree->pRoot, 1 ); -} - -/**Function************************************************************* - - Synopsis [Prints the tree for quenstification scheduling.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_bddImagePrintTree_rec( Extra_ImageNode_t * pNode, int Offset ) -{ - DdNode * Cube; - int i; - - Cube = pNode->bCube; - - if ( pNode->pNode1 == NULL ) - { - printf( "<%d> ", pNode->pPart->iPart ); - if ( Cube != NULL ) - { - ABC_PRB( pNode->dd, Cube ); - } - else - printf( "\n" ); - return; - } - - printf( "<*> " ); - if ( Cube != NULL ) - { - ABC_PRB( pNode->dd, Cube ); - } - else - printf( "\n" ); - - for ( i = 0; i < Offset; i++ ) - printf( " " ); - Extra_bddImagePrintTree_rec( pNode->pNode1, Offset + 1 ); - - for ( i = 0; i < Offset; i++ ) - printf( " " ); - Extra_bddImagePrintTree_rec( pNode->pNode2, Offset + 1 ); -} - - - - - -struct Extra_ImageTree2_t_ -{ - DdManager * dd; - DdNode * bRel; - DdNode * bCube; - DdNode * bImage; -}; - -/**Function************************************************************* - - Synopsis [Starts the monolithic image computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Extra_ImageTree2_t * Extra_bddImageStart2( - DdManager * dd, DdNode * bCare, - int nParts, DdNode ** pbParts, - int nVars, DdNode ** pbVars, int fVerbose ) -{ - Extra_ImageTree2_t * pTree; - DdNode * bCubeAll, * bCubeNot, * bTemp; - int i; - - pTree = ABC_ALLOC( Extra_ImageTree2_t, 1 ); - pTree->dd = dd; - pTree->bImage = NULL; - - bCubeAll = Extra_bddComputeCube( dd, dd->vars, dd->size ); Cudd_Ref( bCubeAll ); - bCubeNot = Extra_bddComputeCube( dd, pbVars, nVars ); Cudd_Ref( bCubeNot ); - pTree->bCube = Cudd_bddExistAbstract( dd, bCubeAll, bCubeNot ); Cudd_Ref( pTree->bCube ); - Cudd_RecursiveDeref( dd, bCubeAll ); - Cudd_RecursiveDeref( dd, bCubeNot ); - - // derive the monolithic relation - pTree->bRel = b1; Cudd_Ref( pTree->bRel ); - for ( i = 0; i < nParts; i++ ) - { - pTree->bRel = Cudd_bddAnd( dd, bTemp = pTree->bRel, pbParts[i] ); Cudd_Ref( pTree->bRel ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Extra_bddImageCompute2( pTree, bCare ); - return pTree; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddImageCompute2( Extra_ImageTree2_t * pTree, DdNode * bCare ) -{ - if ( pTree->bImage ) - Cudd_RecursiveDeref( pTree->dd, pTree->bImage ); - pTree->bImage = Cudd_bddAndAbstract( pTree->dd, pTree->bRel, bCare, pTree->bCube ); - Cudd_Ref( pTree->bImage ); - return pTree->bImage; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_bddImageTreeDelete2( Extra_ImageTree2_t * pTree ) -{ - if ( pTree->bRel ) - Cudd_RecursiveDeref( pTree->dd, pTree->bRel ); - if ( pTree->bCube ) - Cudd_RecursiveDeref( pTree->dd, pTree->bCube ); - if ( pTree->bImage ) - Cudd_RecursiveDeref( pTree->dd, pTree->bImage ); - ABC_FREE( pTree ); -} - -/**Function************************************************************* - - Synopsis [Returns the previously computed image.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddImageRead2( Extra_ImageTree2_t * pTree ) -{ - return pTree->bImage; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/misc/extra/extraBddKmap.c b/src/misc/extra/extraBddKmap.c deleted file mode 100644 index aa5efe75..00000000 --- a/src/misc/extra/extraBddKmap.c +++ /dev/null @@ -1,876 +0,0 @@ -/**CFile**************************************************************** - - FileName [extraBddKmap.c] - - PackageName [extra] - - Synopsis [Visualizing the K-map.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - September 1, 2003.] - - Revision [$Id: extraBddKmap.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $] - -***********************************************************************/ - -/// K-map visualization using pseudo graphics /// -/// Version 1.0. Started - August 20, 2000 /// -/// Version 2.0. Added to EXTRA - July 17, 2001 /// - -#include "extraBdd.h" - -#ifdef WIN32 -#include -#endif - -ABC_NAMESPACE_IMPL_START - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -// the maximum number of variables in the Karnaugh Map -#define MAXVARS 20 - -/* -// single line -#define SINGLE_VERTICAL (char)179 -#define SINGLE_HORIZONTAL (char)196 -#define SINGLE_TOP_LEFT (char)218 -#define SINGLE_TOP_RIGHT (char)191 -#define SINGLE_BOT_LEFT (char)192 -#define SINGLE_BOT_RIGHT (char)217 - -// double line -#define DOUBLE_VERTICAL (char)186 -#define DOUBLE_HORIZONTAL (char)205 -#define DOUBLE_TOP_LEFT (char)201 -#define DOUBLE_TOP_RIGHT (char)187 -#define DOUBLE_BOT_LEFT (char)200 -#define DOUBLE_BOT_RIGHT (char)188 - -// line intersections -#define SINGLES_CROSS (char)197 -#define DOUBLES_CROSS (char)206 -#define S_HOR_CROSS_D_VER (char)215 -#define S_VER_CROSS_D_HOR (char)216 - -// single line joining -#define S_JOINS_S_VER_LEFT (char)180 -#define S_JOINS_S_VER_RIGHT (char)195 -#define S_JOINS_S_HOR_TOP (char)193 -#define S_JOINS_S_HOR_BOT (char)194 - -// double line joining -#define D_JOINS_D_VER_LEFT (char)185 -#define D_JOINS_D_VER_RIGHT (char)204 -#define D_JOINS_D_HOR_TOP (char)202 -#define D_JOINS_D_HOR_BOT (char)203 - -// single line joining double line -#define S_JOINS_D_VER_LEFT (char)182 -#define S_JOINS_D_VER_RIGHT (char)199 -#define S_JOINS_D_HOR_TOP (char)207 -#define S_JOINS_D_HOR_BOT (char)209 -*/ - -// single line -#define SINGLE_VERTICAL (char)'|' -#define SINGLE_HORIZONTAL (char)'-' -#define SINGLE_TOP_LEFT (char)'+' -#define SINGLE_TOP_RIGHT (char)'+' -#define SINGLE_BOT_LEFT (char)'+' -#define SINGLE_BOT_RIGHT (char)'+' - -// double line -#define DOUBLE_VERTICAL (char)'|' -#define DOUBLE_HORIZONTAL (char)'-' -#define DOUBLE_TOP_LEFT (char)'+' -#define DOUBLE_TOP_RIGHT (char)'+' -#define DOUBLE_BOT_LEFT (char)'+' -#define DOUBLE_BOT_RIGHT (char)'+' - -// line intersections -#define SINGLES_CROSS (char)'+' -#define DOUBLES_CROSS (char)'+' -#define S_HOR_CROSS_D_VER (char)'+' -#define S_VER_CROSS_D_HOR (char)'+' - -// single line joining -#define S_JOINS_S_VER_LEFT (char)'+' -#define S_JOINS_S_VER_RIGHT (char)'+' -#define S_JOINS_S_HOR_TOP (char)'+' -#define S_JOINS_S_HOR_BOT (char)'+' - -// double line joining -#define D_JOINS_D_VER_LEFT (char)'+' -#define D_JOINS_D_VER_RIGHT (char)'+' -#define D_JOINS_D_HOR_TOP (char)'+' -#define D_JOINS_D_HOR_BOT (char)'+' - -// single line joining double line -#define S_JOINS_D_VER_LEFT (char)'+' -#define S_JOINS_D_VER_RIGHT (char)'+' -#define S_JOINS_D_HOR_TOP (char)'+' -#define S_JOINS_D_HOR_BOT (char)'+' - - -// other symbols -#define UNDERSCORE (char)95 -//#define SYMBOL_ZERO (char)248 // degree sign -//#define SYMBOL_ZERO (char)'o' -#ifdef WIN32 -#define SYMBOL_ZERO (char)'0' -#else -#define SYMBOL_ZERO (char)' ' -#endif -#define SYMBOL_ONE (char)'1' -#define SYMBOL_DC (char)'-' -#define SYMBOL_OVERLAP (char)'?' - -// full cells and half cells -#define CELL_FREE (char)32 -#define CELL_FULL (char)219 -#define HALF_UPPER (char)223 -#define HALF_LOWER (char)220 -#define HALF_LEFT (char)221 -#define HALF_RIGHT (char)222 - - -/*---------------------------------------------------------------------------*/ -/* Structure declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -// the array of BDD variables used internally -static DdNode * s_XVars[MAXVARS]; - -// flag which determines where the horizontal variable names are printed -static int fHorizontalVarNamesPrintedAbove = 1; - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -// Oleg's way of generating the gray code -static int GrayCode( int BinCode ); -static int BinCode ( int GrayCode ); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Prints the K-map of the function.] - - Description [If the pointer to the array of variables XVars is NULL, - fSuppType determines how the support will be determined. - fSuppType == 0 -- takes the first nVars of the manager - fSuppType == 1 -- takes the topmost nVars of the manager - fSuppType == 2 -- determines support from the on-set and the offset - ] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Extra_PrintKMap( - FILE * Output, /* the output stream */ - DdManager * dd, - DdNode * OnSet, - DdNode * OffSet, - int nVars, - DdNode ** XVars, - int fSuppType, /* the flag which determines how support is computed */ - char ** pVarNames ) -{ - int fPrintTruth = 1; - int d, p, n, s, v, h, w; - int nVarsVer; - int nVarsHor; - int nCellsVer; - int nCellsHor; - int nSkipSpaces; - - // make sure that on-set and off-set do not overlap - if ( !Cudd_bddLeq( dd, OnSet, Cudd_Not(OffSet) ) ) - { - fprintf( Output, "PrintKMap(): The on-set and the off-set overlap\n" ); - return; - } - if ( nVars == 0 ) - { printf( "Function is constant %d.\n", !Cudd_IsComplement(OnSet) ); return; } - - // print truth table for debugging - if ( fPrintTruth ) - { - DdNode * bCube, * bPart; - printf( "Truth table: " ); - if ( nVars == 0 ) - printf( "Constant" ); - else if ( nVars == 1 ) - printf( "1-var function" ); - else - { -// printf( "0x" ); - for ( d = (1<<(nVars-2)) - 1; d >= 0; d-- ) - { - int Value = 0; - for ( s = 0; s < 4; s++ ) - { - bCube = Extra_bddBitsToCube( dd, 4*d+s, nVars, dd->vars, 0 ); Cudd_Ref( bCube ); - bPart = Cudd_Cofactor( dd, OnSet, bCube ); Cudd_Ref( bPart ); - Value |= ((int)(bPart == b1) << s); - Cudd_RecursiveDeref( dd, bPart ); - Cudd_RecursiveDeref( dd, bCube ); - } - if ( Value < 10 ) - fprintf( stdout, "%d", Value ); - else - fprintf( stdout, "%c", 'a' + Value-10 ); - } - } - printf( "\n" ); - } - - -/* - if ( OnSet == b1 ) - { - fprintf( Output, "PrintKMap(): Constant 1\n" ); - return; - } - if ( OffSet == b1 ) - { - fprintf( Output, "PrintKMap(): Constant 0\n" ); - return; - } -*/ - if ( nVars < 0 || nVars > MAXVARS ) - { - fprintf( Output, "PrintKMap(): The number of variables is less than zero or more than %d\n", MAXVARS ); - return; - } - - // determine the support if it is not given - if ( XVars == NULL ) - { - if ( fSuppType == 0 ) - { // assume that the support includes the first nVars of the manager - assert( nVars ); - for ( v = 0; v < nVars; v++ ) - s_XVars[v] = Cudd_bddIthVar( dd, v ); - } - else if ( fSuppType == 1 ) - { // assume that the support includes the topmost nVars of the manager - assert( nVars ); - for ( v = 0; v < nVars; v++ ) - s_XVars[v] = Cudd_bddIthVar( dd, dd->invperm[v] ); - } - else // determine the support - { - DdNode * SuppOn, * SuppOff, * Supp; - int cVars = 0; - DdNode * TempSupp; - - // determine support - SuppOn = Cudd_Support( dd, OnSet ); Cudd_Ref( SuppOn ); - SuppOff = Cudd_Support( dd, OffSet ); Cudd_Ref( SuppOff ); - Supp = Cudd_bddAnd( dd, SuppOn, SuppOff ); Cudd_Ref( Supp ); - Cudd_RecursiveDeref( dd, SuppOn ); - Cudd_RecursiveDeref( dd, SuppOff ); - - nVars = Cudd_SupportSize( dd, Supp ); - if ( nVars > MAXVARS ) - { - fprintf( Output, "PrintKMap(): The number of variables is more than %d\n", MAXVARS ); - Cudd_RecursiveDeref( dd, Supp ); - return; - } - - // assign variables - for ( TempSupp = Supp; TempSupp != dd->one; TempSupp = Cudd_T(TempSupp), cVars++ ) - s_XVars[cVars] = Cudd_bddIthVar( dd, TempSupp->index ); - - Cudd_RecursiveDeref( dd, TempSupp ); - } - } - else - { - // copy variables - assert( XVars ); - for ( v = 0; v < nVars; v++ ) - s_XVars[v] = XVars[v]; - } - - //////////////////////////////////////////////////////////////////// - // determine the Karnaugh map parameters - nVarsVer = nVars/2; - nVarsHor = nVars - nVarsVer; - - nCellsVer = (1< MAXVARS ) - { - fprintf( Output, "PrintKMap(): The number of variables is less than zero or more than %d\n", MAXVARS ); - return; - } - - - //////////////////////////////////////////////////////////////////// - // determine the Karnaugh map parameters - nVarsVer = nXVars; - nVarsHor = nYVars; - nCellsVer = (1<> 1 ); -} - -/**Function******************************************************************** - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int BinCode ( int GrayCode ) -{ - int bc = GrayCode; - while( GrayCode >>= 1 ) bc ^= GrayCode; - return bc; -} - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/misc/extra/extraBddMisc.c b/src/misc/extra/extraBddMisc.c deleted file mode 100644 index a2ba4036..00000000 --- a/src/misc/extra/extraBddMisc.c +++ /dev/null @@ -1,2342 +0,0 @@ -/**CFile**************************************************************** - - FileName [extraBddMisc.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [extra] - - Synopsis [DD-based utilities.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: extraBddMisc.c,v 1.4 2005/10/04 00:19:54 alanmi Exp $] - -***********************************************************************/ - -#include "extraBdd.h" - -ABC_NAMESPACE_IMPL_START - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -// file "extraDdTransfer.c" -static DdNode * extraTransferPermuteRecur( DdManager * ddS, DdManager * ddD, DdNode * f, st__table * table, int * Permute ); -static DdNode * extraTransferPermute( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute ); -static DdNode * cuddBddPermuteRecur ARGS( ( DdManager * manager, DdHashTable * table, DdNode * node, int *permut ) ); - -static DdNode * extraBddAndPermute( DdHashTable * table, DdManager * ddF, DdNode * bF, DdManager * ddG, DdNode * bG, int * pPermute ); - -// file "cuddUtils.c" -static void ddSupportStep(DdNode *f, int *support); -static void ddClearFlag(DdNode *f); - -static DdNode* extraZddPrimes( DdManager *dd, DdNode* F ); - -/**AutomaticEnd***************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Convert a {A,B}DD from a manager to another with variable remapping.] - - Description [Convert a {A,B}DD from a manager to another one. The orders of the - variables in the two managers may be different. Returns a - pointer to the {A,B}DD in the destination manager if successful; NULL - otherwise. The i-th entry in the array Permute tells what is the index - of the i-th variable from the old manager in the new manager.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_TransferPermute( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute ) -{ - DdNode * bRes; - do - { - ddDestination->reordered = 0; - bRes = extraTransferPermute( ddSource, ddDestination, f, Permute ); - } - while ( ddDestination->reordered == 1 ); - return ( bRes ); - -} /* end of Extra_TransferPermute */ - -/**Function******************************************************************** - - Synopsis [Transfers the BDD from one manager into another level by level.] - - Description [Transfers the BDD from one manager into another while - preserving the correspondence between variables level by level.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_TransferLevelByLevel( DdManager * ddSource, DdManager * ddDestination, DdNode * f ) -{ - DdNode * bRes; - int * pPermute; - int nMin, nMax, i; - - nMin = ddMin(ddSource->size, ddDestination->size); - nMax = ddMax(ddSource->size, ddDestination->size); - pPermute = ABC_ALLOC( int, nMax ); - // set up the variable permutation - for ( i = 0; i < nMin; i++ ) - pPermute[ ddSource->invperm[i] ] = ddDestination->invperm[i]; - if ( ddSource->size > ddDestination->size ) - { - for ( ; i < nMax; i++ ) - pPermute[ ddSource->invperm[i] ] = -1; - } - bRes = Extra_TransferPermute( ddSource, ddDestination, f, pPermute ); - ABC_FREE( pPermute ); - return bRes; -} - -/**Function******************************************************************** - - Synopsis [Remaps the function to depend on the topmost variables on the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddRemapUp( - DdManager * dd, - DdNode * bF ) -{ - int * pPermute; - DdNode * bSupp, * bTemp, * bRes; - int Counter; - - pPermute = ABC_ALLOC( int, dd->size ); - - // get support - bSupp = Cudd_Support( dd, bF ); Cudd_Ref( bSupp ); - - // create the variable map - // to remap the DD into the upper part of the manager - Counter = 0; - for ( bTemp = bSupp; bTemp != dd->one; bTemp = cuddT(bTemp) ) - pPermute[bTemp->index] = dd->invperm[Counter++]; - - // transfer the BDD and remap it - bRes = Cudd_bddPermute( dd, bF, pPermute ); Cudd_Ref( bRes ); - - // remove support - Cudd_RecursiveDeref( dd, bSupp ); - - // return - Cudd_Deref( bRes ); - ABC_FREE( pPermute ); - return bRes; -} - -/**Function******************************************************************** - - Synopsis [Moves the BDD by the given number of variables up or down.] - - Description [] - - SideEffects [] - - SeeAlso [Extra_bddShift] - -******************************************************************************/ -DdNode * Extra_bddMove( - DdManager * dd, /* the DD manager */ - DdNode * bF, - int nVars) -{ - DdNode * res; - DdNode * bVars; - if ( nVars == 0 ) - return bF; - if ( Cudd_IsConstant(bF) ) - return bF; - assert( nVars <= dd->size ); - if ( nVars > 0 ) - bVars = dd->vars[nVars]; - else - bVars = Cudd_Not(dd->vars[-nVars]); - - do { - dd->reordered = 0; - res = extraBddMove( dd, bF, bVars ); - } while (dd->reordered == 1); - return(res); - -} /* end of Extra_bddMove */ - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_StopManager( DdManager * dd ) -{ - int RetValue; - // check for remaining references in the package - RetValue = Cudd_CheckZeroRef( dd ); - if ( RetValue > 10 ) -// if ( RetValue ) - printf( "\nThe number of referenced nodes = %d\n\n", RetValue ); -// Cudd_PrintInfo( dd, stdout ); - Cudd_Quit( dd ); -} - -/**Function******************************************************************** - - Synopsis [Outputs the BDD in a readable format.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void Extra_bddPrint( DdManager * dd, DdNode * F ) -{ - DdGen * Gen; - int * Cube; - CUDD_VALUE_TYPE Value; - int nVars = dd->size; - int fFirstCube = 1; - int i; - - if ( F == NULL ) - { - printf("NULL"); - return; - } - if ( F == b0 ) - { - printf("Constant 0"); - return; - } - if ( F == b1 ) - { - printf("Constant 1"); - return; - } - - Cudd_ForeachCube( dd, F, Gen, Cube, Value ) - { - if ( fFirstCube ) - fFirstCube = 0; - else -// Output << " + "; - printf( " + " ); - - for ( i = 0; i < nVars; i++ ) - if ( Cube[i] == 0 ) - printf( "[%d]'", i ); -// printf( "%c'", (char)('a'+i) ); - else if ( Cube[i] == 1 ) - printf( "[%d]", i ); -// printf( "%c", (char)('a'+i) ); - } - -// printf("\n"); -} - -/**Function******************************************************************** - - Synopsis [Outputs the BDD in a readable format.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void Extra_bddPrintSupport( DdManager * dd, DdNode * F ) -{ - DdNode * bSupp; - bSupp = Cudd_Support( dd, F ); Cudd_Ref( bSupp ); - Extra_bddPrint( dd, bSupp ); - Cudd_RecursiveDeref( dd, bSupp ); -} - -/**Function******************************************************************** - - Synopsis [Returns the size of the support.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_bddSuppSize( DdManager * dd, DdNode * bSupp ) -{ - int Counter = 0; - while ( bSupp != b1 ) - { - assert( !Cudd_IsComplement(bSupp) ); - assert( cuddE(bSupp) == b0 ); - - bSupp = cuddT(bSupp); - Counter++; - } - return Counter; -} - -/**Function******************************************************************** - - Synopsis [Returns 1 if the support contains the given BDD variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_bddSuppContainVar( DdManager * dd, DdNode * bS, DdNode * bVar ) -{ - for( ; bS != b1; bS = cuddT(bS) ) - if ( bS->index == bVar->index ) - return 1; - return 0; -} - -/**Function******************************************************************** - - Synopsis [Returns 1 if two supports represented as BDD cubes are overlapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_bddSuppOverlapping( DdManager * dd, DdNode * S1, DdNode * S2 ) -{ - while ( S1->index != CUDD_CONST_INDEX && S2->index != CUDD_CONST_INDEX ) - { - // if the top vars are the same, they intersect - if ( S1->index == S2->index ) - return 1; - // if the top vars are different, skip the one, which is higher - if ( dd->perm[S1->index] < dd->perm[S2->index] ) - S1 = cuddT(S1); - else - S2 = cuddT(S2); - } - return 0; -} - -/**Function******************************************************************** - - Synopsis [Returns the number of different vars in two supports.] - - Description [Counts the number of variables that appear in one support and - does not appear in other support. If the number exceeds DiffMax, returns DiffMax.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_bddSuppDifferentVars( DdManager * dd, DdNode * S1, DdNode * S2, int DiffMax ) -{ - int Result = 0; - while ( S1->index != CUDD_CONST_INDEX && S2->index != CUDD_CONST_INDEX ) - { - // if the top vars are the same, this var is the same - if ( S1->index == S2->index ) - { - S1 = cuddT(S1); - S2 = cuddT(S2); - continue; - } - // the top var is different - Result++; - - if ( Result >= DiffMax ) - return DiffMax; - - // if the top vars are different, skip the one, which is higher - if ( dd->perm[S1->index] < dd->perm[S2->index] ) - S1 = cuddT(S1); - else - S2 = cuddT(S2); - } - - // consider the remaining variables - if ( S1->index != CUDD_CONST_INDEX ) - Result += Extra_bddSuppSize(dd,S1); - else if ( S2->index != CUDD_CONST_INDEX ) - Result += Extra_bddSuppSize(dd,S2); - - if ( Result >= DiffMax ) - return DiffMax; - return Result; -} - - -/**Function******************************************************************** - - Synopsis [Checks the support containment.] - - Description [This function returns 1 if one support is contained in another. - In this case, bLarge (bSmall) is assigned to point to the larger (smaller) support. - If the supports are identical, return 0 and does not assign the supports!] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_bddSuppCheckContainment( DdManager * dd, DdNode * bL, DdNode * bH, DdNode ** bLarge, DdNode ** bSmall ) -{ - DdNode * bSL = bL; - DdNode * bSH = bH; - int fLcontainsH = 1; - int fHcontainsL = 1; - int TopVar; - - if ( bSL == bSH ) - return 0; - - while ( bSL != b1 || bSH != b1 ) - { - if ( bSL == b1 ) - { // Low component has no vars; High components has some vars - fLcontainsH = 0; - if ( fHcontainsL == 0 ) - return 0; - else - break; - } - - if ( bSH == b1 ) - { // similarly - fHcontainsL = 0; - if ( fLcontainsH == 0 ) - return 0; - else - break; - } - - // determine the topmost var of the supports by comparing their levels - if ( dd->perm[bSL->index] < dd->perm[bSH->index] ) - TopVar = bSL->index; - else - TopVar = bSH->index; - - if ( TopVar == bSL->index && TopVar == bSH->index ) - { // they are on the same level - // it does not tell us anything about their containment - // skip this var - bSL = cuddT(bSL); - bSH = cuddT(bSH); - } - else if ( TopVar == bSL->index ) // and TopVar != bSH->index - { // Low components is higher and contains more vars - // it is not possible that High component contains Low - fHcontainsL = 0; - // skip this var - bSL = cuddT(bSL); - } - else // if ( TopVar == bSH->index ) // and TopVar != bSL->index - { // similarly - fLcontainsH = 0; - // skip this var - bSH = cuddT(bSH); - } - - // check the stopping condition - if ( !fHcontainsL && !fLcontainsH ) - return 0; - } - // only one of them can be true at the same time - assert( !fHcontainsL || !fLcontainsH ); - if ( fHcontainsL ) - { - *bLarge = bH; - *bSmall = bL; - } - else // fLcontainsH - { - *bLarge = bL; - *bSmall = bH; - } - return 1; -} - - -/**Function******************************************************************** - - Synopsis [Finds variables on which the DD depends and returns them as am array.] - - Description [Finds the variables on which the DD depends. Returns an array - with entries set to 1 for those variables that belong to the support; - NULL otherwise. The array is allocated by the user and should have at least - as many entries as the maximum number of variables in BDD and ZDD parts of - the manager.] - - SideEffects [None] - - SeeAlso [Cudd_Support Cudd_VectorSupport Cudd_ClassifySupport] - -******************************************************************************/ -int * -Extra_SupportArray( - DdManager * dd, /* manager */ - DdNode * f, /* DD whose support is sought */ - int * support ) /* array allocated by the user */ -{ - int i, size; - - /* Initialize support array for ddSupportStep. */ - size = ddMax(dd->size, dd->sizeZ); - for (i = 0; i < size; i++) - support[i] = 0; - - /* Compute support and clean up markers. */ - ddSupportStep(Cudd_Regular(f),support); - ddClearFlag(Cudd_Regular(f)); - - return(support); - -} /* end of Extra_SupportArray */ - -/**Function******************************************************************** - - Synopsis [Finds the variables on which a set of DDs depends.] - - Description [Finds the variables on which a set of DDs depends. - The set must contain either BDDs and ADDs, or ZDDs. - Returns a BDD consisting of the product of the variables if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_Support Cudd_ClassifySupport] - -******************************************************************************/ -int * -Extra_VectorSupportArray( - DdManager * dd, /* manager */ - DdNode ** F, /* array of DDs whose support is sought */ - int n, /* size of the array */ - int * support ) /* array allocated by the user */ -{ - int i, size; - - /* Allocate and initialize support array for ddSupportStep. */ - size = ddMax( dd->size, dd->sizeZ ); - for ( i = 0; i < size; i++ ) - support[i] = 0; - - /* Compute support and clean up markers. */ - for ( i = 0; i < n; i++ ) - ddSupportStep( Cudd_Regular(F[i]), support ); - for ( i = 0; i < n; i++ ) - ddClearFlag( Cudd_Regular(F[i]) ); - - return support; -} - -/**Function******************************************************************** - - Synopsis [Find any cube belonging to the on-set of the function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddFindOneCube( DdManager * dd, DdNode * bF ) -{ - char * s_Temp; - DdNode * bCube, * bTemp; - int v; - - // get the vector of variables in the cube - s_Temp = ABC_ALLOC( char, dd->size ); - Cudd_bddPickOneCube( dd, bF, s_Temp ); - - // start the cube - bCube = b1; Cudd_Ref( bCube ); - for ( v = 0; v < dd->size; v++ ) - if ( s_Temp[v] == 0 ) - { -// Cube &= !s_XVars[v]; - bCube = Cudd_bddAnd( dd, bTemp = bCube, Cudd_Not(dd->vars[v]) ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( dd, bTemp ); - } - else if ( s_Temp[v] == 1 ) - { -// Cube &= s_XVars[v]; - bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[v] ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref(bCube); - ABC_FREE( s_Temp ); - return bCube; -} - -/**Function******************************************************************** - - Synopsis [Returns one cube contained in the given BDD.] - - Description [This function returns the cube with the smallest - bits-to-integer value.] - - SideEffects [] - -******************************************************************************/ -DdNode * Extra_bddGetOneCube( DdManager * dd, DdNode * bFunc ) -{ - DdNode * bFuncR, * bFunc0, * bFunc1; - DdNode * bRes0, * bRes1, * bRes; - - bFuncR = Cudd_Regular(bFunc); - if ( cuddIsConstant(bFuncR) ) - return bFunc; - - // cofactor - if ( Cudd_IsComplement(bFunc) ) - { - bFunc0 = Cudd_Not( cuddE(bFuncR) ); - bFunc1 = Cudd_Not( cuddT(bFuncR) ); - } - else - { - bFunc0 = cuddE(bFuncR); - bFunc1 = cuddT(bFuncR); - } - - // try to find the cube with the negative literal - bRes0 = Extra_bddGetOneCube( dd, bFunc0 ); Cudd_Ref( bRes0 ); - - if ( bRes0 != b0 ) - { - bRes = Cudd_bddAnd( dd, bRes0, Cudd_Not(dd->vars[bFuncR->index]) ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bRes0 ); - } - else - { - Cudd_RecursiveDeref( dd, bRes0 ); - // try to find the cube with the positive literal - bRes1 = Extra_bddGetOneCube( dd, bFunc1 ); Cudd_Ref( bRes1 ); - assert( bRes1 != b0 ); - bRes = Cudd_bddAnd( dd, bRes1, dd->vars[bFuncR->index] ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bRes1 ); - } - - Cudd_Deref( bRes ); - return bRes; -} - -/**Function******************************************************************** - - Synopsis [Performs the reordering-sensitive step of Extra_bddMove().] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddComputeRangeCube( DdManager * dd, int iStart, int iStop ) -{ - DdNode * bTemp, * bProd; - int i; - assert( iStart <= iStop ); - assert( iStart >= 0 && iStart <= dd->size ); - assert( iStop >= 0 && iStop <= dd->size ); - bProd = b1; Cudd_Ref( bProd ); - for ( i = iStart; i < iStop; i++ ) - { - bProd = Cudd_bddAnd( dd, bTemp = bProd, dd->vars[i] ); Cudd_Ref( bProd ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bProd ); - return bProd; -} - -/**Function******************************************************************** - - Synopsis [Computes the cube of BDD variables corresponding to bits it the bit-code] - - Description [Returns a bdd composed of elementary bdds found in array BddVars[] such - that the bdd vars encode the number Value of bit length CodeWidth (if fMsbFirst is 1, - the most significant bit is encoded with the first bdd variable). If the variables - BddVars are not specified, takes the first CodeWidth variables of the manager] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddBitsToCube( DdManager * dd, int Code, int CodeWidth, DdNode ** pbVars, int fMsbFirst ) -{ - int z; - DdNode * bTemp, * bVar, * bVarBdd, * bResult; - - bResult = b1; Cudd_Ref( bResult ); - for ( z = 0; z < CodeWidth; z++ ) - { - bVarBdd = (pbVars)? pbVars[z]: dd->vars[z]; - if ( fMsbFirst ) - bVar = Cudd_NotCond( bVarBdd, (Code & (1 << (CodeWidth-1-z)))==0 ); - else - bVar = Cudd_NotCond( bVarBdd, (Code & (1 << (z)))==0 ); - bResult = Cudd_bddAnd( dd, bTemp = bResult, bVar ); Cudd_Ref( bResult ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bResult ); - - return bResult; -} /* end of Extra_bddBitsToCube */ - -/**Function******************************************************************** - - Synopsis [Finds the support as a negative polarity cube.] - - Description [Finds the variables on which a DD depends. Returns a BDD - consisting of the product of the variables in the negative polarity - if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_VectorSupport Cudd_Support] - -******************************************************************************/ -DdNode * Extra_bddSupportNegativeCube( DdManager * dd, DdNode * f ) -{ - int *support; - DdNode *res, *tmp, *var; - int i, j; - int size; - - /* Allocate and initialize support array for ddSupportStep. */ - size = ddMax( dd->size, dd->sizeZ ); - support = ABC_ALLOC( int, size ); - if ( support == NULL ) - { - dd->errorCode = CUDD_MEMORY_OUT; - return ( NULL ); - } - for ( i = 0; i < size; i++ ) - { - support[i] = 0; - } - - /* Compute support and clean up markers. */ - ddSupportStep( Cudd_Regular( f ), support ); - ddClearFlag( Cudd_Regular( f ) ); - - /* Transform support from array to cube. */ - do - { - dd->reordered = 0; - res = DD_ONE( dd ); - cuddRef( res ); - for ( j = size - 1; j >= 0; j-- ) - { /* for each level bottom-up */ - i = ( j >= dd->size ) ? j : dd->invperm[j]; - if ( support[i] == 1 ) - { - var = cuddUniqueInter( dd, i, dd->one, Cudd_Not( dd->one ) ); - ////////////////////////////////////////////////////////////////// - var = Cudd_Not(var); - ////////////////////////////////////////////////////////////////// - cuddRef( var ); - tmp = cuddBddAndRecur( dd, res, var ); - if ( tmp == NULL ) - { - Cudd_RecursiveDeref( dd, res ); - Cudd_RecursiveDeref( dd, var ); - res = NULL; - break; - } - cuddRef( tmp ); - Cudd_RecursiveDeref( dd, res ); - Cudd_RecursiveDeref( dd, var ); - res = tmp; - } - } - } - while ( dd->reordered == 1 ); - - ABC_FREE( support ); - if ( res != NULL ) - cuddDeref( res ); - return ( res ); - -} /* end of Extra_SupportNeg */ - -/**Function******************************************************************** - - Synopsis [Returns 1 if the BDD is the BDD of elementary variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_bddIsVar( DdNode * bFunc ) -{ - bFunc = Cudd_Regular( bFunc ); - if ( cuddIsConstant(bFunc) ) - return 0; - return cuddIsConstant( cuddT(bFunc) ) && cuddIsConstant( Cudd_Regular(cuddE(bFunc)) ); -} - -/**Function******************************************************************** - - Synopsis [Creates AND composed of the first nVars of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddCreateAnd( DdManager * dd, int nVars ) -{ - DdNode * bFunc, * bTemp; - int i; - bFunc = Cudd_ReadOne(dd); Cudd_Ref( bFunc ); - for ( i = 0; i < nVars; i++ ) - { - bFunc = Cudd_bddAnd( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bFunc ); - return bFunc; -} - -/**Function******************************************************************** - - Synopsis [Creates OR composed of the first nVars of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddCreateOr( DdManager * dd, int nVars ) -{ - DdNode * bFunc, * bTemp; - int i; - bFunc = Cudd_ReadLogicZero(dd); Cudd_Ref( bFunc ); - for ( i = 0; i < nVars; i++ ) - { - bFunc = Cudd_bddOr( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bFunc ); - return bFunc; -} - -/**Function******************************************************************** - - Synopsis [Creates EXOR composed of the first nVars of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddCreateExor( DdManager * dd, int nVars ) -{ - DdNode * bFunc, * bTemp; - int i; - bFunc = Cudd_ReadLogicZero(dd); Cudd_Ref( bFunc ); - for ( i = 0; i < nVars; i++ ) - { - bFunc = Cudd_bddXor( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bFunc ); - return bFunc; -} - -/**Function******************************************************************** - - Synopsis [Computes the set of primes as a ZDD.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_zddPrimes( DdManager * dd, DdNode * F ) -{ - DdNode *res; - do { - dd->reordered = 0; - res = extraZddPrimes(dd, F); - if ( dd->reordered == 1 ) - printf("\nReordering in Extra_zddPrimes()\n"); - } while (dd->reordered == 1); - return(res); - -} /* end of Extra_zddPrimes */ - -/**Function******************************************************************** - - Synopsis [Permutes the variables of the array of BDDs.] - - Description [Given a permutation in array permut, creates a new BDD - with permuted variables. There should be an entry in array permut - for each variable in the manager. The i-th entry of permut holds the - index of the variable that is to substitute the i-th variable. - The DDs in the resulting array are already referenced.] - - SideEffects [None] - - SeeAlso [Cudd_addPermute Cudd_bddSwapVariables] - -******************************************************************************/ -void Extra_bddPermuteArray( DdManager * manager, DdNode ** bNodesIn, DdNode ** bNodesOut, int nNodes, int *permut ) -{ - DdHashTable *table; - int i, k; - do - { - manager->reordered = 0; - table = cuddHashTableInit( manager, 1, 2 ); - - /* permute the output functions one-by-one */ - for ( i = 0; i < nNodes; i++ ) - { - bNodesOut[i] = cuddBddPermuteRecur( manager, table, bNodesIn[i], permut ); - if ( bNodesOut[i] == NULL ) - { - /* deref the array of the already computed outputs */ - for ( k = 0; k < i; k++ ) - Cudd_RecursiveDeref( manager, bNodesOut[k] ); - break; - } - cuddRef( bNodesOut[i] ); - } - /* Dispose of local cache. */ - cuddHashTableQuit( table ); - } - while ( manager->reordered == 1 ); -} /* end of Extra_bddPermuteArray */ - - -/**Function******************************************************************** - - Synopsis [Computes the positive polarty cube composed of the first vars in the array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddComputeCube( DdManager * dd, DdNode ** bXVars, int nVars ) -{ - DdNode * bRes; - DdNode * bTemp; - int i; - - bRes = b1; Cudd_Ref( bRes ); - for ( i = 0; i < nVars; i++ ) - { - bRes = Cudd_bddAnd( dd, bTemp = bRes, bXVars[i] ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - } - - Cudd_Deref( bRes ); - return bRes; -} - -/**Function******************************************************************** - - Synopsis [Changes the polarity of vars listed in the cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddChangePolarity( - DdManager * dd, /* the DD manager */ - DdNode * bFunc, - DdNode * bVars) -{ - DdNode *res; - do { - dd->reordered = 0; - res = extraBddChangePolarity( dd, bFunc, bVars ); - } while (dd->reordered == 1); - return(res); - -} /* end of Extra_bddChangePolarity */ - - -/**Function************************************************************* - - Synopsis [Checks if the given variable belongs to the cube.] - - Description [Return -1 if the var does not appear in the cube. - Otherwise, returns polarity (0 or 1) of the var in the cube.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_bddVarIsInCube( DdNode * bCube, int iVar ) -{ - DdNode * bCube0, * bCube1; - while ( Cudd_Regular(bCube)->index != CUDD_CONST_INDEX ) - { - bCube0 = Cudd_NotCond( cuddE(Cudd_Regular(bCube)), Cudd_IsComplement(bCube) ); - bCube1 = Cudd_NotCond( cuddT(Cudd_Regular(bCube)), Cudd_IsComplement(bCube) ); - // make sure it is a cube - assert( (Cudd_IsComplement(bCube0) && Cudd_Regular(bCube0)->index == CUDD_CONST_INDEX) || // bCube0 == 0 - (Cudd_IsComplement(bCube1) && Cudd_Regular(bCube1)->index == CUDD_CONST_INDEX) ); // bCube1 == 0 - // quit if it is the last one - if ( Cudd_Regular(bCube)->index == iVar ) - return (int)(Cudd_IsComplement(bCube0) && Cudd_Regular(bCube0)->index == CUDD_CONST_INDEX); - // get the next cube - if ( (Cudd_IsComplement(bCube0) && Cudd_Regular(bCube0)->index == CUDD_CONST_INDEX) ) - bCube = bCube1; - else - bCube = bCube0; - } - return -1; -} - -/**Function************************************************************* - - Synopsis [Computes the AND of two BDD with different orders.] - - Description [Derives the result of Boolean AND of bF and bG in ddF. - The array pPermute gives the mapping of variables of ddG into that of ddF.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddAndPermute( DdManager * ddF, DdNode * bF, DdManager * ddG, DdNode * bG, int * pPermute ) -{ - DdHashTable * table; - DdNode * bRes; - do - { - ddF->reordered = 0; - table = cuddHashTableInit( ddF, 2, 256 ); - if (table == NULL) return NULL; - bRes = extraBddAndPermute( table, ddF, bF, ddG, bG, pPermute ); - if ( bRes ) cuddRef( bRes ); - cuddHashTableQuit( table ); - if ( bRes ) cuddDeref( bRes ); -//if ( ddF->reordered == 1 ) -//printf( "Reordering happened\n" ); - } - while ( ddF->reordered == 1 ); -//printf( "|F| =%6d |G| =%6d |H| =%6d |F|*|G| =%9d\n", -// Cudd_DagSize(bF), Cudd_DagSize(bG), Cudd_DagSize(bRes), -// Cudd_DagSize(bF) * Cudd_DagSize(bG) ); - return ( bRes ); -} - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Performs the reordering-sensitive step of Extra_bddMove().] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * extraBddMove( - DdManager * dd, /* the DD manager */ - DdNode * bF, - DdNode * bDist) -{ - DdNode * bRes; - - if ( Cudd_IsConstant(bF) ) - return bF; - - if ( (bRes = cuddCacheLookup2(dd, extraBddMove, bF, bDist)) ) - return bRes; - else - { - DdNode * bRes0, * bRes1; - DdNode * bF0, * bF1; - DdNode * bFR = Cudd_Regular(bF); - int VarNew; - - if ( Cudd_IsComplement(bDist) ) - VarNew = bFR->index - Cudd_Not(bDist)->index; - else - VarNew = bFR->index + bDist->index; - assert( VarNew < dd->size ); - - // cofactor the functions - if ( bFR != bF ) // bFunc is complemented - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - - bRes0 = extraBddMove( dd, bF0, bDist ); - if ( bRes0 == NULL ) - return NULL; - cuddRef( bRes0 ); - - bRes1 = extraBddMove( dd, bF1, bDist ); - if ( bRes1 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - return NULL; - } - cuddRef( bRes1 ); - - /* only bRes0 and bRes1 are referenced at this point */ - bRes = cuddBddIteRecur( dd, dd->vars[VarNew], bRes1, bRes0 ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bRes1 ); - return NULL; - } - cuddRef( bRes ); - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bRes1 ); - - /* insert the result into cache */ - cuddCacheInsert2( dd, extraBddMove, bF, bDist, bRes ); - cuddDeref( bRes ); - return bRes; - } -} /* end of extraBddMove */ - - -/**Function******************************************************************** - - Synopsis [Finds three cofactors of the cover w.r.t. to the topmost variable.] - - Description [Finds three cofactors of the cover w.r.t. to the topmost variable. - Does not check the cover for being a constant. Assumes that ZDD variables encoding - positive and negative polarities are adjacent in the variable order. Is different - from cuddZddGetCofactors3() in that it does not compute the cofactors w.r.t. the - given variable but takes the cofactors with respent to the topmost variable. - This function is more efficient when used in recursive procedures because it does - not require referencing of the resulting cofactors (compare cuddZddProduct() - and extraZddPrimeProduct()).] - - SideEffects [None] - - SeeAlso [cuddZddGetCofactors3] - -******************************************************************************/ -void -extraDecomposeCover( - DdManager* dd, /* the manager */ - DdNode* zC, /* the cover */ - DdNode** zC0, /* the pointer to the negative var cofactor */ - DdNode** zC1, /* the pointer to the positive var cofactor */ - DdNode** zC2 ) /* the pointer to the cofactor without var */ -{ - if ( (zC->index & 1) == 0 ) - { /* the top variable is present in positive polarity and maybe in negative */ - - DdNode *Temp = cuddE( zC ); - *zC1 = cuddT( zC ); - if ( cuddIZ(dd,Temp->index) == cuddIZ(dd,zC->index) + 1 ) - { /* Temp is not a terminal node - * top var is present in negative polarity */ - *zC2 = cuddE( Temp ); - *zC0 = cuddT( Temp ); - } - else - { /* top var is not present in negative polarity */ - *zC2 = Temp; - *zC0 = dd->zero; - } - } - else - { /* the top variable is present only in negative */ - *zC1 = dd->zero; - *zC2 = cuddE( zC ); - *zC0 = cuddT( zC ); - } -} /* extraDecomposeCover */ - - - -/**Function******************************************************************** - - Synopsis [Counts the total number of cubes in the ISOPs of the functions.] - - Description [Returns -1 if the number of cubes exceeds the limit.] - - SideEffects [None] - - SeeAlso [Extra_TransferPermute] - -******************************************************************************/ -static DdNode * extraBddCountCubes( DdManager * dd, DdNode * L, DdNode * U, st__table *table, int * pnCubes, int Limit ) -{ - DdNode *one = DD_ONE(dd); - DdNode *zero = Cudd_Not(one); - int v, top_l, top_u; - DdNode *Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud; - DdNode *Lsuper0, *Usuper0, *Lsuper1, *Usuper1; - DdNode *Isub0, *Isub1, *Id; - DdNode *x; - DdNode *term0, *term1, *sum; - DdNode *Lv, *Uv, *Lnv, *Unv; - DdNode *r; - int index; - int Count0 = 0, Count1 = 0, Count2 = 0; - - statLine(dd); - if (L == zero) - { - *pnCubes = 0; - return(zero); - } - if (U == one) - { - *pnCubes = 1; - return(one); - } - - /* Check cache */ - r = cuddCacheLookup2(dd, cuddBddIsop, L, U); - if (r) - { - int nCubes = 0; - if ( st__lookup( table, (char *)r, (char **)&nCubes ) ) - *pnCubes = nCubes; - else assert( 0 ); - return r; - } - - top_l = dd->perm[Cudd_Regular(L)->index]; - top_u = dd->perm[Cudd_Regular(U)->index]; - v = ddMin(top_l, top_u); - - /* Compute cofactors */ - if (top_l == v) { - index = Cudd_Regular(L)->index; - Lv = Cudd_T(L); - Lnv = Cudd_E(L); - if (Cudd_IsComplement(L)) { - Lv = Cudd_Not(Lv); - Lnv = Cudd_Not(Lnv); - } - } - else { - index = Cudd_Regular(U)->index; - Lv = Lnv = L; - } - - if (top_u == v) { - Uv = Cudd_T(U); - Unv = Cudd_E(U); - if (Cudd_IsComplement(U)) { - Uv = Cudd_Not(Uv); - Unv = Cudd_Not(Unv); - } - } - else { - Uv = Unv = U; - } - - Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv)); - if (Lsub0 == NULL) - return(NULL); - Cudd_Ref(Lsub0); - Usub0 = Unv; - Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv)); - if (Lsub1 == NULL) { - Cudd_RecursiveDeref(dd, Lsub0); - return(NULL); - } - Cudd_Ref(Lsub1); - Usub1 = Uv; - - Isub0 = extraBddCountCubes(dd, Lsub0, Usub0, table, &Count0, Limit); - if (Isub0 == NULL) { - Cudd_RecursiveDeref(dd, Lsub0); - Cudd_RecursiveDeref(dd, Lsub1); - return(NULL); - } - Cudd_Ref(Isub0); - Isub1 = extraBddCountCubes(dd, Lsub1, Usub1, table, &Count1, Limit); - if (Isub1 == NULL) { - Cudd_RecursiveDeref(dd, Lsub0); - Cudd_RecursiveDeref(dd, Lsub1); - Cudd_RecursiveDeref(dd, Isub0); - return(NULL); - } - Cudd_Ref(Isub1); - Cudd_RecursiveDeref(dd, Lsub0); - Cudd_RecursiveDeref(dd, Lsub1); - - Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0)); - if (Lsuper0 == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - return(NULL); - } - Cudd_Ref(Lsuper0); - Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1)); - if (Lsuper1 == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Lsuper0); - return(NULL); - } - Cudd_Ref(Lsuper1); - Usuper0 = Unv; - Usuper1 = Uv; - - /* Ld = Lsuper0 + Lsuper1 */ - Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1)); - Ld = Cudd_NotCond(Ld, Ld != NULL); - if (Ld == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Lsuper0); - Cudd_RecursiveDeref(dd, Lsuper1); - return(NULL); - } - Cudd_Ref(Ld); - Ud = cuddBddAndRecur(dd, Usuper0, Usuper1); - if (Ud == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Lsuper0); - Cudd_RecursiveDeref(dd, Lsuper1); - Cudd_RecursiveDeref(dd, Ld); - return(NULL); - } - Cudd_Ref(Ud); - Cudd_RecursiveDeref(dd, Lsuper0); - Cudd_RecursiveDeref(dd, Lsuper1); - - Id = extraBddCountCubes(dd, Ld, Ud, table, &Count2, Limit); - if (Id == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Ld); - Cudd_RecursiveDeref(dd, Ud); - return(NULL); - } - Cudd_Ref(Id); - Cudd_RecursiveDeref(dd, Ld); - Cudd_RecursiveDeref(dd, Ud); - - x = cuddUniqueInter(dd, index, one, zero); - if (x == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Id); - return(NULL); - } - Cudd_Ref(x); - term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0); - if (term0 == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Id); - Cudd_RecursiveDeref(dd, x); - return(NULL); - } - Cudd_Ref(term0); - Cudd_RecursiveDeref(dd, Isub0); - term1 = cuddBddAndRecur(dd, x, Isub1); - if (term1 == NULL) { - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Id); - Cudd_RecursiveDeref(dd, x); - Cudd_RecursiveDeref(dd, term0); - return(NULL); - } - Cudd_Ref(term1); - Cudd_RecursiveDeref(dd, x); - Cudd_RecursiveDeref(dd, Isub1); - /* sum = term0 + term1 */ - sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1)); - sum = Cudd_NotCond(sum, sum != NULL); - if (sum == NULL) { - Cudd_RecursiveDeref(dd, Id); - Cudd_RecursiveDeref(dd, term0); - Cudd_RecursiveDeref(dd, term1); - return(NULL); - } - Cudd_Ref(sum); - Cudd_RecursiveDeref(dd, term0); - Cudd_RecursiveDeref(dd, term1); - /* r = sum + Id */ - r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id)); - r = Cudd_NotCond(r, r != NULL); - if (r == NULL) { - Cudd_RecursiveDeref(dd, Id); - Cudd_RecursiveDeref(dd, sum); - return(NULL); - } - Cudd_Ref(r); - Cudd_RecursiveDeref(dd, sum); - Cudd_RecursiveDeref(dd, Id); - - cuddCacheInsert2(dd, cuddBddIsop, L, U, r); - *pnCubes = Count0 + Count1 + Count2; - if ( st__add_direct( table, (char *)r, (char *)(ABC_PTRINT_T)*pnCubes ) == st__OUT_OF_MEM ) - { - Cudd_RecursiveDeref( dd, r ); - return NULL; - } - if ( *pnCubes > Limit ) - { - Cudd_RecursiveDeref( dd, r ); - return NULL; - } - //printf( "%d ", *pnCubes ); - Cudd_Deref(r); - return r; -} -int Extra_bddCountCubes( DdManager * dd, DdNode ** pFuncs, int nFuncs, int fMode, int nLimit, int * pGuide ) -{ - DdNode * pF0, * pF1; - int i, Count, Count0, Count1, CounterAll = 0; - st__table *table = st__init_table( st__ptrcmp, st__ptrhash ); - unsigned int saveLimit = dd->maxLive; - dd->maxLive = dd->keys - dd->dead + 1000000; // limit on intermediate BDD nodes - for ( i = 0; i < nFuncs; i++ ) - { - if ( !pFuncs[i] ) - continue; - pF1 = pF0 = NULL; - Count0 = Count1 = nLimit; - if ( fMode == -1 || fMode == 1 ) // both or pos - pF1 = extraBddCountCubes( dd, pFuncs[i], pFuncs[i], table, &Count1, nLimit ); - pFuncs[i] = Cudd_Not( pFuncs[i] ); - if ( fMode == -1 || fMode == 0 ) // both or neg - pF0 = extraBddCountCubes( dd, pFuncs[i], pFuncs[i], table, &Count0, Count1 ); - pFuncs[i] = Cudd_Not( pFuncs[i] ); - if ( !pF1 && !pF0 ) - break; - if ( !pF0 ) pGuide[i] = 1, Count = Count1; // use pos - else if ( !pF1 ) pGuide[i] = 0, Count = Count0; // use neg - else if ( Count1 <= Count0 ) pGuide[i] = 1, Count = Count1; // use pos - else pGuide[i] = 0, Count = Count0; // use neg - CounterAll += Count; - //printf( "Output %5d has %5d cubes (%d) (%5d and %5d)\n", nOuts++, Count, pGuide[i], Count1, Count0 ); - } - dd->maxLive = saveLimit; - st__free_table( table ); - return i == nFuncs ? CounterAll : -1; -} /* end of Extra_bddCountCubes */ - -/*---------------------------------------------------------------------------*/ -/* Definition of static Functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Convert a BDD from a manager to another one.] - - Description [Convert a BDD from a manager to another one. Returns a - pointer to the BDD in the destination manager if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Extra_TransferPermute] - -******************************************************************************/ -DdNode * extraTransferPermute( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute ) -{ - DdNode *res; - st__table *table = NULL; - st__generator *gen = NULL; - DdNode *key, *value; - - table = st__init_table( st__ptrcmp, st__ptrhash ); - if ( table == NULL ) - goto failure; - res = extraTransferPermuteRecur( ddS, ddD, f, table, Permute ); - if ( res != NULL ) - cuddRef( res ); - - /* Dereference all elements in the table and dispose of the table. - ** This must be done also if res is NULL to avoid leaks in case of - ** reordering. */ - gen = st__init_gen( table ); - if ( gen == NULL ) - goto failure; - while ( st__gen( gen, ( const char ** ) &key, ( char ** ) &value ) ) - { - Cudd_RecursiveDeref( ddD, value ); - } - st__free_gen( gen ); - gen = NULL; - st__free_table( table ); - table = NULL; - - if ( res != NULL ) - cuddDeref( res ); - return ( res ); - - failure: - if ( table != NULL ) - st__free_table( table ); - if ( gen != NULL ) - st__free_gen( gen ); - return ( NULL ); - -} /* end of extraTransferPermute */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Extra_TransferPermute.] - - Description [Performs the recursive step of Extra_TransferPermute. - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [extraTransferPermute] - -******************************************************************************/ -static DdNode * -extraTransferPermuteRecur( - DdManager * ddS, - DdManager * ddD, - DdNode * f, - st__table * table, - int * Permute ) -{ - DdNode *ft, *fe, *t, *e, *var, *res; - DdNode *one, *zero; - int index; - int comple = 0; - - statLine( ddD ); - one = DD_ONE( ddD ); - comple = Cudd_IsComplement( f ); - - /* Trivial cases. */ - if ( Cudd_IsConstant( f ) ) - return ( Cudd_NotCond( one, comple ) ); - - - /* Make canonical to increase the utilization of the cache. */ - f = Cudd_NotCond( f, comple ); - /* Now f is a regular pointer to a non-constant node. */ - - /* Check the cache. */ - if ( st__lookup( table, ( char * ) f, ( char ** ) &res ) ) - return ( Cudd_NotCond( res, comple ) ); - - if ( ddS->TimeStop && Abc_Clock() > ddS->TimeStop ) - return NULL; - if ( ddD->TimeStop && Abc_Clock() > ddD->TimeStop ) - return NULL; - - /* Recursive step. */ - if ( Permute ) - index = Permute[f->index]; - else - index = f->index; - - ft = cuddT( f ); - fe = cuddE( f ); - - t = extraTransferPermuteRecur( ddS, ddD, ft, table, Permute ); - if ( t == NULL ) - { - return ( NULL ); - } - cuddRef( t ); - - e = extraTransferPermuteRecur( ddS, ddD, fe, table, Permute ); - if ( e == NULL ) - { - Cudd_RecursiveDeref( ddD, t ); - return ( NULL ); - } - cuddRef( e ); - - zero = Cudd_Not(ddD->one); - var = cuddUniqueInter( ddD, index, one, zero ); - if ( var == NULL ) - { - Cudd_RecursiveDeref( ddD, t ); - Cudd_RecursiveDeref( ddD, e ); - return ( NULL ); - } - res = cuddBddIteRecur( ddD, var, t, e ); - - if ( res == NULL ) - { - Cudd_RecursiveDeref( ddD, t ); - Cudd_RecursiveDeref( ddD, e ); - return ( NULL ); - } - cuddRef( res ); - Cudd_RecursiveDeref( ddD, t ); - Cudd_RecursiveDeref( ddD, e ); - - if ( st__add_direct( table, ( char * ) f, ( char * ) res ) == - st__OUT_OF_MEM ) - { - Cudd_RecursiveDeref( ddD, res ); - return ( NULL ); - } - return ( Cudd_NotCond( res, comple ) ); - -} /* end of extraTransferPermuteRecur */ - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_Support.] - - Description [Performs the recursive step of Cudd_Support. Performs a - DFS from f. The support is accumulated in supp as a side effect. Uses - the LSB of the then pointer as visited flag.] - - SideEffects [None] - - SeeAlso [ddClearFlag] - -******************************************************************************/ -static void -ddSupportStep( - DdNode * f, - int * support) -{ - if (cuddIsConstant(f) || Cudd_IsComplement(f->next)) { - return; - } - - support[f->index] = 1; - ddSupportStep(cuddT(f),support); - ddSupportStep(Cudd_Regular(cuddE(f)),support); - /* Mark as visited. */ - f->next = Cudd_Not(f->next); - return; - -} /* end of ddSupportStep */ - - -/**Function******************************************************************** - - Synopsis [Performs a DFS from f, clearing the LSB of the next - pointers.] - - Description [] - - SideEffects [None] - - SeeAlso [ddSupportStep ddDagInt] - -******************************************************************************/ -static void -ddClearFlag( - DdNode * f) -{ - if (!Cudd_IsComplement(f->next)) { - return; - } - /* Clear visited flag. */ - f->next = Cudd_Regular(f->next); - if (cuddIsConstant(f)) { - return; - } - ddClearFlag(cuddT(f)); - ddClearFlag(Cudd_Regular(cuddE(f))); - return; - -} /* end of ddClearFlag */ - - -/**Function******************************************************************** - - Synopsis [Composed three subcovers into one ZDD.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -extraComposeCover( - DdManager* dd, /* the manager */ - DdNode* zC0, /* the pointer to the negative var cofactor */ - DdNode* zC1, /* the pointer to the positive var cofactor */ - DdNode* zC2, /* the pointer to the cofactor without var */ - int TopVar) /* the index of the positive ZDD var */ -{ - DdNode * zRes, * zTemp; - /* compose with-neg-var and without-var using the neg ZDD var */ - zTemp = cuddZddGetNode( dd, 2*TopVar + 1, zC0, zC2 ); - if ( zTemp == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zC0); - Cudd_RecursiveDerefZdd(dd, zC1); - Cudd_RecursiveDerefZdd(dd, zC2); - return NULL; - } - cuddRef( zTemp ); - cuddDeref( zC0 ); - cuddDeref( zC2 ); - - /* compose with-pos-var and previous result using the pos ZDD var */ - zRes = cuddZddGetNode( dd, 2*TopVar, zC1, zTemp ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zC1); - Cudd_RecursiveDerefZdd(dd, zTemp); - return NULL; - } - cuddDeref( zC1 ); - cuddDeref( zTemp ); - return zRes; -} /* extraComposeCover */ - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of prime computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode* extraZddPrimes( DdManager *dd, DdNode* F ) -{ - DdNode *zRes; - - if ( F == Cudd_Not( dd->one ) ) - return dd->zero; - if ( F == dd->one ) - return dd->one; - - /* check cache */ - zRes = cuddCacheLookup1Zdd(dd, extraZddPrimes, F); - if (zRes) - return(zRes); - { - /* temporary variables */ - DdNode *bF01, *zP0, *zP1; - /* three components of the prime set */ - DdNode *zResE, *zResP, *zResN; - int fIsComp = Cudd_IsComplement( F ); - - /* find cofactors of F */ - DdNode * bF0 = Cudd_NotCond( Cudd_E( F ), fIsComp ); - DdNode * bF1 = Cudd_NotCond( Cudd_T( F ), fIsComp ); - - /* find the intersection of cofactors */ - bF01 = cuddBddAndRecur( dd, bF0, bF1 ); - if ( bF01 == NULL ) return NULL; - cuddRef( bF01 ); - - /* solve the problems for cofactors */ - zP0 = extraZddPrimes( dd, bF0 ); - if ( zP0 == NULL ) - { - Cudd_RecursiveDeref( dd, bF01 ); - return NULL; - } - cuddRef( zP0 ); - - zP1 = extraZddPrimes( dd, bF1 ); - if ( zP1 == NULL ) - { - Cudd_RecursiveDeref( dd, bF01 ); - Cudd_RecursiveDerefZdd( dd, zP0 ); - return NULL; - } - cuddRef( zP1 ); - - /* check for local unateness */ - if ( bF01 == bF0 ) /* unate increasing */ - { - /* intersection is useless */ - cuddDeref( bF01 ); - /* the primes of intersection are the primes of F0 */ - zResE = zP0; - /* there are no primes with negative var */ - zResN = dd->zero; - cuddRef( zResN ); - /* primes with positive var are primes of F1 that are not primes of F01 */ - zResP = cuddZddDiff( dd, zP1, zP0 ); - if ( zResP == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zResE ); - Cudd_RecursiveDerefZdd( dd, zResN ); - Cudd_RecursiveDerefZdd( dd, zP1 ); - return NULL; - } - cuddRef( zResP ); - Cudd_RecursiveDerefZdd( dd, zP1 ); - } - else if ( bF01 == bF1 ) /* unate decreasing */ - { - /* intersection is useless */ - cuddDeref( bF01 ); - /* the primes of intersection are the primes of F1 */ - zResE = zP1; - /* there are no primes with positive var */ - zResP = dd->zero; - cuddRef( zResP ); - /* primes with negative var are primes of F0 that are not primes of F01 */ - zResN = cuddZddDiff( dd, zP0, zP1 ); - if ( zResN == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zResE ); - Cudd_RecursiveDerefZdd( dd, zResP ); - Cudd_RecursiveDerefZdd( dd, zP0 ); - return NULL; - } - cuddRef( zResN ); - Cudd_RecursiveDerefZdd( dd, zP0 ); - } - else /* not unate */ - { - /* primes without the top var are primes of F10 */ - zResE = extraZddPrimes( dd, bF01 ); - if ( zResE == NULL ) - { - Cudd_RecursiveDerefZdd( dd, bF01 ); - Cudd_RecursiveDerefZdd( dd, zP0 ); - Cudd_RecursiveDerefZdd( dd, zP1 ); - return NULL; - } - cuddRef( zResE ); - Cudd_RecursiveDeref( dd, bF01 ); - - /* primes with the negative top var are those of P0 that are not in F10 */ - zResN = cuddZddDiff( dd, zP0, zResE ); - if ( zResN == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zResE ); - Cudd_RecursiveDerefZdd( dd, zP0 ); - Cudd_RecursiveDerefZdd( dd, zP1 ); - return NULL; - } - cuddRef( zResN ); - Cudd_RecursiveDerefZdd( dd, zP0 ); - - /* primes with the positive top var are those of P1 that are not in F10 */ - zResP = cuddZddDiff( dd, zP1, zResE ); - if ( zResP == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zResE ); - Cudd_RecursiveDerefZdd( dd, zResN ); - Cudd_RecursiveDerefZdd( dd, zP1 ); - return NULL; - } - cuddRef( zResP ); - Cudd_RecursiveDerefZdd( dd, zP1 ); - } - - zRes = extraComposeCover( dd, zResN, zResP, zResE, Cudd_Regular(F)->index ); - if ( zRes == NULL ) return NULL; - - /* insert the result into cache */ - cuddCacheInsert1(dd, extraZddPrimes, F, zRes); - return zRes; - } -} /* end of extraZddPrimes */ - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_bddPermute.] - - Description [ Recursively puts the BDD in the order given in the array permut. - Checks for trivial cases to terminate recursion, then splits on the - children of this node. Once the solutions for the children are - obtained, it puts into the current position the node from the rest of - the BDD that should be here. Then returns this BDD. - The key here is that the node being visited is NOT put in its proper - place by this instance, but rather is switched when its proper position - is reached in the recursion tree.

- The DdNode * that is returned is the same BDD as passed in as node, - but in the new order.] - - SideEffects [None] - - SeeAlso [Cudd_bddPermute cuddAddPermuteRecur] - -******************************************************************************/ -static DdNode * -cuddBddPermuteRecur( DdManager * manager /* DD manager */ , - DdHashTable * table /* computed table */ , - DdNode * node /* BDD to be reordered */ , - int *permut /* permutation array */ ) -{ - DdNode *N, *T, *E; - DdNode *res; - int index; - - statLine( manager ); - N = Cudd_Regular( node ); - - /* Check for terminal case of constant node. */ - if ( cuddIsConstant( N ) ) - { - return ( node ); - } - - /* If problem already solved, look up answer and return. */ - if ( N->ref != 1 && ( res = cuddHashTableLookup1( table, N ) ) != NULL ) - { - return ( Cudd_NotCond( res, N != node ) ); - } - - /* Split and recur on children of this node. */ - T = cuddBddPermuteRecur( manager, table, cuddT( N ), permut ); - if ( T == NULL ) - return ( NULL ); - cuddRef( T ); - E = cuddBddPermuteRecur( manager, table, cuddE( N ), permut ); - if ( E == NULL ) - { - Cudd_IterDerefBdd( manager, T ); - return ( NULL ); - } - cuddRef( E ); - - /* Move variable that should be in this position to this position - ** by retrieving the single var BDD for that variable, and calling - ** cuddBddIteRecur with the T and E we just created. - */ - index = permut[N->index]; - res = cuddBddIteRecur( manager, manager->vars[index], T, E ); - if ( res == NULL ) - { - Cudd_IterDerefBdd( manager, T ); - Cudd_IterDerefBdd( manager, E ); - return ( NULL ); - } - cuddRef( res ); - Cudd_IterDerefBdd( manager, T ); - Cudd_IterDerefBdd( manager, E ); - - /* Do not keep the result if the reference count is only 1, since - ** it will not be visited again. - */ - if ( N->ref != 1 ) - { - ptrint fanout = ( ptrint ) N->ref; - cuddSatDec( fanout ); - if ( !cuddHashTableInsert1( table, N, res, fanout ) ) - { - Cudd_IterDerefBdd( manager, res ); - return ( NULL ); - } - } - cuddDeref( res ); - return ( Cudd_NotCond( res, N != node ) ); - -} /* end of cuddBddPermuteRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the reordering-sensitive step of Extra_bddChangePolarity().] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * extraBddChangePolarity( - DdManager * dd, /* the DD manager */ - DdNode * bFunc, - DdNode * bVars) -{ - DdNode * bRes; - - if ( bVars == b1 ) - return bFunc; - if ( Cudd_IsConstant(bFunc) ) - return bFunc; - - if ( (bRes = cuddCacheLookup2(dd, extraBddChangePolarity, bFunc, bVars)) ) - return bRes; - else - { - DdNode * bFR = Cudd_Regular(bFunc); - int LevelF = dd->perm[bFR->index]; - int LevelV = dd->perm[bVars->index]; - - if ( LevelV < LevelF ) - bRes = extraBddChangePolarity( dd, bFunc, cuddT(bVars) ); - else // if ( LevelF <= LevelV ) - { - DdNode * bRes0, * bRes1; - DdNode * bF0, * bF1; - DdNode * bVarsNext; - - // cofactor the functions - if ( bFR != bFunc ) // bFunc is complemented - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - - if ( LevelF == LevelV ) - bVarsNext = cuddT(bVars); - else - bVarsNext = bVars; - - bRes0 = extraBddChangePolarity( dd, bF0, bVarsNext ); - if ( bRes0 == NULL ) - return NULL; - cuddRef( bRes0 ); - - bRes1 = extraBddChangePolarity( dd, bF1, bVarsNext ); - if ( bRes1 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - return NULL; - } - cuddRef( bRes1 ); - - if ( LevelF == LevelV ) - { // swap the cofactors - DdNode * bTemp; - bTemp = bRes0; - bRes0 = bRes1; - bRes1 = bTemp; - } - - /* only aRes0 and aRes1 are referenced at this point */ - - /* consider the case when Res0 and Res1 are the same node */ - if ( bRes0 == bRes1 ) - bRes = bRes1; - /* consider the case when Res1 is complemented */ - else if ( Cudd_IsComplement(bRes1) ) - { - bRes = cuddUniqueInter(dd, bFR->index, Cudd_Not(bRes1), Cudd_Not(bRes0)); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref(dd,bRes0); - Cudd_RecursiveDeref(dd,bRes1); - return NULL; - } - bRes = Cudd_Not(bRes); - } - else - { - bRes = cuddUniqueInter( dd, bFR->index, bRes1, bRes0 ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref(dd,bRes0); - Cudd_RecursiveDeref(dd,bRes1); - return NULL; - } - } - cuddDeref( bRes0 ); - cuddDeref( bRes1 ); - } - - /* insert the result into cache */ - cuddCacheInsert2(dd, extraBddChangePolarity, bFunc, bVars, bRes); - return bRes; - } -} /* end of extraBddChangePolarity */ - - - -static int Counter = 0; - -/**Function************************************************************* - - Synopsis [Computes the AND of two BDD with different orders.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * extraBddAndPermute( DdHashTable * table, DdManager * ddF, DdNode * bF, DdManager * ddG, DdNode * bG, int * pPermute ) -{ - DdNode * bF0, * bF1, * bG0, * bG1, * bRes0, * bRes1, * bRes, * bVar; - int LevF, LevG, Lev; - - // if F == 0, return 0 - if ( bF == Cudd_Not(ddF->one) ) - return Cudd_Not(ddF->one); - // if G == 0, return 0 - if ( bG == Cudd_Not(ddG->one) ) - return Cudd_Not(ddF->one); - // if G == 1, return F - if ( bG == ddG->one ) - return bF; - // cannot use F == 1, because the var order of G has to be changed - - // check cache - if ( //(Cudd_Regular(bF)->ref != 1 || Cudd_Regular(bG)->ref != 1) && - (bRes = cuddHashTableLookup2(table, bF, bG)) ) - return bRes; - Counter++; - - if ( ddF->TimeStop && Abc_Clock() > ddF->TimeStop ) - return NULL; - if ( ddG->TimeStop && Abc_Clock() > ddG->TimeStop ) - return NULL; - - // find the topmost variable in F and G using var order of F - LevF = cuddI( ddF, Cudd_Regular(bF)->index ); - LevG = cuddI( ddF, pPermute ? pPermute[Cudd_Regular(bG)->index] : Cudd_Regular(bG)->index ); - Lev = Abc_MinInt( LevF, LevG ); - assert( Lev < ddF->size ); - bVar = ddF->vars[ddF->invperm[Lev]]; - - // cofactor - bF0 = (Lev < LevF) ? bF : Cudd_NotCond( cuddE(Cudd_Regular(bF)), Cudd_IsComplement(bF) ); - bF1 = (Lev < LevF) ? bF : Cudd_NotCond( cuddT(Cudd_Regular(bF)), Cudd_IsComplement(bF) ); - bG0 = (Lev < LevG) ? bG : Cudd_NotCond( cuddE(Cudd_Regular(bG)), Cudd_IsComplement(bG) ); - bG1 = (Lev < LevG) ? bG : Cudd_NotCond( cuddT(Cudd_Regular(bG)), Cudd_IsComplement(bG) ); - - // call for cofactors - bRes0 = extraBddAndPermute( table, ddF, bF0, ddG, bG0, pPermute ); - if ( bRes0 == NULL ) - return NULL; - cuddRef( bRes0 ); - // call for cofactors - bRes1 = extraBddAndPermute( table, ddF, bF1, ddG, bG1, pPermute ); - if ( bRes1 == NULL ) - { - Cudd_IterDerefBdd( ddF, bRes0 ); - return NULL; - } - cuddRef( bRes1 ); - - // compose the result - bRes = cuddBddIteRecur( ddF, bVar, bRes1, bRes0 ); - if ( bRes == NULL ) - { - Cudd_IterDerefBdd( ddF, bRes0 ); - Cudd_IterDerefBdd( ddF, bRes1 ); - return NULL; - } - cuddRef( bRes ); - Cudd_IterDerefBdd( ddF, bRes0 ); - Cudd_IterDerefBdd( ddF, bRes1 ); - - // cache the result -// if ( Cudd_Regular(bF)->ref != 1 || Cudd_Regular(bG)->ref != 1 ) - { - ptrint fanout = (ptrint)Cudd_Regular(bF)->ref * Cudd_Regular(bG)->ref; - cuddSatDec(fanout); - cuddHashTableInsert2( table, bF, bG, bRes, fanout ); - } - cuddDeref( bRes ); - return bRes; -} - -/**Function************************************************************* - - Synopsis [Testbench.] - - Description [This procedure takes BDD manager ddF and two BDDs - in this manager (bF and bG). It creates a new manager ddG, - transfers bG into it and then reorders it, resulting in bG2. - Then it tries to compute the product of bF and bG2 in ddF.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_TestAndPerm( DdManager * ddF, DdNode * bF, DdNode * bG ) -{ - DdManager * ddG; - DdNode * bG2, * bRes1, * bRes2; - abctime clk; - // disable variable ordering in ddF - Cudd_AutodynDisable( ddF ); - - // create new BDD manager - ddG = Cudd_Init( ddF->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - // transfer BDD into it - Cudd_ShuffleHeap( ddG, ddF->invperm ); - bG2 = Extra_TransferLevelByLevel( ddF, ddG, bG ); Cudd_Ref( bG2 ); - // reorder the new manager - Cudd_ReduceHeap( ddG, CUDD_REORDER_SYMM_SIFT, 1 ); - - // compute the result -clk = Abc_Clock(); - bRes1 = Cudd_bddAnd( ddF, bF, bG ); Cudd_Ref( bRes1 ); -Abc_PrintTime( 1, "Runtime of Cudd_bddAnd ", Abc_Clock() - clk ); - - // compute the result -Counter = 0; -clk = Abc_Clock(); - bRes2 = Extra_bddAndPermute( ddF, bF, ddG, bG2, NULL ); Cudd_Ref( bRes2 ); -Abc_PrintTime( 1, "Runtime of new procedure", Abc_Clock() - clk ); -printf( "Recursive calls = %d\n", Counter ); -printf( "|F| =%6d |G| =%6d |H| =%6d |F|*|G| =%9d ", - Cudd_DagSize(bF), Cudd_DagSize(bG), Cudd_DagSize(bRes2), - Cudd_DagSize(bF) * Cudd_DagSize(bG) ); - - if ( bRes1 == bRes2 ) - printf( "Result verified.\n\n" ); - else - printf( "Result is incorrect.\n\n" ); - - Cudd_RecursiveDeref( ddF, bRes1 ); - Cudd_RecursiveDeref( ddF, bRes2 ); - // quit the new manager - Cudd_RecursiveDeref( ddG, bG2 ); - Extra_StopManager( ddG ); - - // re-enable variable ordering in ddF - Cudd_AutodynEnable( ddF, CUDD_REORDER_SYMM_SIFT ); -} - -/**Function************************************************************* - - Synopsis [Writes ZDD into a PLA file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_zddDumpPla( DdManager * dd, DdNode * F, int nVars, char * pFileName ) -{ - DdGen *gen; - char * pCube; - int * pPath, i; - FILE * pFile = fopen( pFileName, "wb" ); - if ( pFile == NULL ) - { - printf( "Cannot open file \"%s\" for writing.\n", pFileName ); - return; - } - fprintf( pFile, "# PLA file dumped by Extra_zddDumpPla() in ABC\n" ); - fprintf( pFile, ".i %d\n", nVars ); - fprintf( pFile, ".o 1\n" ); - pCube = ABC_CALLOC( char, dd->sizeZ ); - Cudd_zddForeachPath( dd, F, gen, pPath ) - { - for ( i = 0; i < nVars; i++ ) - pCube[i] = '-'; - for ( i = 0; i < nVars; i++ ) - if ( pPath[2*i] == 1 || pPath[2*i+1] == 1 ) - pCube[i] = '0' + (pPath[2*i] == 1); - fprintf( pFile, "%s 1\n", pCube ); - } - fprintf( pFile, ".e\n\n" ); - fclose( pFile ); - ABC_FREE( pCube ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/misc/extra/extraBddSymm.c b/src/misc/extra/extraBddSymm.c deleted file mode 100644 index 9dd2c8e5..00000000 --- a/src/misc/extra/extraBddSymm.c +++ /dev/null @@ -1,1474 +0,0 @@ -/**CFile**************************************************************** - - FileName [extraBddSymm.c] - - PackageName [extra] - - Synopsis [Efficient methods to compute the information about - symmetric variables using the algorithm presented in the paper: - A. Mishchenko. Fast Computation of Symmetries in Boolean Functions. - Transactions on CAD, Nov. 2003.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - September 1, 2003.] - - Revision [$Id: extraBddSymm.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "extraBdd.h" - -ABC_NAMESPACE_IMPL_START - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -#define DD_GET_SYMM_VARS_TAG 0x0a /* former DD_BDD_XOR_EXIST_ABSTRACT_TAG */ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticEnd***************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Computes the classical symmetry information for the function.] - - Description [Returns the symmetry information in the form of Extra_SymmInfo_t structure.] - - SideEffects [If the ZDD variables are not derived from BDD variables with - multiplicity 2, this function may derive them in a wrong way.] - - SeeAlso [] - -******************************************************************************/ -Extra_SymmInfo_t * Extra_SymmPairsCompute( - DdManager * dd, /* the manager */ - DdNode * bFunc) /* the function whose symmetries are computed */ -{ - DdNode * bSupp; - DdNode * zRes; - Extra_SymmInfo_t * p; - - bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); - zRes = Extra_zddSymmPairsCompute( dd, bFunc, bSupp ); Cudd_Ref( zRes ); - - p = Extra_SymmPairsCreateFromZdd( dd, zRes, bSupp ); - - Cudd_RecursiveDeref( dd, bSupp ); - Cudd_RecursiveDerefZdd( dd, zRes ); - - return p; - -} /* end of Extra_SymmPairsCompute */ - - -/**Function******************************************************************** - - Synopsis [Computes the classical symmetry information as a ZDD.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_zddSymmPairsCompute( - DdManager * dd, /* the DD manager */ - DdNode * bF, - DdNode * bVars) -{ - DdNode * res; - do { - dd->reordered = 0; - res = extraZddSymmPairsCompute( dd, bF, bVars ); - } while (dd->reordered == 1); - return(res); - -} /* end of Extra_zddSymmPairsCompute */ - -/**Function******************************************************************** - - Synopsis [Returns a singleton-set ZDD containing all variables that are symmetric with the given one.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_zddGetSymmetricVars( - DdManager * dd, /* the DD manager */ - DdNode * bF, /* the first function - originally, the positive cofactor */ - DdNode * bG, /* the second fucntion - originally, the negative cofactor */ - DdNode * bVars) /* the set of variables, on which F and G depend */ -{ - DdNode * res; - do { - dd->reordered = 0; - res = extraZddGetSymmetricVars( dd, bF, bG, bVars ); - } while (dd->reordered == 1); - return(res); - -} /* end of Extra_zddGetSymmetricVars */ - - -/**Function******************************************************************** - - Synopsis [Converts a set of variables into a set of singleton subsets.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_zddGetSingletons( - DdManager * dd, /* the DD manager */ - DdNode * bVars) /* the set of variables */ -{ - DdNode * res; - do { - dd->reordered = 0; - res = extraZddGetSingletons( dd, bVars ); - } while (dd->reordered == 1); - return(res); - -} /* end of Extra_zddGetSingletons */ - -/**Function******************************************************************** - - Synopsis [Filters the set of variables using the support of the function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddReduceVarSet( - DdManager * dd, /* the DD manager */ - DdNode * bVars, /* the set of variables to be reduced */ - DdNode * bF) /* the function whose support is used for reduction */ -{ - DdNode * res; - do { - dd->reordered = 0; - res = extraBddReduceVarSet( dd, bVars, bF ); - } while (dd->reordered == 1); - return(res); - -} /* end of Extra_bddReduceVarSet */ - - -/**Function******************************************************************** - - Synopsis [Allocates symmetry information structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -Extra_SymmInfo_t * Extra_SymmPairsAllocate( int nVars ) -{ - int i; - Extra_SymmInfo_t * p; - - // allocate and clean the storage for symmetry info - p = ABC_ALLOC( Extra_SymmInfo_t, 1 ); - memset( p, 0, sizeof(Extra_SymmInfo_t) ); - p->nVars = nVars; - p->pVars = ABC_ALLOC( int, nVars ); - p->pSymms = ABC_ALLOC( char *, nVars ); - p->pSymms[0] = ABC_ALLOC( char , nVars * nVars ); - memset( p->pSymms[0], 0, nVars * nVars * sizeof(char) ); - - for ( i = 1; i < nVars; i++ ) - p->pSymms[i] = p->pSymms[i-1] + nVars; - - return p; -} /* end of Extra_SymmPairsAllocate */ - -/**Function******************************************************************** - - Synopsis [Deallocates symmetry information structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Extra_SymmPairsDissolve( Extra_SymmInfo_t * p ) -{ - ABC_FREE( p->pVars ); - ABC_FREE( p->pSymms[0] ); - ABC_FREE( p->pSymms ); - ABC_FREE( p ); -} /* end of Extra_SymmPairsDissolve */ - -/**Function******************************************************************** - - Synopsis [Allocates symmetry information structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Extra_SymmPairsPrint( Extra_SymmInfo_t * p ) -{ - int i, k; - printf( "\n" ); - for ( i = 0; i < p->nVars; i++ ) - { - for ( k = 0; k <= i; k++ ) - printf( " " ); - for ( k = i+1; k < p->nVars; k++ ) - if ( p->pSymms[i][k] ) - printf( "1" ); - else - printf( "." ); - printf( "\n" ); - } -} /* end of Extra_SymmPairsPrint */ - - -/**Function******************************************************************** - - Synopsis [Creates the symmetry information structure from ZDD.] - - Description [ZDD representation of symmetries is the set of cubes, each - of which has two variables in the positive polarity. These variables correspond - to the symmetric variable pair.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -Extra_SymmInfo_t * Extra_SymmPairsCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bSupp ) -{ - int i; - int nSuppSize; - Extra_SymmInfo_t * p; - int * pMapVars2Nums; - DdNode * bTemp; - DdNode * zSet, * zCube, * zTemp; - int iVar1, iVar2; - - nSuppSize = Extra_bddSuppSize( dd, bSupp ); - - // allocate and clean the storage for symmetry info - p = Extra_SymmPairsAllocate( nSuppSize ); - - // allocate the storage for the temporary map - pMapVars2Nums = ABC_ALLOC( int, dd->size ); - memset( pMapVars2Nums, 0, dd->size * sizeof(int) ); - - // assign the variables - p->nVarsMax = dd->size; -// p->nNodes = Cudd_DagSize( zPairs ); - p->nNodes = 0; - for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ ) - { - p->pVars[i] = bTemp->index; - pMapVars2Nums[bTemp->index] = i; - } - - // write the symmetry info into the structure - zSet = zPairs; Cudd_Ref( zSet ); - while ( zSet != z0 ) - { - // get the next cube - zCube = Extra_zddSelectOneSubset( dd, zSet ); Cudd_Ref( zCube ); - - // add these two variables to the data structure - assert( cuddT( cuddT(zCube) ) == z1 ); - iVar1 = zCube->index/2; - iVar2 = cuddT(zCube)->index/2; - if ( pMapVars2Nums[iVar1] < pMapVars2Nums[iVar2] ) - p->pSymms[ pMapVars2Nums[iVar1] ][ pMapVars2Nums[iVar2] ] = 1; - else - p->pSymms[ pMapVars2Nums[iVar2] ][ pMapVars2Nums[iVar1] ] = 1; - // count the symmetric pairs - p->nSymms ++; - - // update the cuver and deref the cube - zSet = Cudd_zddDiff( dd, zTemp = zSet, zCube ); Cudd_Ref( zSet ); - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zCube ); - - } // for each cube - Cudd_RecursiveDerefZdd( dd, zSet ); - - ABC_FREE( pMapVars2Nums ); - return p; - -} /* end of Extra_SymmPairsCreateFromZdd */ - - -/**Function******************************************************************** - - Synopsis [Checks the possibility of two variables being symmetric.] - - Description [Returns 0 if vars are not symmetric. Return 1 if vars can be symmetric.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_bddCheckVarsSymmetric( - DdManager * dd, /* the DD manager */ - DdNode * bF, - int iVar1, - int iVar2) -{ - DdNode * bVars; - int Res; - -// return 1; - - assert( iVar1 != iVar2 ); - assert( iVar1 < dd->size ); - assert( iVar2 < dd->size ); - - bVars = Cudd_bddAnd( dd, dd->vars[iVar1], dd->vars[iVar2] ); Cudd_Ref( bVars ); - - Res = (int)( extraBddCheckVarsSymmetric( dd, bF, bVars ) == b1 ); - - Cudd_RecursiveDeref( dd, bVars ); - - return Res; -} /* end of Extra_bddCheckVarsSymmetric */ - - -/**Function******************************************************************** - - Synopsis [Computes the classical symmetry information for the function.] - - Description [Uses the naive way of comparing cofactors.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -Extra_SymmInfo_t * Extra_SymmPairsComputeNaive( DdManager * dd, DdNode * bFunc ) -{ - DdNode * bSupp, * bTemp; - int nSuppSize; - Extra_SymmInfo_t * p; - int i, k; - - // compute the support - bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); - nSuppSize = Extra_bddSuppSize( dd, bSupp ); -//printf( "Support = %d. ", nSuppSize ); -//Extra_bddPrint( dd, bSupp ); -//printf( "%d ", nSuppSize ); - - // allocate the storage for symmetry info - p = Extra_SymmPairsAllocate( nSuppSize ); - - // assign the variables - p->nVarsMax = dd->size; - for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ ) - p->pVars[i] = bTemp->index; - - // go through the candidate pairs and check using Idea1 - for ( i = 0; i < nSuppSize; i++ ) - for ( k = i+1; k < nSuppSize; k++ ) - { - p->pSymms[k][i] = p->pSymms[i][k] = Extra_bddCheckVarsSymmetricNaive( dd, bFunc, p->pVars[i], p->pVars[k] ); - if ( p->pSymms[i][k] ) - p->nSymms++; - } - - Cudd_RecursiveDeref( dd, bSupp ); - return p; - -} /* end of Extra_SymmPairsComputeNaive */ - -/**Function******************************************************************** - - Synopsis [Checks if the two variables are symmetric.] - - Description [Returns 0 if vars are not symmetric. Return 1 if vars are symmetric.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_bddCheckVarsSymmetricNaive( - DdManager * dd, /* the DD manager */ - DdNode * bF, - int iVar1, - int iVar2) -{ - DdNode * bCube1, * bCube2; - DdNode * bCof01, * bCof10; - int Res; - - assert( iVar1 != iVar2 ); - assert( iVar1 < dd->size ); - assert( iVar2 < dd->size ); - - bCube1 = Cudd_bddAnd( dd, Cudd_Not( dd->vars[iVar1] ), dd->vars[iVar2] ); Cudd_Ref( bCube1 ); - bCube2 = Cudd_bddAnd( dd, Cudd_Not( dd->vars[iVar2] ), dd->vars[iVar1] ); Cudd_Ref( bCube2 ); - - bCof01 = Cudd_Cofactor( dd, bF, bCube1 ); Cudd_Ref( bCof01 ); - bCof10 = Cudd_Cofactor( dd, bF, bCube2 ); Cudd_Ref( bCof10 ); - - Res = (int)( bCof10 == bCof01 ); - - Cudd_RecursiveDeref( dd, bCof01 ); - Cudd_RecursiveDeref( dd, bCof10 ); - Cudd_RecursiveDeref( dd, bCube1 ); - Cudd_RecursiveDeref( dd, bCube2 ); - - return Res; -} /* end of Extra_bddCheckVarsSymmetricNaive */ - - -/**Function******************************************************************** - - Synopsis [Builds ZDD representing the set of fixed-size variable tuples.] - - Description [Creates ZDD of all combinations of variables in Support that - is represented by a BDD.] - - SideEffects [New ZDD variables are created if indices of the variables - present in the combination are larger than the currently - allocated number of ZDD variables.] - - SeeAlso [] - -******************************************************************************/ -DdNode* Extra_zddTuplesFromBdd( - DdManager * dd, /* the DD manager */ - int K, /* the number of variables in tuples */ - DdNode * bVarsN) /* the set of all variables represented as a BDD */ -{ - DdNode *zRes; - int autoDynZ; - - autoDynZ = dd->autoDynZ; - dd->autoDynZ = 0; - - do { - /* transform the numeric arguments (K) into a DdNode* argument; - * this allows us to use the standard internal CUDD cache */ - DdNode *bVarSet = bVarsN, *bVarsK = bVarsN; - int nVars = 0, i; - - /* determine the number of variables in VarSet */ - while ( bVarSet != b1 ) - { - nVars++; - /* make sure that the VarSet is a cube */ - if ( cuddE( bVarSet ) != b0 ) - return NULL; - bVarSet = cuddT( bVarSet ); - } - /* make sure that the number of variables in VarSet is less or equal - that the number of variables that should be present in the tuples - */ - if ( K > nVars ) - return NULL; - - /* the second argument in the recursive call stannds for ; - * reate the first argument, which stands for - * as when we are talking about the tuple of out of */ - for ( i = 0; i < nVars-K; i++ ) - bVarsK = cuddT( bVarsK ); - - dd->reordered = 0; - zRes = extraZddTuplesFromBdd(dd, bVarsK, bVarsN ); - - } while (dd->reordered == 1); - dd->autoDynZ = autoDynZ; - return zRes; - -} /* end of Extra_zddTuplesFromBdd */ - -/**Function******************************************************************** - - Synopsis [Selects one subset from the set of subsets represented by a ZDD.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode* Extra_zddSelectOneSubset( - DdManager * dd, /* the DD manager */ - DdNode * zS) /* the ZDD */ -{ - DdNode *res; - do { - dd->reordered = 0; - res = extraZddSelectOneSubset(dd, zS); - } while (dd->reordered == 1); - return(res); - -} /* end of Extra_zddSelectOneSubset */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Performs a recursive step of Extra_SymmPairsCompute.] - - Description [Returns the set of symmetric variable pairs represented as a set - of two-literal ZDD cubes. Both variables always appear in the positive polarity - in the cubes. This function works without building new BDD nodes. Some relatively - small number of ZDD nodes may be built to ensure proper bookkeeping of the - symmetry information.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * -extraZddSymmPairsCompute( - DdManager * dd, /* the manager */ - DdNode * bFunc, /* the function whose symmetries are computed */ - DdNode * bVars ) /* the set of variables on which this function depends */ -{ - DdNode * zRes; - DdNode * bFR = Cudd_Regular(bFunc); - - if ( cuddIsConstant(bFR) ) - { - int nVars, i; - - // determine how many vars are in the bVars - nVars = Extra_bddSuppSize( dd, bVars ); - if ( nVars < 2 ) - return z0; - else - { - DdNode * bVarsK; - - // create the BDD bVarsK corresponding to K = 2; - bVarsK = bVars; - for ( i = 0; i < nVars-2; i++ ) - bVarsK = cuddT( bVarsK ); - return extraZddTuplesFromBdd( dd, bVarsK, bVars ); - } - } - assert( bVars != b1 ); - - if ( (zRes = cuddCacheLookup2Zdd(dd, extraZddSymmPairsCompute, bFunc, bVars)) ) - return zRes; - else - { - DdNode * zRes0, * zRes1; - DdNode * zTemp, * zPlus, * zSymmVars; - DdNode * bF0, * bF1; - DdNode * bVarsNew; - int nVarsExtra; - int LevelF; - - // every variable in bF should be also in bVars, therefore LevelF cannot be above LevelV - // if LevelF is below LevelV, scroll through the vars in bVars to the same level as F - // count how many extra vars are there in bVars - nVarsExtra = 0; - LevelF = dd->perm[bFR->index]; - for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) ) - nVarsExtra++; - // the indexes (level) of variables should be synchronized now - assert( bFR->index == bVarsNew->index ); - - // cofactor the function - if ( bFR != bFunc ) // bFunc is complemented - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - - // solve subproblems - zRes0 = extraZddSymmPairsCompute( dd, bF0, cuddT(bVarsNew) ); - if ( zRes0 == NULL ) - return NULL; - cuddRef( zRes0 ); - - // if there is no symmetries in the negative cofactor - // there is no need to test the positive cofactor - if ( zRes0 == z0 ) - zRes = zRes0; // zRes takes reference - else - { - zRes1 = extraZddSymmPairsCompute( dd, bF1, cuddT(bVarsNew) ); - if ( zRes1 == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes0 ); - return NULL; - } - cuddRef( zRes1 ); - - // only those variables are pair-wise symmetric - // that are pair-wise symmetric in both cofactors - // therefore, intersect the solutions - zRes = cuddZddIntersect( dd, zRes0, zRes1 ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes0 ); - Cudd_RecursiveDerefZdd( dd, zRes1 ); - return NULL; - } - cuddRef( zRes ); - Cudd_RecursiveDerefZdd( dd, zRes0 ); - Cudd_RecursiveDerefZdd( dd, zRes1 ); - } - - // consider the current top-most variable and find all the vars - // that are pairwise symmetric with it - // these variables are returned as a set of ZDD singletons - zSymmVars = extraZddGetSymmetricVars( dd, bF1, bF0, cuddT(bVarsNew) ); - if ( zSymmVars == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes ); - return NULL; - } - cuddRef( zSymmVars ); - - // attach the topmost variable to the set, to get the variable pairs - // use the positive polarity ZDD variable for the purpose - - // there is no need to do so, if zSymmVars is empty - if ( zSymmVars == z0 ) - Cudd_RecursiveDerefZdd( dd, zSymmVars ); - else - { - zPlus = cuddZddGetNode( dd, 2*bFR->index, zSymmVars, z0 ); - if ( zPlus == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes ); - Cudd_RecursiveDerefZdd( dd, zSymmVars ); - return NULL; - } - cuddRef( zPlus ); - cuddDeref( zSymmVars ); - - // add these variable pairs to the result - zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - return NULL; - } - cuddRef( zRes ); - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - } - - // only zRes is referenced at this point - - // if we skipped some variables, these variables cannot be symmetric with - // any variables that are currently in the support of bF, but they can be - // symmetric with the variables that are in bVars but not in the support of bF - if ( nVarsExtra ) - { - // it is possible to improve this step: - // (1) there is no need to enter here, if nVarsExtra < 2 - - // create the set of topmost nVarsExtra in bVars - DdNode * bVarsExtra; - int nVars; - - // remove from bVars all the variable that are in the support of bFunc - bVarsExtra = extraBddReduceVarSet( dd, bVars, bFunc ); - if ( bVarsExtra == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes ); - return NULL; - } - cuddRef( bVarsExtra ); - - // determine how many vars are in the bVarsExtra - nVars = Extra_bddSuppSize( dd, bVarsExtra ); - if ( nVars < 2 ) - { - Cudd_RecursiveDeref( dd, bVarsExtra ); - } - else - { - int i; - DdNode * bVarsK; - - // create the BDD bVarsK corresponding to K = 2; - bVarsK = bVarsExtra; - for ( i = 0; i < nVars-2; i++ ) - bVarsK = cuddT( bVarsK ); - - // create the 2 variable tuples - zPlus = extraZddTuplesFromBdd( dd, bVarsK, bVarsExtra ); - if ( zPlus == NULL ) - { - Cudd_RecursiveDeref( dd, bVarsExtra ); - Cudd_RecursiveDerefZdd( dd, zRes ); - return NULL; - } - cuddRef( zPlus ); - Cudd_RecursiveDeref( dd, bVarsExtra ); - - // add these to the result - zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - return NULL; - } - cuddRef( zRes ); - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - } - } - cuddDeref( zRes ); - - - /* insert the result into cache */ - cuddCacheInsert2(dd, extraZddSymmPairsCompute, bFunc, bVars, zRes); - return zRes; - } -} /* end of extraZddSymmPairsCompute */ - -/**Function******************************************************************** - - Synopsis [Performs a recursive step of Extra_zddGetSymmetricVars.] - - Description [Returns the set of ZDD singletons, containing those positive - ZDD variables that correspond to BDD variables x, for which it is true - that bF(x=0) == bG(x=1).] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * extraZddGetSymmetricVars( - DdManager * dd, /* the DD manager */ - DdNode * bF, /* the first function - originally, the positive cofactor */ - DdNode * bG, /* the second function - originally, the negative cofactor */ - DdNode * bVars) /* the set of variables, on which F and G depend */ -{ - DdNode * zRes; - DdNode * bFR = Cudd_Regular(bF); - DdNode * bGR = Cudd_Regular(bG); - - if ( cuddIsConstant(bFR) && cuddIsConstant(bGR) ) - { - if ( bF == bG ) - return extraZddGetSingletons( dd, bVars ); - else - return z0; - } - assert( bVars != b1 ); - - if ( (zRes = cuddCacheLookupZdd(dd, DD_GET_SYMM_VARS_TAG, bF, bG, bVars)) ) - return zRes; - else - { - DdNode * zRes0, * zRes1; - DdNode * zPlus, * zTemp; - DdNode * bF0, * bF1; - DdNode * bG0, * bG1; - DdNode * bVarsNew; - - int LevelF = cuddI(dd,bFR->index); - int LevelG = cuddI(dd,bGR->index); - int LevelFG; - - if ( LevelF < LevelG ) - LevelFG = LevelF; - else - LevelFG = LevelG; - - // at least one of the arguments is not a constant - assert( LevelFG < dd->size ); - - // every variable in bF and bG should be also in bVars, therefore LevelFG cannot be above LevelV - // if LevelFG is below LevelV, scroll through the vars in bVars to the same level as LevelFG - for ( bVarsNew = bVars; LevelFG > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) ); - assert( LevelFG == dd->perm[bVarsNew->index] ); - - // cofactor the functions - if ( LevelF == LevelFG ) - { - if ( bFR != bF ) // bF is complemented - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - } - else - bF0 = bF1 = bF; - - if ( LevelG == LevelFG ) - { - if ( bGR != bG ) // bG is complemented - { - bG0 = Cudd_Not( cuddE(bGR) ); - bG1 = Cudd_Not( cuddT(bGR) ); - } - else - { - bG0 = cuddE(bGR); - bG1 = cuddT(bGR); - } - } - else - bG0 = bG1 = bG; - - // solve subproblems - zRes0 = extraZddGetSymmetricVars( dd, bF0, bG0, cuddT(bVarsNew) ); - if ( zRes0 == NULL ) - return NULL; - cuddRef( zRes0 ); - - // if there is not symmetries in the negative cofactor - // there is no need to test the positive cofactor - if ( zRes0 == z0 ) - zRes = zRes0; // zRes takes reference - else - { - zRes1 = extraZddGetSymmetricVars( dd, bF1, bG1, cuddT(bVarsNew) ); - if ( zRes1 == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes0 ); - return NULL; - } - cuddRef( zRes1 ); - - // only those variables should belong to the resulting set - // for which the property is true for both cofactors - zRes = cuddZddIntersect( dd, zRes0, zRes1 ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes0 ); - Cudd_RecursiveDerefZdd( dd, zRes1 ); - return NULL; - } - cuddRef( zRes ); - Cudd_RecursiveDerefZdd( dd, zRes0 ); - Cudd_RecursiveDerefZdd( dd, zRes1 ); - } - - // add one more singleton if the property is true for this variable - if ( bF0 == bG1 ) - { - zPlus = cuddZddGetNode( dd, 2*bVarsNew->index, z1, z0 ); - if ( zPlus == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes ); - return NULL; - } - cuddRef( zPlus ); - - // add these variable pairs to the result - zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - return NULL; - } - cuddRef( zRes ); - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - } - - if ( bF == bG && bVars != bVarsNew ) - { - // if the functions are equal, so are their cofactors - // add those variables from V that are above F and G - - DdNode * bVarsExtra; - - assert( LevelFG > dd->perm[bVars->index] ); - - // create the BDD of the extra variables - bVarsExtra = cuddBddExistAbstractRecur( dd, bVars, bVarsNew ); - if ( bVarsExtra == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes ); - return NULL; - } - cuddRef( bVarsExtra ); - - zPlus = extraZddGetSingletons( dd, bVarsExtra ); - if ( zPlus == NULL ) - { - Cudd_RecursiveDeref( dd, bVarsExtra ); - Cudd_RecursiveDerefZdd( dd, zRes ); - return NULL; - } - cuddRef( zPlus ); - Cudd_RecursiveDeref( dd, bVarsExtra ); - - // add these to the result - zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - return NULL; - } - cuddRef( zRes ); - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - } - cuddDeref( zRes ); - - cuddCacheInsert( dd, DD_GET_SYMM_VARS_TAG, bF, bG, bVars, zRes ); - return zRes; - } -} /* end of extraZddGetSymmetricVars */ - - -/**Function******************************************************************** - - Synopsis [Performs a recursive step of Extra_zddGetSingletons.] - - Description [Returns the set of ZDD singletons, containing those positive - polarity ZDD variables that correspond to the BDD variables in bVars.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * extraZddGetSingletons( - DdManager * dd, /* the DD manager */ - DdNode * bVars) /* the set of variables */ -{ - DdNode * zRes; - - if ( bVars == b1 ) -// if ( bVars == b0 ) // bug fixed by Jin Zhang, Jan 23, 2004 - return z1; - - if ( (zRes = cuddCacheLookup1Zdd(dd, extraZddGetSingletons, bVars)) ) - return zRes; - else - { - DdNode * zTemp, * zPlus; - - // solve subproblem - zRes = extraZddGetSingletons( dd, cuddT(bVars) ); - if ( zRes == NULL ) - return NULL; - cuddRef( zRes ); - - zPlus = cuddZddGetNode( dd, 2*bVars->index, z1, z0 ); - if ( zPlus == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes ); - return NULL; - } - cuddRef( zPlus ); - - // add these to the result - zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - return NULL; - } - cuddRef( zRes ); - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - cuddDeref( zRes ); - - cuddCacheInsert1( dd, extraZddGetSingletons, bVars, zRes ); - return zRes; - } -} /* end of extraZddGetSingletons */ - - -/**Function******************************************************************** - - Synopsis [Performs a recursive step of Extra_bddReduceVarSet.] - - Description [Returns the set of all variables in the given set that are not in the - support of the given function.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * extraBddReduceVarSet( - DdManager * dd, /* the DD manager */ - DdNode * bVars, /* the set of variables to be reduced */ - DdNode * bF) /* the function whose support is used for reduction */ -{ - DdNode * bRes; - DdNode * bFR = Cudd_Regular(bF); - - if ( cuddIsConstant(bFR) || bVars == b1 ) - return bVars; - - if ( (bRes = cuddCacheLookup2(dd, extraBddReduceVarSet, bVars, bF)) ) - return bRes; - else - { - DdNode * bF0, * bF1; - DdNode * bVarsThis, * bVarsLower, * bTemp; - int LevelF; - - // if LevelF is below LevelV, scroll through the vars in bVars - LevelF = dd->perm[bFR->index]; - for ( bVarsThis = bVars; LevelF > cuddI(dd,bVarsThis->index); bVarsThis = cuddT(bVarsThis) ); - // scroll also through the current var, because it should be not be added - if ( LevelF == cuddI(dd,bVarsThis->index) ) - bVarsLower = cuddT(bVarsThis); - else - bVarsLower = bVarsThis; - - // cofactor the function - if ( bFR != bF ) // bFunc is complemented - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - - // solve subproblems - bRes = extraBddReduceVarSet( dd, bVarsLower, bF0 ); - if ( bRes == NULL ) - return NULL; - cuddRef( bRes ); - - bRes = extraBddReduceVarSet( dd, bTemp = bRes, bF1 ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref( dd, bTemp ); - return NULL; - } - cuddRef( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - - // the current var should not be added - // add the skipped vars - if ( bVarsThis != bVars ) - { - DdNode * bVarsExtra; - - // extract the skipped variables - bVarsExtra = cuddBddExistAbstractRecur( dd, bVars, bVarsThis ); - if ( bVarsExtra == NULL ) - { - Cudd_RecursiveDeref( dd, bRes ); - return NULL; - } - cuddRef( bVarsExtra ); - - // add these variables - bRes = cuddBddAndRecur( dd, bTemp = bRes, bVarsExtra ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bVarsExtra ); - return NULL; - } - cuddRef( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bVarsExtra ); - } - cuddDeref( bRes ); - - cuddCacheInsert2( dd, extraBddReduceVarSet, bVars, bF, bRes ); - return bRes; - } -} /* end of extraBddReduceVarSet */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Extra_bddCheckVarsSymmetric().] - - Description [Returns b0 if the variables are not symmetric. Returns b1 if the - variables can be symmetric. The variables are represented in the form of a - two-variable cube. In case the cube contains one variable (below Var1 level), - the cube's pointer is complemented if the variable Var1 occurred on the - current path; otherwise, the cube's pointer is regular. Uses additional - complemented bit (Hash_Not) to mark the result if in the BDD rooted that this - node there is a branch passing though the node labeled with Var2.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * extraBddCheckVarsSymmetric( - DdManager * dd, /* the DD manager */ - DdNode * bF, - DdNode * bVars) -{ - DdNode * bRes; - - if ( bF == b0 ) - return b1; - - assert( bVars != b1 ); - - if ( (bRes = cuddCacheLookup2(dd, extraBddCheckVarsSymmetric, bF, bVars)) ) - return bRes; - else - { - DdNode * bRes0, * bRes1; - DdNode * bF0, * bF1; - DdNode * bFR = Cudd_Regular(bF); - int LevelF = cuddI(dd,bFR->index); - - DdNode * bVarsR = Cudd_Regular(bVars); - int fVar1Pres; - int iLev1; - int iLev2; - - if ( bVarsR != bVars ) // cube's pointer is complemented - { - assert( cuddT(bVarsR) == b1 ); - fVar1Pres = 1; // the first var is present on the path - iLev1 = -1; // we are already below the first var level - iLev2 = dd->perm[bVarsR->index]; // the level of the second var - } - else // cube's pointer is NOT complemented - { - fVar1Pres = 0; // the first var is absent on the path - if ( cuddT(bVars) == b1 ) - { - iLev1 = -1; // we are already below the first var level - iLev2 = dd->perm[bVars->index]; // the level of the second var - } - else - { - assert( cuddT(cuddT(bVars)) == b1 ); - iLev1 = dd->perm[bVars->index]; // the level of the first var - iLev2 = dd->perm[cuddT(bVars)->index]; // the level of the second var - } - } - - // cofactor the function - // the cofactors are needed only if we are above the second level - if ( LevelF < iLev2 ) - { - if ( bFR != bF ) // bFunc is complemented - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - } - else - bF0 = bF1 = NULL; - - // consider five cases: - // (1) F is above iLev1 - // (2) F is on the level iLev1 - // (3) F is between iLev1 and iLev2 - // (4) F is on the level iLev2 - // (5) F is below iLev2 - - // (1) F is above iLev1 - if ( LevelF < iLev1 ) - { - // the returned result cannot have the hash attribute - // because we still did not reach the level of Var1; - // the attribute never travels above the level of Var1 - bRes0 = extraBddCheckVarsSymmetric( dd, bF0, bVars ); -// assert( !Hash_IsComplement( bRes0 ) ); - assert( bRes0 != z0 ); - if ( bRes0 == b0 ) - bRes = b0; - else - bRes = extraBddCheckVarsSymmetric( dd, bF1, bVars ); -// assert( !Hash_IsComplement( bRes ) ); - assert( bRes != z0 ); - } - // (2) F is on the level iLev1 - else if ( LevelF == iLev1 ) - { - bRes0 = extraBddCheckVarsSymmetric( dd, bF0, Cudd_Not( cuddT(bVars) ) ); - if ( bRes0 == b0 ) - bRes = b0; - else - { - bRes1 = extraBddCheckVarsSymmetric( dd, bF1, Cudd_Not( cuddT(bVars) ) ); - if ( bRes1 == b0 ) - bRes = b0; - else - { -// if ( Hash_IsComplement( bRes0 ) || Hash_IsComplement( bRes1 ) ) - if ( bRes0 == z0 || bRes1 == z0 ) - bRes = b1; - else - bRes = b0; - } - } - } - // (3) F is between iLev1 and iLev2 - else if ( LevelF < iLev2 ) - { - bRes0 = extraBddCheckVarsSymmetric( dd, bF0, bVars ); - if ( bRes0 == b0 ) - bRes = b0; - else - { - bRes1 = extraBddCheckVarsSymmetric( dd, bF1, bVars ); - if ( bRes1 == b0 ) - bRes = b0; - else - { -// if ( Hash_IsComplement( bRes0 ) || Hash_IsComplement( bRes1 ) ) -// bRes = Hash_Not( b1 ); - if ( bRes0 == z0 || bRes1 == z0 ) - bRes = z0; - else - bRes = b1; - } - } - } - // (4) F is on the level iLev2 - else if ( LevelF == iLev2 ) - { - // this is the only place where the hash attribute (Hash_Not) can be added - // to the result; it can be added only if the path came through the node - // lebeled with Var1; therefore, the hash attribute cannot be returned - // to the caller function - if ( fVar1Pres ) -// bRes = Hash_Not( b1 ); - bRes = z0; - else - bRes = b0; - } - // (5) F is below iLev2 - else // if ( LevelF > iLev2 ) - { - // it is possible that the path goes through the node labeled by Var1 - // and still everything is okay; we do not label with Hash_Not here - // because the path does not go through node labeled by Var2 - bRes = b1; - } - - cuddCacheInsert2(dd, extraBddCheckVarsSymmetric, bF, bVars, bRes); - return bRes; - } -} /* end of extraBddCheckVarsSymmetric */ - -/**Function******************************************************************** - - Synopsis [Performs the reordering-sensitive step of Extra_zddTupleFromBdd().] - - Description [Generates in a bottom-up fashion ZDD for all combinations - composed of k variables out of variables belonging to Support.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode* extraZddTuplesFromBdd( - DdManager * dd, /* the DD manager */ - DdNode * bVarsK, /* the number of variables in tuples */ - DdNode * bVarsN) /* the set of all variables */ -{ - DdNode *zRes, *zRes0, *zRes1; - statLine(dd); - - /* terminal cases */ -/* if ( k < 0 || k > n ) - * return dd->zero; - * if ( n == 0 ) - * return dd->one; - */ - if ( cuddI( dd, bVarsK->index ) < cuddI( dd, bVarsN->index ) ) - return z0; - if ( bVarsN == b1 ) - return z1; - - /* check cache */ - zRes = cuddCacheLookup2Zdd(dd, extraZddTuplesFromBdd, bVarsK, bVarsN); - if (zRes) - return(zRes); - - /* ZDD in which this variable is 0 */ -/* zRes0 = extraZddTuplesFromBdd( dd, k, n-1 ); */ - zRes0 = extraZddTuplesFromBdd( dd, bVarsK, cuddT(bVarsN) ); - if ( zRes0 == NULL ) - return NULL; - cuddRef( zRes0 ); - - /* ZDD in which this variable is 1 */ -/* zRes1 = extraZddTuplesFromBdd( dd, k-1, n-1 ); */ - if ( bVarsK == b1 ) - { - zRes1 = z0; - cuddRef( zRes1 ); - } - else - { - zRes1 = extraZddTuplesFromBdd( dd, cuddT(bVarsK), cuddT(bVarsN) ); - if ( zRes1 == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes0 ); - return NULL; - } - cuddRef( zRes1 ); - } - - /* compose Res0 and Res1 with the given ZDD variable */ - zRes = cuddZddGetNode( dd, 2*bVarsN->index, zRes1, zRes0 ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes0 ); - Cudd_RecursiveDerefZdd( dd, zRes1 ); - return NULL; - } - cuddDeref( zRes0 ); - cuddDeref( zRes1 ); - - /* insert the result into cache */ - cuddCacheInsert2(dd, extraZddTuplesFromBdd, bVarsK, bVarsN, zRes); - return zRes; - -} /* end of extraZddTuplesFromBdd */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Extra_zddSelectOneSubset.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * extraZddSelectOneSubset( - DdManager * dd, - DdNode * zS ) -// selects one subset from the ZDD zS -// returns z0 if and only if zS is an empty set of cubes -{ - DdNode * zRes; - - if ( zS == z0 ) return z0; - if ( zS == z1 ) return z1; - - // check cache - if ( (zRes = cuddCacheLookup1Zdd( dd, extraZddSelectOneSubset, zS )) ) - return zRes; - else - { - DdNode * zS0, * zS1, * zTemp; - - zS0 = cuddE(zS); - zS1 = cuddT(zS); - - if ( zS0 != z0 ) - { - zRes = extraZddSelectOneSubset( dd, zS0 ); - if ( zRes == NULL ) - return NULL; - } - else // if ( zS0 == z0 ) - { - assert( zS1 != z0 ); - zRes = extraZddSelectOneSubset( dd, zS1 ); - if ( zRes == NULL ) - return NULL; - cuddRef( zRes ); - - zRes = cuddZddGetNode( dd, zS->index, zTemp = zRes, z0 ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zTemp ); - return NULL; - } - cuddDeref( zTemp ); - } - - // insert the result into cache - cuddCacheInsert1( dd, extraZddSelectOneSubset, zS, zRes ); - return zRes; - } -} /* end of extraZddSelectOneSubset */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static Functions */ -/*---------------------------------------------------------------------------*/ -ABC_NAMESPACE_IMPL_END - diff --git a/src/misc/extra/extraBddTime.c b/src/misc/extra/extraBddTime.c deleted file mode 100644 index dc9ff147..00000000 --- a/src/misc/extra/extraBddTime.c +++ /dev/null @@ -1,660 +0,0 @@ -/**CFile**************************************************************** - - FileName [extraBddTime.c] - - PackageName [extra] - - Synopsis [Procedures to control runtime in BDD operators.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - September 1, 2003.] - - Revision [$Id: extraBddTime.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $] - -***********************************************************************/ - -#include "extraBdd.h" - -ABC_NAMESPACE_IMPL_START - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define CHECK_FACTOR 10 - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdNode * cuddBddAndRecurTime( DdManager * manager, DdNode * f, DdNode * g, int * pRecCalls, int TimeOut ); -static DdNode * cuddBddAndAbstractRecurTime( DdManager * manager, DdNode * f, DdNode * g, DdNode * cube, int * pRecCalls, int TimeOut ); -static DdNode * extraTransferPermuteTime( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute, int TimeOut ); -static DdNode * extraTransferPermuteRecurTime( DdManager * ddS, DdManager * ddD, DdNode * f, st__table * table, int * Permute, int TimeOut ); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Computes the conjunction of two BDDs f and g.] - - Description [Computes the conjunction of two BDDs f and g. Returns a - pointer to the resulting BDD if successful; NULL if the intermediate - result blows up.] - - SideEffects [None] - - SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAndAbstract Cudd_bddIntersect - Cudd_bddOr Cudd_bddNand Cudd_bddNor Cudd_bddXor Cudd_bddXnor] - -******************************************************************************/ -DdNode * -Extra_bddAndTime( - DdManager * dd, - DdNode * f, - DdNode * g, - int TimeOut) -{ - DdNode *res; - int Counter = 0; - - do { - dd->reordered = 0; - res = cuddBddAndRecurTime(dd,f,g, &Counter, TimeOut); - } while (dd->reordered == 1); - return(res); - -} /* end of Extra_bddAndTime */ - -/**Function******************************************************************** - - Synopsis [Takes the AND of two BDDs and simultaneously abstracts the - variables in cube.] - - Description [Takes the AND of two BDDs and simultaneously abstracts - the variables in cube. The variables are existentially abstracted. - Returns a pointer to the result is successful; NULL otherwise. - Cudd_bddAndAbstract implements the semiring matrix multiplication - algorithm for the boolean semiring.] - - SideEffects [None] - - SeeAlso [Cudd_addMatrixMultiply Cudd_addTriangle Cudd_bddAnd] - -******************************************************************************/ -DdNode * -Extra_bddAndAbstractTime( - DdManager * manager, - DdNode * f, - DdNode * g, - DdNode * cube, - int TimeOut) -{ - DdNode *res; - int Counter = 0; - - do { - manager->reordered = 0; - res = cuddBddAndAbstractRecurTime(manager, f, g, cube, &Counter, TimeOut); - } while (manager->reordered == 1); - return(res); - -} /* end of Extra_bddAndAbstractTime */ - -/**Function******************************************************************** - - Synopsis [Convert a {A,B}DD from a manager to another with variable remapping.] - - Description [Convert a {A,B}DD from a manager to another one. The orders of the - variables in the two managers may be different. Returns a - pointer to the {A,B}DD in the destination manager if successful; NULL - otherwise. The i-th entry in the array Permute tells what is the index - of the i-th variable from the old manager in the new manager.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_TransferPermuteTime( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute, int TimeOut ) -{ - DdNode * bRes; - do - { - ddDestination->reordered = 0; - bRes = extraTransferPermuteTime( ddSource, ddDestination, f, Permute, TimeOut ); - } - while ( ddDestination->reordered == 1 ); - return ( bRes ); - -} /* end of Extra_TransferPermuteTime */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_bddAnd.] - - Description [Implements the recursive step of Cudd_bddAnd by taking - the conjunction of two BDDs. Returns a pointer to the result is - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddAnd] - -******************************************************************************/ -DdNode * -cuddBddAndRecurTime( - DdManager * manager, - DdNode * f, - DdNode * g, - int * pRecCalls, - int TimeOut) -{ - DdNode *F, *fv, *fnv, *G, *gv, *gnv; - DdNode *one, *r, *t, *e; - unsigned int topf, topg, index; - - statLine(manager); - one = DD_ONE(manager); - - /* Terminal cases. */ - F = Cudd_Regular(f); - G = Cudd_Regular(g); - if (F == G) { - if (f == g) return(f); - else return(Cudd_Not(one)); - } - if (F == one) { - if (f == one) return(g); - else return(f); - } - if (G == one) { - if (g == one) return(f); - else return(g); - } - - /* At this point f and g are not constant. */ - if (f > g) { /* Try to increase cache efficiency. */ - DdNode *tmp = f; - f = g; - g = tmp; - F = Cudd_Regular(f); - G = Cudd_Regular(g); - } - - /* Check cache. */ - if (F->ref != 1 || G->ref != 1) { - r = cuddCacheLookup2(manager, Cudd_bddAnd, f, g); - if (r != NULL) return(r); - } - -// if ( TimeOut && ((*pRecCalls)++ % CHECK_FACTOR) == 0 && TimeOut < Abc_Clock() ) - if ( TimeOut && Abc_Clock() > TimeOut ) - return NULL; - - /* Here we can skip the use of cuddI, because the operands are known - ** to be non-constant. - */ - topf = manager->perm[F->index]; - topg = manager->perm[G->index]; - - /* Compute cofactors. */ - if (topf <= topg) { - index = F->index; - fv = cuddT(F); - fnv = cuddE(F); - if (Cudd_IsComplement(f)) { - fv = Cudd_Not(fv); - fnv = Cudd_Not(fnv); - } - } else { - index = G->index; - fv = fnv = f; - } - - if (topg <= topf) { - gv = cuddT(G); - gnv = cuddE(G); - if (Cudd_IsComplement(g)) { - gv = Cudd_Not(gv); - gnv = Cudd_Not(gnv); - } - } else { - gv = gnv = g; - } - - t = cuddBddAndRecurTime(manager, fv, gv, pRecCalls, TimeOut); - if (t == NULL) return(NULL); - cuddRef(t); - - e = cuddBddAndRecurTime(manager, fnv, gnv, pRecCalls, TimeOut); - if (e == NULL) { - Cudd_IterDerefBdd(manager, t); - return(NULL); - } - cuddRef(e); - - if (t == e) { - r = t; - } else { - if (Cudd_IsComplement(t)) { - r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); - if (r == NULL) { - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = cuddUniqueInter(manager,(int)index,t,e); - if (r == NULL) { - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - return(NULL); - } - } - } - cuddDeref(e); - cuddDeref(t); - if (F->ref != 1 || G->ref != 1) - cuddCacheInsert2(manager, Cudd_bddAnd, f, g, r); - return(r); - -} /* end of cuddBddAndRecur */ - - -/**Function******************************************************************** - - Synopsis [Takes the AND of two BDDs and simultaneously abstracts the - variables in cube.] - - Description [Takes the AND of two BDDs and simultaneously abstracts - the variables in cube. The variables are existentially abstracted. - Returns a pointer to the result is successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddAndAbstract] - -******************************************************************************/ -DdNode * -cuddBddAndAbstractRecurTime( - DdManager * manager, - DdNode * f, - DdNode * g, - DdNode * cube, - int * pRecCalls, - int TimeOut) -{ - DdNode *F, *ft, *fe, *G, *gt, *ge; - DdNode *one, *zero, *r, *t, *e; - unsigned int topf, topg, topcube, top, index; - - statLine(manager); - one = DD_ONE(manager); - zero = Cudd_Not(one); - - /* Terminal cases. */ - if (f == zero || g == zero || f == Cudd_Not(g)) return(zero); - if (f == one && g == one) return(one); - - if (cube == one) { - return(cuddBddAndRecurTime(manager, f, g, pRecCalls, TimeOut)); - } - if (f == one || f == g) { - return(cuddBddExistAbstractRecur(manager, g, cube)); - } - if (g == one) { - return(cuddBddExistAbstractRecur(manager, f, cube)); - } - /* At this point f, g, and cube are not constant. */ - - if (f > g) { /* Try to increase cache efficiency. */ - DdNode *tmp = f; - f = g; - g = tmp; - } - - /* Here we can skip the use of cuddI, because the operands are known - ** to be non-constant. - */ - F = Cudd_Regular(f); - G = Cudd_Regular(g); - topf = manager->perm[F->index]; - topg = manager->perm[G->index]; - top = ddMin(topf, topg); - topcube = manager->perm[cube->index]; - - while (topcube < top) { - cube = cuddT(cube); - if (cube == one) { - return(cuddBddAndRecurTime(manager, f, g, pRecCalls, TimeOut)); - } - topcube = manager->perm[cube->index]; - } - /* Now, topcube >= top. */ - - /* Check cache. */ - if (F->ref != 1 || G->ref != 1) { - r = cuddCacheLookup(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube); - if (r != NULL) { - return(r); - } - } - -// if ( TimeOut && ((*pRecCalls)++ % CHECK_FACTOR) == 0 && TimeOut < Abc_Clock() ) - if ( TimeOut && Abc_Clock() > TimeOut ) - return NULL; - - if (topf == top) { - index = F->index; - ft = cuddT(F); - fe = cuddE(F); - if (Cudd_IsComplement(f)) { - ft = Cudd_Not(ft); - fe = Cudd_Not(fe); - } - } else { - index = G->index; - ft = fe = f; - } - - if (topg == top) { - gt = cuddT(G); - ge = cuddE(G); - if (Cudd_IsComplement(g)) { - gt = Cudd_Not(gt); - ge = Cudd_Not(ge); - } - } else { - gt = ge = g; - } - - if (topcube == top) { /* quantify */ - DdNode *Cube = cuddT(cube); - t = cuddBddAndAbstractRecurTime(manager, ft, gt, Cube, pRecCalls, TimeOut); - if (t == NULL) return(NULL); - /* Special case: 1 OR anything = 1. Hence, no need to compute - ** the else branch if t is 1. Likewise t + t * anything == t. - ** Notice that t == fe implies that fe does not depend on the - ** variables in Cube. Likewise for t == ge. - */ - if (t == one || t == fe || t == ge) { - if (F->ref != 1 || G->ref != 1) - cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG, - f, g, cube, t); - return(t); - } - cuddRef(t); - /* Special case: t + !t * anything == t + anything. */ - if (t == Cudd_Not(fe)) { - e = cuddBddExistAbstractRecur(manager, ge, Cube); - } else if (t == Cudd_Not(ge)) { - e = cuddBddExistAbstractRecur(manager, fe, Cube); - } else { - e = cuddBddAndAbstractRecurTime(manager, fe, ge, Cube, pRecCalls, TimeOut); - } - if (e == NULL) { - Cudd_IterDerefBdd(manager, t); - return(NULL); - } - if (t == e) { - r = t; - cuddDeref(t); - } else { - cuddRef(e); - r = cuddBddAndRecurTime(manager, Cudd_Not(t), Cudd_Not(e), pRecCalls, TimeOut); - if (r == NULL) { - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - return(NULL); - } - r = Cudd_Not(r); - cuddRef(r); - Cudd_DelayedDerefBdd(manager, t); - Cudd_DelayedDerefBdd(manager, e); - cuddDeref(r); - } - } else { - t = cuddBddAndAbstractRecurTime(manager, ft, gt, cube, pRecCalls, TimeOut); - if (t == NULL) return(NULL); - cuddRef(t); - e = cuddBddAndAbstractRecurTime(manager, fe, ge, cube, pRecCalls, TimeOut); - if (e == NULL) { - Cudd_IterDerefBdd(manager, t); - return(NULL); - } - if (t == e) { - r = t; - cuddDeref(t); - } else { - cuddRef(e); - if (Cudd_IsComplement(t)) { - r = cuddUniqueInter(manager, (int) index, - Cudd_Not(t), Cudd_Not(e)); - if (r == NULL) { - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = cuddUniqueInter(manager,(int)index,t,e); - if (r == NULL) { - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - return(NULL); - } - } - cuddDeref(e); - cuddDeref(t); - } - } - - if (F->ref != 1 || G->ref != 1) - cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube, r); - return (r); - -} /* end of cuddBddAndAbstractRecur */ - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Convert a BDD from a manager to another one.] - - Description [Convert a BDD from a manager to another one. Returns a - pointer to the BDD in the destination manager if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Extra_TransferPermute] - -******************************************************************************/ -DdNode * extraTransferPermuteTime( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute, int TimeOut ) -{ - DdNode *res; - st__table *table = NULL; - st__generator *gen = NULL; - DdNode *key, *value; - - table = st__init_table( st__ptrcmp, st__ptrhash ); - if ( table == NULL ) - goto failure; - res = extraTransferPermuteRecurTime( ddS, ddD, f, table, Permute, TimeOut ); - if ( res != NULL ) - cuddRef( res ); - - /* Dereference all elements in the table and dispose of the table. - ** This must be done also if res is NULL to avoid leaks in case of - ** reordering. */ - gen = st__init_gen( table ); - if ( gen == NULL ) - goto failure; - while ( st__gen( gen, ( const char ** ) &key, ( char ** ) &value ) ) - { - Cudd_RecursiveDeref( ddD, value ); - } - st__free_gen( gen ); - gen = NULL; - st__free_table( table ); - table = NULL; - - if ( res != NULL ) - cuddDeref( res ); - return ( res ); - - failure: - if ( table != NULL ) - st__free_table( table ); - if ( gen != NULL ) - st__free_gen( gen ); - return ( NULL ); - -} /* end of extraTransferPermuteTime */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Extra_TransferPermute.] - - Description [Performs the recursive step of Extra_TransferPermute. - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [extraTransferPermuteTime] - -******************************************************************************/ -static DdNode * -extraTransferPermuteRecurTime( - DdManager * ddS, - DdManager * ddD, - DdNode * f, - st__table * table, - int * Permute, - int TimeOut ) -{ - DdNode *ft, *fe, *t, *e, *var, *res; - DdNode *one, *zero; - int index; - int comple = 0; - - statLine( ddD ); - one = DD_ONE( ddD ); - comple = Cudd_IsComplement( f ); - - /* Trivial cases. */ - if ( Cudd_IsConstant( f ) ) - return ( Cudd_NotCond( one, comple ) ); - - - /* Make canonical to increase the utilization of the cache. */ - f = Cudd_NotCond( f, comple ); - /* Now f is a regular pointer to a non-constant node. */ - - /* Check the cache. */ - if ( st__lookup( table, ( char * ) f, ( char ** ) &res ) ) - return ( Cudd_NotCond( res, comple ) ); - - if ( TimeOut && Abc_Clock() > TimeOut ) - return NULL; - - /* Recursive step. */ - if ( Permute ) - index = Permute[f->index]; - else - index = f->index; - - ft = cuddT( f ); - fe = cuddE( f ); - - t = extraTransferPermuteRecurTime( ddS, ddD, ft, table, Permute, TimeOut ); - if ( t == NULL ) - { - return ( NULL ); - } - cuddRef( t ); - - e = extraTransferPermuteRecurTime( ddS, ddD, fe, table, Permute, TimeOut ); - if ( e == NULL ) - { - Cudd_RecursiveDeref( ddD, t ); - return ( NULL ); - } - cuddRef( e ); - - zero = Cudd_Not(ddD->one); - var = cuddUniqueInter( ddD, index, one, zero ); - if ( var == NULL ) - { - Cudd_RecursiveDeref( ddD, t ); - Cudd_RecursiveDeref( ddD, e ); - return ( NULL ); - } - res = cuddBddIteRecur( ddD, var, t, e ); - - if ( res == NULL ) - { - Cudd_RecursiveDeref( ddD, t ); - Cudd_RecursiveDeref( ddD, e ); - return ( NULL ); - } - cuddRef( res ); - Cudd_RecursiveDeref( ddD, t ); - Cudd_RecursiveDeref( ddD, e ); - - if ( st__add_direct( table, ( char * ) f, ( char * ) res ) == - st__OUT_OF_MEM ) - { - Cudd_RecursiveDeref( ddD, res ); - return ( NULL ); - } - return ( Cudd_NotCond( res, comple ) ); - -} /* end of extraTransferPermuteRecurTime */ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// -ABC_NAMESPACE_IMPL_END - diff --git a/src/misc/extra/extraBddUnate.c b/src/misc/extra/extraBddUnate.c deleted file mode 100644 index 9ebdd4e5..00000000 --- a/src/misc/extra/extraBddUnate.c +++ /dev/null @@ -1,646 +0,0 @@ -/**CFile**************************************************************** - - FileName [extraBddUnate.c] - - PackageName [extra] - - Synopsis [Efficient methods to compute the information about - unate variables using an algorithm that is conceptually similar to - the algorithm for two-variable symmetry computation presented in: - A. Mishchenko. Fast Computation of Symmetries in Boolean Functions. - Transactions on CAD, Nov. 2003.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - September 1, 2003.] - - Revision [$Id: extraBddUnate.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "extraBdd.h" - -ABC_NAMESPACE_IMPL_START - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticEnd***************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Computes the classical symmetry information for the function.] - - Description [Returns the symmetry information in the form of Extra_UnateInfo_t structure.] - - SideEffects [If the ZDD variables are not derived from BDD variables with - multiplicity 2, this function may derive them in a wrong way.] - - SeeAlso [] - -******************************************************************************/ -Extra_UnateInfo_t * Extra_UnateComputeFast( - DdManager * dd, /* the manager */ - DdNode * bFunc) /* the function whose symmetries are computed */ -{ - DdNode * bSupp; - DdNode * zRes; - Extra_UnateInfo_t * p; - - bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); - zRes = Extra_zddUnateInfoCompute( dd, bFunc, bSupp ); Cudd_Ref( zRes ); - - p = Extra_UnateInfoCreateFromZdd( dd, zRes, bSupp ); - - Cudd_RecursiveDeref( dd, bSupp ); - Cudd_RecursiveDerefZdd( dd, zRes ); - - return p; - -} /* end of Extra_UnateInfoCompute */ - - -/**Function******************************************************************** - - Synopsis [Computes the classical symmetry information as a ZDD.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_zddUnateInfoCompute( - DdManager * dd, /* the DD manager */ - DdNode * bF, - DdNode * bVars) -{ - DdNode * res; - do { - dd->reordered = 0; - res = extraZddUnateInfoCompute( dd, bF, bVars ); - } while (dd->reordered == 1); - return(res); - -} /* end of Extra_zddUnateInfoCompute */ - - -/**Function******************************************************************** - - Synopsis [Converts a set of variables into a set of singleton subsets.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_zddGetSingletonsBoth( - DdManager * dd, /* the DD manager */ - DdNode * bVars) /* the set of variables */ -{ - DdNode * res; - do { - dd->reordered = 0; - res = extraZddGetSingletonsBoth( dd, bVars ); - } while (dd->reordered == 1); - return(res); - -} /* end of Extra_zddGetSingletonsBoth */ - -/**Function******************************************************************** - - Synopsis [Allocates unateness information structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -Extra_UnateInfo_t * Extra_UnateInfoAllocate( int nVars ) -{ - Extra_UnateInfo_t * p; - // allocate and clean the storage for unateness info - p = ABC_ALLOC( Extra_UnateInfo_t, 1 ); - memset( p, 0, sizeof(Extra_UnateInfo_t) ); - p->nVars = nVars; - p->pVars = ABC_ALLOC( Extra_UnateVar_t, nVars ); - memset( p->pVars, 0, nVars * sizeof(Extra_UnateVar_t) ); - return p; -} /* end of Extra_UnateInfoAllocate */ - -/**Function******************************************************************** - - Synopsis [Deallocates symmetry information structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Extra_UnateInfoDissolve( Extra_UnateInfo_t * p ) -{ - ABC_FREE( p->pVars ); - ABC_FREE( p ); -} /* end of Extra_UnateInfoDissolve */ - -/**Function******************************************************************** - - Synopsis [Allocates symmetry information structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Extra_UnateInfoPrint( Extra_UnateInfo_t * p ) -{ - char * pBuffer; - int i; - pBuffer = ABC_ALLOC( char, p->nVarsMax+1 ); - memset( pBuffer, ' ', p->nVarsMax ); - pBuffer[p->nVarsMax] = 0; - for ( i = 0; i < p->nVars; i++ ) - if ( p->pVars[i].Neg ) - pBuffer[ p->pVars[i].iVar ] = 'n'; - else if ( p->pVars[i].Pos ) - pBuffer[ p->pVars[i].iVar ] = 'p'; - else - pBuffer[ p->pVars[i].iVar ] = '.'; - printf( "%s\n", pBuffer ); - ABC_FREE( pBuffer ); -} /* end of Extra_UnateInfoPrint */ - - -/**Function******************************************************************** - - Synopsis [Creates the symmetry information structure from ZDD.] - - Description [ZDD representation of symmetries is the set of cubes, each - of which has two variables in the positive polarity. These variables correspond - to the symmetric variable pair.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -Extra_UnateInfo_t * Extra_UnateInfoCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bSupp ) -{ - Extra_UnateInfo_t * p; - DdNode * bTemp, * zSet, * zCube, * zTemp; - int * pMapVars2Nums; - int i, nSuppSize; - - nSuppSize = Extra_bddSuppSize( dd, bSupp ); - - // allocate and clean the storage for symmetry info - p = Extra_UnateInfoAllocate( nSuppSize ); - - // allocate the storage for the temporary map - pMapVars2Nums = ABC_ALLOC( int, dd->size ); - memset( pMapVars2Nums, 0, dd->size * sizeof(int) ); - - // assign the variables - p->nVarsMax = dd->size; - for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ ) - { - p->pVars[i].iVar = bTemp->index; - pMapVars2Nums[bTemp->index] = i; - } - - // write the symmetry info into the structure - zSet = zPairs; Cudd_Ref( zSet ); -// Cudd_zddPrintCover( dd, zPairs ); printf( "\n" ); - while ( zSet != z0 ) - { - // get the next cube - zCube = Extra_zddSelectOneSubset( dd, zSet ); Cudd_Ref( zCube ); - - // add this var to the data structure - assert( cuddT(zCube) == z1 && cuddE(zCube) == z0 ); - if ( zCube->index & 1 ) // neg - p->pVars[ pMapVars2Nums[zCube->index/2] ].Neg = 1; - else - p->pVars[ pMapVars2Nums[zCube->index/2] ].Pos = 1; - // count the unate vars - p->nUnate++; - - // update the cuver and deref the cube - zSet = Cudd_zddDiff( dd, zTemp = zSet, zCube ); Cudd_Ref( zSet ); - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zCube ); - - } // for each cube - Cudd_RecursiveDerefZdd( dd, zSet ); - ABC_FREE( pMapVars2Nums ); - return p; - -} /* end of Extra_UnateInfoCreateFromZdd */ - - - -/**Function******************************************************************** - - Synopsis [Computes the classical unateness information for the function.] - - Description [Uses the naive way of comparing cofactors.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -Extra_UnateInfo_t * Extra_UnateComputeSlow( DdManager * dd, DdNode * bFunc ) -{ - int nSuppSize; - DdNode * bSupp, * bTemp; - Extra_UnateInfo_t * p; - int i, Res; - - // compute the support - bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); - nSuppSize = Extra_bddSuppSize( dd, bSupp ); -//printf( "Support = %d. ", nSuppSize ); -//Extra_bddPrint( dd, bSupp ); -//printf( "%d ", nSuppSize ); - - // allocate the storage for symmetry info - p = Extra_UnateInfoAllocate( nSuppSize ); - - // assign the variables - p->nVarsMax = dd->size; - for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ ) - { - Res = Extra_bddCheckUnateNaive( dd, bFunc, bTemp->index ); - p->pVars[i].iVar = bTemp->index; - if ( Res == -1 ) - p->pVars[i].Neg = 1; - else if ( Res == 1 ) - p->pVars[i].Pos = 1; - p->nUnate += (Res != 0); - } - Cudd_RecursiveDeref( dd, bSupp ); - return p; - -} /* end of Extra_UnateComputeSlow */ - -/**Function******************************************************************** - - Synopsis [Checks if the two variables are symmetric.] - - Description [Returns 0 if vars are not unate. Return -1/+1 if the var is neg/pos unate.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_bddCheckUnateNaive( - DdManager * dd, /* the DD manager */ - DdNode * bF, - int iVar) -{ - DdNode * bCof0, * bCof1; - int Res; - - assert( iVar < dd->size ); - - bCof0 = Cudd_Cofactor( dd, bF, Cudd_Not(Cudd_bddIthVar(dd,iVar)) ); Cudd_Ref( bCof0 ); - bCof1 = Cudd_Cofactor( dd, bF, Cudd_bddIthVar(dd,iVar) ); Cudd_Ref( bCof1 ); - - if ( Cudd_bddLeq( dd, bCof0, bCof1 ) ) - Res = 1; - else if ( Cudd_bddLeq( dd, bCof1, bCof0 ) ) - Res =-1; - else - Res = 0; - - Cudd_RecursiveDeref( dd, bCof0 ); - Cudd_RecursiveDeref( dd, bCof1 ); - return Res; -} /* end of Extra_bddCheckUnateNaive */ - - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Performs a recursive step of Extra_UnateInfoCompute.] - - Description [Returns the set of symmetric variable pairs represented as a set - of two-literal ZDD cubes. Both variables always appear in the positive polarity - in the cubes. This function works without building new BDD nodes. Some relatively - small number of ZDD nodes may be built to ensure proper bookkeeping of the - symmetry information.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * -extraZddUnateInfoCompute( - DdManager * dd, /* the manager */ - DdNode * bFunc, /* the function whose symmetries are computed */ - DdNode * bVars ) /* the set of variables on which this function depends */ -{ - DdNode * zRes; - DdNode * bFR = Cudd_Regular(bFunc); - - if ( cuddIsConstant(bFR) ) - { - if ( cuddIsConstant(bVars) ) - return z0; - return extraZddGetSingletonsBoth( dd, bVars ); - } - assert( bVars != b1 ); - - if ( (zRes = cuddCacheLookup2Zdd(dd, extraZddUnateInfoCompute, bFunc, bVars)) ) - return zRes; - else - { - DdNode * zRes0, * zRes1; - DdNode * zTemp, * zPlus; - DdNode * bF0, * bF1; - DdNode * bVarsNew; - int nVarsExtra; - int LevelF; - int AddVar; - - // every variable in bF should be also in bVars, therefore LevelF cannot be above LevelV - // if LevelF is below LevelV, scroll through the vars in bVars to the same level as F - // count how many extra vars are there in bVars - nVarsExtra = 0; - LevelF = dd->perm[bFR->index]; - for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) ) - nVarsExtra++; - // the indexes (level) of variables should be synchronized now - assert( bFR->index == bVarsNew->index ); - - // cofactor the function - if ( bFR != bFunc ) // bFunc is complemented - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - - // solve subproblems - zRes0 = extraZddUnateInfoCompute( dd, bF0, cuddT(bVarsNew) ); - if ( zRes0 == NULL ) - return NULL; - cuddRef( zRes0 ); - - // if there is no symmetries in the negative cofactor - // there is no need to test the positive cofactor - if ( zRes0 == z0 ) - zRes = zRes0; // zRes takes reference - else - { - zRes1 = extraZddUnateInfoCompute( dd, bF1, cuddT(bVarsNew) ); - if ( zRes1 == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes0 ); - return NULL; - } - cuddRef( zRes1 ); - - // only those variables are pair-wise symmetric - // that are pair-wise symmetric in both cofactors - // therefore, intersect the solutions - zRes = cuddZddIntersect( dd, zRes0, zRes1 ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes0 ); - Cudd_RecursiveDerefZdd( dd, zRes1 ); - return NULL; - } - cuddRef( zRes ); - Cudd_RecursiveDerefZdd( dd, zRes0 ); - Cudd_RecursiveDerefZdd( dd, zRes1 ); - } - - // consider the current top-most variable - AddVar = -1; - if ( Cudd_bddLeq( dd, bF0, bF1 ) ) // pos - AddVar = 0; - else if ( Cudd_bddLeq( dd, bF1, bF0 ) ) // neg - AddVar = 1; - if ( AddVar >= 0 ) - { - // create the singleton - zPlus = cuddZddGetNode( dd, 2*bFR->index + AddVar, z1, z0 ); - if ( zPlus == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes ); - return NULL; - } - cuddRef( zPlus ); - - // add these to the result - zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - return NULL; - } - cuddRef( zRes ); - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - } - // only zRes is referenced at this point - - // if we skipped some variables, these variables cannot be symmetric with - // any variables that are currently in the support of bF, but they can be - // symmetric with the variables that are in bVars but not in the support of bF - for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) ) - { - // create the negative singleton - zPlus = cuddZddGetNode( dd, 2*bVarsNew->index+1, z1, z0 ); - if ( zPlus == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes ); - return NULL; - } - cuddRef( zPlus ); - - // add these to the result - zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - return NULL; - } - cuddRef( zRes ); - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - - - // create the positive singleton - zPlus = cuddZddGetNode( dd, 2*bVarsNew->index, z1, z0 ); - if ( zPlus == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes ); - return NULL; - } - cuddRef( zPlus ); - - // add these to the result - zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - return NULL; - } - cuddRef( zRes ); - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - } - cuddDeref( zRes ); - - /* insert the result into cache */ - cuddCacheInsert2(dd, extraZddUnateInfoCompute, bFunc, bVars, zRes); - return zRes; - } -} /* end of extraZddUnateInfoCompute */ - - -/**Function******************************************************************** - - Synopsis [Performs a recursive step of Extra_zddGetSingletons.] - - Description [Returns the set of ZDD singletons, containing those pos/neg - polarity ZDD variables that correspond to the BDD variables in bVars.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * extraZddGetSingletonsBoth( - DdManager * dd, /* the DD manager */ - DdNode * bVars) /* the set of variables */ -{ - DdNode * zRes; - - if ( bVars == b1 ) - return z1; - - if ( (zRes = cuddCacheLookup1Zdd(dd, extraZddGetSingletonsBoth, bVars)) ) - return zRes; - else - { - DdNode * zTemp, * zPlus; - - // solve subproblem - zRes = extraZddGetSingletonsBoth( dd, cuddT(bVars) ); - if ( zRes == NULL ) - return NULL; - cuddRef( zRes ); - - - // create the negative singleton - zPlus = cuddZddGetNode( dd, 2*bVars->index+1, z1, z0 ); - if ( zPlus == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes ); - return NULL; - } - cuddRef( zPlus ); - - // add these to the result - zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - return NULL; - } - cuddRef( zRes ); - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - - - // create the positive singleton - zPlus = cuddZddGetNode( dd, 2*bVars->index, z1, z0 ); - if ( zPlus == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes ); - return NULL; - } - cuddRef( zPlus ); - - // add these to the result - zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - return NULL; - } - cuddRef( zRes ); - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - - cuddDeref( zRes ); - cuddCacheInsert1( dd, extraZddGetSingletonsBoth, bVars, zRes ); - return zRes; - } -} /* end of extraZddGetSingletonsBoth */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static Functions */ -/*---------------------------------------------------------------------------*/ -ABC_NAMESPACE_IMPL_END - diff --git a/src/misc/parse/module.make b/src/misc/parse/module.make new file mode 100644 index 00000000..bb13c8e5 --- /dev/null +++ b/src/misc/parse/module.make @@ -0,0 +1,2 @@ +SRC += src/misc/parse/parseEqn.c \ + src/misc/parse/parseStack.c diff --git a/src/misc/parse/parse.h b/src/misc/parse/parse.h new file mode 100644 index 00000000..584ec30a --- /dev/null +++ b/src/misc/parse/parse.h @@ -0,0 +1,62 @@ +/**CFile**************************************************************** + + FileName [parse.h] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Parsing symbolic Boolean formulas into BDDs.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 8, 2003.] + + Revision [$Id: parse.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__bdd__parse__parse_h +#define ABC__bdd__parse__parse_h + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== parseCore.c =============================================================*/ +extern DdNode * Parse_FormulaParser( FILE * pOutput, char * pFormula, int nVars, int nRanks, + char * ppVarNames[], DdManager * dd, DdNode * pbVars[] ); + + + +ABC_NAMESPACE_HEADER_END + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/src/misc/parse/parseCore.c b/src/misc/parse/parseCore.c new file mode 100644 index 00000000..f451d3aa --- /dev/null +++ b/src/misc/parse/parseCore.c @@ -0,0 +1,536 @@ +/**CFile**************************************************************** + + FileNameIn [parseCore.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Boolean formula parser.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: parseCore.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +/* + Some aspects of Boolean Formula Parser: + + 1) The names in the boolean formulas can be any strings of symbols + that start with char or underscore and contain chars, digits + and underscores: For example: 1) a&b <+> c'&d => a + b; + 2) a1 b2 c3' dummy' + (a2+b2')c3 dummy + 2) Constant values 0 and 1 can be used just like normal variables + 3) Any boolean operator (listed below) and parentheses can be used + any number of times provided there are equal number of opening + and closing parentheses. + 4) By default, absence of an operator between vars and before and + after parentheses is taken for AND. + 5) Both complementation prefix and complementation suffix can be + used at the same time (but who needs this?) + 6) Spaces (tabs, end-of-lines) may be inserted anywhere, + except between characters of the operations: <=>, =>, <=, <+> + 7) The stack size is defined by macro STACKSIZE and is used by the + stack constructor. +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#include "parseInt.h" + +ABC_NAMESPACE_IMPL_START + + +// the list of operation symbols to be used in expressions +#define PARSE_SYM_OPEN '(' // opening parenthesis +#define PARSE_SYM_CLOSE ')' // closing parenthesis +#define PARSE_SYM_LOWER '[' // shifts one rank down +#define PARSE_SYM_RAISE ']' // shifts one rank up +#define PARSE_SYM_CONST0 '0' // constant 0 +#define PARSE_SYM_CONST1 '1' // constant 1 +#define PARSE_SYM_NEGBEF1 '!' // negation before the variable +#define PARSE_SYM_NEGBEF2 '~' // negation before the variable +#define PARSE_SYM_NEGAFT '\'' // negation after the variable +#define PARSE_SYM_AND1 '&' // logic AND +#define PARSE_SYM_AND2 '*' // logic AND +#define PARSE_SYM_XOR1 '<' // logic EXOR (the 1st symbol) +#define PARSE_SYM_XOR2 '+' // logic EXOR (the 2nd symbol) +#define PARSE_SYM_XOR3 '>' // logic EXOR (the 3rd symbol) +#define PARSE_SYM_XOR '^' // logic XOR +#define PARSE_SYM_OR1 '+' // logic OR +#define PARSE_SYM_OR2 '|' // logic OR +#define PARSE_SYM_EQU1 '<' // equvalence (the 1st symbol) +#define PARSE_SYM_EQU2 '=' // equvalence (the 2nd symbol) +#define PARSE_SYM_EQU3 '>' // equvalence (the 3rd symbol) +#define PARSE_SYM_FLR1 '=' // implication (the 1st symbol) +#define PARSE_SYM_FLR2 '>' // implication (the 2nd symbol) +#define PARSE_SYM_FLL1 '<' // backward imp (the 1st symbol) +#define PARSE_SYM_FLL2 '=' // backward imp (the 2nd symbol) +// PARSE_SYM_FLR1 and PARSE_SYM_FLR2 should be the same as PARSE_SYM_EQU2 and PARSE_SYM_EQU3! + +// the list of opcodes (also specifying operation precedence) +#define PARSE_OPER_NEG 10 // negation +#define PARSE_OPER_AND 9 // logic AND +#define PARSE_OPER_XOR 8 // logic EXOR (a'b | ab') +#define PARSE_OPER_OR 7 // logic OR +#define PARSE_OPER_EQU 6 // equvalence (a'b'| ab ) +#define PARSE_OPER_FLR 5 // implication ( a' | b ) +#define PARSE_OPER_FLL 4 // backward imp ( 'b | a ) +#define PARSE_OPER_MARK 1 // OpStack token standing for an opening parenthesis + +// these are values of the internal Flag +#define PARSE_FLAG_START 1 // after the opening parenthesis +#define PARSE_FLAG_VAR 2 // after operation is received +#define PARSE_FLAG_OPER 3 // after operation symbol is received +#define PARSE_FLAG_ERROR 4 // when error is detected + +#define STACKSIZE 1000 + +static DdNode * Parse_ParserPerformTopOp( DdManager * dd, Parse_StackFn_t * pStackFn, int Oper ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Derives the BDD corresponding to the formula in language L.] + + Description [Takes the stream to output messages, the formula, the number + variables and the rank in the formula. The array of variable names is also + given. The BDD manager and the elementary 0-rank variable are the last two + arguments. The manager should have at least as many variables as + nVars * (nRanks + 1). The 0-rank variables should have numbers larger + than the variables of other ranks.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Parse_FormulaParser( FILE * pOutput, char * pFormulaInit, int nVars, int nRanks, + char * ppVarNames[], DdManager * dd, DdNode * pbVars[] ) +{ + char * pFormula; + Parse_StackFn_t * pStackFn; + Parse_StackOp_t * pStackOp; + DdNode * bFunc, * bTemp; + char * pTemp; + int nParans, fFound, Flag; + int Oper, Oper1, Oper2; + int i, fLower; + int v = -1; // Suppress "might be used uninitialized" + + // make sure that the number of vars and ranks is correct + if ( nVars * (nRanks + 1) > dd->size ) + { + printf( "Parse_FormulaParser(): The BDD manager does not have enough variables.\n" ); + return NULL; + } + + // make sure that the number of opening and closing parentheses is the same + nParans = 0; + for ( pTemp = pFormulaInit; *pTemp; pTemp++ ) + if ( *pTemp == '(' ) + nParans++; + else if ( *pTemp == ')' ) + nParans--; + if ( nParans != 0 ) + { + fprintf( pOutput, "Parse_FormulaParser(): Different number of opening and closing parentheses ().\n" ); + return NULL; + } + + nParans = 0; + for ( pTemp = pFormulaInit; *pTemp; pTemp++ ) + if ( *pTemp == '[' ) + nParans++; + else if ( *pTemp == ']' ) + nParans--; + if ( nParans != 0 ) + { + fprintf( pOutput, "Parse_FormulaParser(): Different number of opening and closing brackets [].\n" ); + return NULL; + } + + // copy the formula + pFormula = ABC_ALLOC( char, strlen(pFormulaInit) + 3 ); + sprintf( pFormula, "(%s)", pFormulaInit ); + + // start the stacks + pStackFn = Parse_StackFnStart( STACKSIZE ); + pStackOp = Parse_StackOpStart( STACKSIZE ); + + Flag = PARSE_FLAG_START; + fLower = 0; + for ( pTemp = pFormula; *pTemp; pTemp++ ) + { + switch ( *pTemp ) + { + // skip all spaces, tabs, and end-of-lines + case ' ': + case '\t': + case '\r': + case '\n': + continue; + + // treat Constant 0 as a variable + case PARSE_SYM_CONST0: + Parse_StackFnPush( pStackFn, b0 ); Cudd_Ref( b0 ); + if ( Flag == PARSE_FLAG_VAR ) + { + fprintf( pOutput, "Parse_FormulaParser(): No operation symbol before constant 0.\n" ); + Flag = PARSE_FLAG_ERROR; + break; + } + Flag = PARSE_FLAG_VAR; + break; + + // the same for Constant 1 + case PARSE_SYM_CONST1: + Parse_StackFnPush( pStackFn, b1 ); Cudd_Ref( b1 ); + if ( Flag == PARSE_FLAG_VAR ) + { + fprintf( pOutput, "Parse_FormulaParser(): No operation symbol before constant 1.\n" ); + Flag = PARSE_FLAG_ERROR; + break; + } + Flag = PARSE_FLAG_VAR; + break; + + case PARSE_SYM_NEGBEF1: + case PARSE_SYM_NEGBEF2: + if ( Flag == PARSE_FLAG_VAR ) + {// if NEGBEF follows a variable, AND is assumed + Parse_StackOpPush( pStackOp, PARSE_OPER_AND ); + Flag = PARSE_FLAG_OPER; + } + Parse_StackOpPush( pStackOp, PARSE_OPER_NEG ); + break; + + case PARSE_SYM_NEGAFT: + if ( Flag != PARSE_FLAG_VAR ) + {// if there is no variable before NEGAFT, it is an error + fprintf( pOutput, "Parse_FormulaParser(): No variable is specified before the negation suffix.\n" ); + Flag = PARSE_FLAG_ERROR; + break; + } + else // if ( Flag == PARSE_FLAG_VAR ) + Parse_StackFnPush( pStackFn, Cudd_Not( Parse_StackFnPop(pStackFn) ) ); + break; + + case PARSE_SYM_AND1: + case PARSE_SYM_AND2: + case PARSE_SYM_OR1: + case PARSE_SYM_OR2: + case PARSE_SYM_XOR: + if ( Flag != PARSE_FLAG_VAR ) + { + fprintf( pOutput, "Parse_FormulaParser(): There is no variable before AND, EXOR, or OR.\n" ); + Flag = PARSE_FLAG_ERROR; + break; + } + if ( *pTemp == PARSE_SYM_AND1 || *pTemp == PARSE_SYM_AND2 ) + Parse_StackOpPush( pStackOp, PARSE_OPER_AND ); + else if ( *pTemp == PARSE_SYM_OR1 || *pTemp == PARSE_SYM_OR2 ) + Parse_StackOpPush( pStackOp, PARSE_OPER_OR ); + else //if ( Str[Pos] == PARSE_SYM_XOR ) + Parse_StackOpPush( pStackOp, PARSE_OPER_XOR ); + Flag = PARSE_FLAG_OPER; + break; + + case PARSE_SYM_EQU1: + if ( Flag != PARSE_FLAG_VAR ) + { + fprintf( pOutput, "Parse_FormulaParser(): There is no variable before Equivalence or Implication\n" ); + Flag = PARSE_FLAG_ERROR; break; + } + if ( pTemp[1] == PARSE_SYM_EQU2 ) + { // check what is the next symbol in the string + pTemp++; + if ( pTemp[1] == PARSE_SYM_EQU3 ) + { + pTemp++; + Parse_StackOpPush( pStackOp, PARSE_OPER_EQU ); + } + else + { + Parse_StackOpPush( pStackOp, PARSE_OPER_FLL ); + } + } + else if ( pTemp[1] == PARSE_SYM_XOR2 ) + { + pTemp++; + if ( pTemp[1] == PARSE_SYM_XOR3 ) + { + pTemp++; + Parse_StackOpPush( pStackOp, PARSE_OPER_XOR ); + } + else + { + fprintf( pOutput, "Parse_FormulaParser(): Wrong symbol after \"%c%c\"\n", PARSE_SYM_EQU1, PARSE_SYM_XOR2 ); + Flag = PARSE_FLAG_ERROR; + break; + } + } + else + { + fprintf( pOutput, "Parse_FormulaParser(): Wrong symbol after \"%c\"\n", PARSE_SYM_EQU1 ); + Flag = PARSE_FLAG_ERROR; + break; + } + Flag = PARSE_FLAG_OPER; + break; + + case PARSE_SYM_EQU2: + if ( Flag != PARSE_FLAG_VAR ) + { + fprintf( pOutput, "Parse_FormulaParser(): There is no variable before Reverse Implication\n" ); + Flag = PARSE_FLAG_ERROR; + break; + } + if ( pTemp[1] == PARSE_SYM_EQU3 ) + { + pTemp++; + Parse_StackOpPush( pStackOp, PARSE_OPER_FLR ); + } + else + { + fprintf( pOutput, "Parse_FormulaParser(): Wrong symbol after \"%c\"\n", PARSE_SYM_EQU2 ); + Flag = PARSE_FLAG_ERROR; + break; + } + Flag = PARSE_FLAG_OPER; + break; + + case PARSE_SYM_LOWER: + case PARSE_SYM_OPEN: + if ( Flag == PARSE_FLAG_VAR ) + Parse_StackOpPush( pStackOp, PARSE_OPER_AND ); + Parse_StackOpPush( pStackOp, PARSE_OPER_MARK ); + // after an opening bracket, it feels like starting over again + Flag = PARSE_FLAG_START; + break; + + case PARSE_SYM_RAISE: + fLower = 1; + case PARSE_SYM_CLOSE: + if ( !Parse_StackOpIsEmpty( pStackOp ) ) + { + while ( 1 ) + { + if ( Parse_StackOpIsEmpty( pStackOp ) ) + { + fprintf( pOutput, "Parse_FormulaParser(): There is no opening parenthesis\n" ); + Flag = PARSE_FLAG_ERROR; + break; + } + Oper = Parse_StackOpPop( pStackOp ); + if ( Oper == PARSE_OPER_MARK ) + break; + + // perform the given operation + if ( Parse_ParserPerformTopOp( dd, pStackFn, Oper ) == NULL ) + { + fprintf( pOutput, "Parse_FormulaParser(): Unknown operation\n" ); + ABC_FREE( pFormula ); + return NULL; + } + } + + if ( fLower ) + { + bFunc = (DdNode *)Parse_StackFnPop( pStackFn ); + bFunc = Extra_bddMove( dd, bTemp = bFunc, -nVars ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( dd, bTemp ); + Parse_StackFnPush( pStackFn, bFunc ); + } + } + else + { + fprintf( pOutput, "Parse_FormulaParser(): There is no opening parenthesis\n" ); + Flag = PARSE_FLAG_ERROR; + break; + } + if ( Flag != PARSE_FLAG_ERROR ) + Flag = PARSE_FLAG_VAR; + fLower = 0; + break; + + + default: + // scan the next name +/* + fFound = 0; + for ( i = 0; pTemp[i] && pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n'; i++ ) + { + for ( v = 0; v < nVars; v++ ) + if ( strncmp( pTemp, ppVarNames[v], i+1 ) == 0 && strlen(ppVarNames[v]) == (unsigned)(i+1) ) + { + pTemp += i; + fFound = 1; + break; + } + if ( fFound ) + break; + } +*/ + // bug fix by SV (9/11/08) + fFound = 0; + for ( i = 0; pTemp[i] && pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n' && + pTemp[i] != PARSE_SYM_AND1 && pTemp[i] != PARSE_SYM_AND2 && pTemp[i] != PARSE_SYM_XOR1 && + pTemp[i] != PARSE_SYM_XOR2 && pTemp[i] != PARSE_SYM_XOR3 && pTemp[i] != PARSE_SYM_XOR && + pTemp[i] != PARSE_SYM_OR1 && pTemp[i] != PARSE_SYM_OR2 && pTemp[i] != PARSE_SYM_CLOSE && + pTemp[i] != PARSE_SYM_NEGAFT; + i++ ) + {} + for ( v = 0; v < nVars; v++ ) + { + if ( strncmp( pTemp, ppVarNames[v], i ) == 0 && strlen(ppVarNames[v]) == (unsigned)(i) ) + { + pTemp += i-1; + fFound = 1; + break; + } + } + + if ( !fFound ) + { + fprintf( pOutput, "Parse_FormulaParser(): The parser cannot find var \"%s\" in the input var list.\n", pTemp ); + Flag = PARSE_FLAG_ERROR; + break; + } + // assume operation AND, if vars follow one another + if ( Flag == PARSE_FLAG_VAR ) + Parse_StackOpPush( pStackOp, PARSE_OPER_AND ); + Parse_StackFnPush( pStackFn, pbVars[v] ); Cudd_Ref( pbVars[v] ); + Flag = PARSE_FLAG_VAR; + break; + } + + if ( Flag == PARSE_FLAG_ERROR ) + break; // error exit + else if ( Flag == PARSE_FLAG_START ) + continue; // go on parsing + else if ( Flag == PARSE_FLAG_VAR ) + while ( 1 ) + { // check if there are negations in the OpStack + if ( Parse_StackOpIsEmpty(pStackOp) ) + break; + Oper = Parse_StackOpPop( pStackOp ); + if ( Oper != PARSE_OPER_NEG ) + { + Parse_StackOpPush( pStackOp, Oper ); + break; + } + else + { + Parse_StackFnPush( pStackFn, Cudd_Not(Parse_StackFnPop(pStackFn)) ); + } + } + else // if ( Flag == PARSE_FLAG_OPER ) + while ( 1 ) + { // execute all the operations in the OpStack + // with precedence higher or equal than the last one + Oper1 = Parse_StackOpPop( pStackOp ); // the last operation + if ( Parse_StackOpIsEmpty(pStackOp) ) + { // if it is the only operation, push it back + Parse_StackOpPush( pStackOp, Oper1 ); + break; + } + Oper2 = Parse_StackOpPop( pStackOp ); // the operation before the last one + if ( Oper2 >= Oper1 ) + { // if Oper2 precedence is higher or equal, execute it +// Parse_StackPush( pStackFn, Operation( FunStack.Pop(), FunStack.Pop(), Oper2 ) ); + if ( Parse_ParserPerformTopOp( dd, pStackFn, Oper2 ) == NULL ) + { + fprintf( pOutput, "Parse_FormulaParser(): Unknown operation\n" ); + ABC_FREE( pFormula ); + return NULL; + } + Parse_StackOpPush( pStackOp, Oper1 ); // push the last operation back + } + else + { // if Oper2 precedence is lower, push them back and done + Parse_StackOpPush( pStackOp, Oper2 ); + Parse_StackOpPush( pStackOp, Oper1 ); + break; + } + } + } + + if ( Flag != PARSE_FLAG_ERROR ) + { + if ( !Parse_StackFnIsEmpty(pStackFn) ) + { + bFunc = (DdNode *)Parse_StackFnPop(pStackFn); + if ( Parse_StackFnIsEmpty(pStackFn) ) + if ( Parse_StackOpIsEmpty(pStackOp) ) + { + Parse_StackFnFree(pStackFn); + Parse_StackOpFree(pStackOp); + Cudd_Deref( bFunc ); + ABC_FREE( pFormula ); + return bFunc; + } + else + fprintf( pOutput, "Parse_FormulaParser(): Something is left in the operation stack\n" ); + else + fprintf( pOutput, "Parse_FormulaParser(): Something is left in the function stack\n" ); + } + else + fprintf( pOutput, "Parse_FormulaParser(): The input string is empty\n" ); + } + ABC_FREE( pFormula ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Performs the operation on the top entries in the stack.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Parse_ParserPerformTopOp( DdManager * dd, Parse_StackFn_t * pStackFn, int Oper ) +{ + DdNode * bArg1, * bArg2, * bFunc; + // perform the given operation + bArg2 = (DdNode *)Parse_StackFnPop( pStackFn ); + bArg1 = (DdNode *)Parse_StackFnPop( pStackFn ); + if ( Oper == PARSE_OPER_AND ) + bFunc = Cudd_bddAnd( dd, bArg1, bArg2 ); + else if ( Oper == PARSE_OPER_XOR ) + bFunc = Cudd_bddXor( dd, bArg1, bArg2 ); + else if ( Oper == PARSE_OPER_OR ) + bFunc = Cudd_bddOr( dd, bArg1, bArg2 ); + else if ( Oper == PARSE_OPER_EQU ) + bFunc = Cudd_bddXnor( dd, bArg1, bArg2 ); + else if ( Oper == PARSE_OPER_FLR ) + bFunc = Cudd_bddOr( dd, Cudd_Not(bArg1), bArg2 ); + else if ( Oper == PARSE_OPER_FLL ) + bFunc = Cudd_bddOr( dd, Cudd_Not(bArg2), bArg1 ); + else + return NULL; + Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( dd, bArg1 ); + Cudd_RecursiveDeref( dd, bArg2 ); + Parse_StackFnPush( pStackFn, bFunc ); + return bFunc; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// +ABC_NAMESPACE_IMPL_END + diff --git a/src/misc/parse/parseEqn.c b/src/misc/parse/parseEqn.c new file mode 100644 index 00000000..eef95dc2 --- /dev/null +++ b/src/misc/parse/parseEqn.c @@ -0,0 +1,355 @@ +/**CFile**************************************************************** + + FileNameIn [parseEqn.c] + + PackageName [ABC: Logic synthesis and verification system.] + + Synopsis [Boolean formula parser.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - December 18, 2006.] + + Revision [$Id: parseEqn.c,v 1.0 2006/12/18 00:00:00 alanmi Exp $] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#include "parseInt.h" + +ABC_NAMESPACE_IMPL_START + + +// the list of operation symbols to be used in expressions +#define PARSE_EQN_SYM_OPEN '(' // opening parenthesis +#define PARSE_EQN_SYM_CLOSE ')' // closing parenthesis +#define PARSE_EQN_SYM_CONST0 '0' // constant 0 +#define PARSE_EQN_SYM_CONST1 '1' // constant 1 +#define PARSE_EQN_SYM_NEG '!' // negation before the variable +#define PARSE_EQN_SYM_AND '*' // logic AND +#define PARSE_EQN_SYM_OR '+' // logic OR + +// the list of opcodes (also specifying operation precedence) +#define PARSE_EQN_OPER_NEG 10 // negation +#define PARSE_EQN_OPER_AND 9 // logic AND +#define PARSE_EQN_OPER_OR 7 // logic OR +#define PARSE_EQN_OPER_MARK 1 // OpStack token standing for an opening parenthesis + +// these are values of the internal Flag +#define PARSE_EQN_FLAG_START 1 // after the opening parenthesis +#define PARSE_EQN_FLAG_VAR 2 // after operation is received +#define PARSE_EQN_FLAG_OPER 3 // after operation symbol is received +#define PARSE_EQN_FLAG_ERROR 4 // when error is detected + +#define PARSE_EQN_STACKSIZE 1000 + +static Hop_Obj_t * Parse_ParserPerformTopOp( Hop_Man_t * pMan, Parse_StackFn_t * pStackFn, int Oper ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Derives the AIG corresponding to the equation.] + + Description [Takes the stream to output messages, the formula, the vector + of variable names and the AIG manager.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Parse_FormulaParserEqn( FILE * pOutput, char * pFormInit, Vec_Ptr_t * vVarNames, Hop_Man_t * pMan ) +{ + char * pFormula; + Parse_StackFn_t * pStackFn; + Parse_StackOp_t * pStackOp; + Hop_Obj_t * gFunc; + char * pTemp, * pName; + int nParans, fFound, Flag; + int Oper, Oper1, Oper2; + int i, v; + + // make sure that the number of opening and closing parentheses is the same + nParans = 0; + for ( pTemp = pFormInit; *pTemp; pTemp++ ) + if ( *pTemp == '(' ) + nParans++; + else if ( *pTemp == ')' ) + nParans--; + if ( nParans != 0 ) + { + fprintf( pOutput, "Parse_FormulaParserEqn(): Different number of opening and closing parentheses ().\n" ); + return NULL; + } + + // copy the formula + pFormula = ABC_ALLOC( char, strlen(pFormInit) + 3 ); + sprintf( pFormula, "(%s)", pFormInit ); + + // start the stacks + pStackFn = Parse_StackFnStart( PARSE_EQN_STACKSIZE ); + pStackOp = Parse_StackOpStart( PARSE_EQN_STACKSIZE ); + + Flag = PARSE_EQN_FLAG_START; + for ( pTemp = pFormula; *pTemp; pTemp++ ) + { + switch ( *pTemp ) + { + // skip all spaces, tabs, and end-of-lines + case ' ': + case '\t': + case '\r': + case '\n': + continue; + case PARSE_EQN_SYM_CONST0: + Parse_StackFnPush( pStackFn, Hop_ManConst0(pMan) ); // Cudd_Ref( b0 ); + if ( Flag == PARSE_EQN_FLAG_VAR ) + { + fprintf( pOutput, "Parse_FormulaParserEqn(): No operation symbol before constant 0.\n" ); + Flag = PARSE_EQN_FLAG_ERROR; + break; + } + Flag = PARSE_EQN_FLAG_VAR; + break; + case PARSE_EQN_SYM_CONST1: + Parse_StackFnPush( pStackFn, Hop_ManConst1(pMan) ); // Cudd_Ref( b1 ); + if ( Flag == PARSE_EQN_FLAG_VAR ) + { + fprintf( pOutput, "Parse_FormulaParserEqn(): No operation symbol before constant 1.\n" ); + Flag = PARSE_EQN_FLAG_ERROR; + break; + } + Flag = PARSE_EQN_FLAG_VAR; + break; + case PARSE_EQN_SYM_NEG: + if ( Flag == PARSE_EQN_FLAG_VAR ) + {// if NEGBEF follows a variable, AND is assumed + Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_AND ); + Flag = PARSE_EQN_FLAG_OPER; + } + Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_NEG ); + break; + case PARSE_EQN_SYM_AND: + case PARSE_EQN_SYM_OR: + if ( Flag != PARSE_EQN_FLAG_VAR ) + { + fprintf( pOutput, "Parse_FormulaParserEqn(): There is no variable before AND, EXOR, or OR.\n" ); + Flag = PARSE_EQN_FLAG_ERROR; + break; + } + if ( *pTemp == PARSE_EQN_SYM_AND ) + Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_AND ); + else //if ( *pTemp == PARSE_EQN_SYM_OR ) + Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_OR ); + Flag = PARSE_EQN_FLAG_OPER; + break; + case PARSE_EQN_SYM_OPEN: + if ( Flag == PARSE_EQN_FLAG_VAR ) + { +// Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_AND ); + fprintf( pOutput, "Parse_FormulaParserEqn(): An opening parenthesis follows a var without operation sign.\n" ); + Flag = PARSE_EQN_FLAG_ERROR; + break; + } + Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_MARK ); + // after an opening bracket, it feels like starting over again + Flag = PARSE_EQN_FLAG_START; + break; + case PARSE_EQN_SYM_CLOSE: + if ( !Parse_StackOpIsEmpty( pStackOp ) ) + { + while ( 1 ) + { + if ( Parse_StackOpIsEmpty( pStackOp ) ) + { + fprintf( pOutput, "Parse_FormulaParserEqn(): There is no opening parenthesis\n" ); + Flag = PARSE_EQN_FLAG_ERROR; + break; + } + Oper = Parse_StackOpPop( pStackOp ); + if ( Oper == PARSE_EQN_OPER_MARK ) + break; + + // perform the given operation + if ( Parse_ParserPerformTopOp( pMan, pStackFn, Oper ) == NULL ) + { + Parse_StackFnFree( pStackFn ); + Parse_StackOpFree( pStackOp ); + fprintf( pOutput, "Parse_FormulaParserEqn(): Unknown operation\n" ); + ABC_FREE( pFormula ); + return NULL; + } + } + } + else + { + fprintf( pOutput, "Parse_FormulaParserEqn(): There is no opening parenthesis\n" ); + Flag = PARSE_EQN_FLAG_ERROR; + break; + } + if ( Flag != PARSE_EQN_FLAG_ERROR ) + Flag = PARSE_EQN_FLAG_VAR; + break; + + + default: + // scan the next name + for ( i = 0; pTemp[i] && + pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n' && + pTemp[i] != PARSE_EQN_SYM_AND && pTemp[i] != PARSE_EQN_SYM_OR && pTemp[i] != PARSE_EQN_SYM_CLOSE; i++ ) + { + if ( pTemp[i] == PARSE_EQN_SYM_NEG || pTemp[i] == PARSE_EQN_SYM_OPEN ) + { + fprintf( pOutput, "Parse_FormulaParserEqn(): The negation sign or an opening parenthesis inside the variable name.\n" ); + Flag = PARSE_EQN_FLAG_ERROR; + break; + } + } + // variable name is found + fFound = 0; + Vec_PtrForEachEntry( char *, vVarNames, pName, v ) + if ( strncmp(pTemp, pName, i) == 0 && strlen(pName) == (unsigned)i ) + { + pTemp += i-1; + fFound = 1; + break; + } + if ( !fFound ) + { + fprintf( pOutput, "Parse_FormulaParserEqn(): The parser cannot find var \"%s\" in the input var list.\n", pTemp ); + Flag = PARSE_EQN_FLAG_ERROR; + break; + } + if ( Flag == PARSE_EQN_FLAG_VAR ) + { + fprintf( pOutput, "Parse_FormulaParserEqn(): The variable name \"%s\" follows another var without operation sign.\n", pTemp ); + Flag = PARSE_EQN_FLAG_ERROR; + break; + } + Parse_StackFnPush( pStackFn, Hop_IthVar( pMan, v ) ); // Cudd_Ref( pbVars[v] ); + Flag = PARSE_EQN_FLAG_VAR; + break; + } + + if ( Flag == PARSE_EQN_FLAG_ERROR ) + break; // error exit + else if ( Flag == PARSE_EQN_FLAG_START ) + continue; // go on parsing + else if ( Flag == PARSE_EQN_FLAG_VAR ) + while ( 1 ) + { // check if there are negations in the OpStack + if ( Parse_StackOpIsEmpty(pStackOp) ) + break; + Oper = Parse_StackOpPop( pStackOp ); + if ( Oper != PARSE_EQN_OPER_NEG ) + { + Parse_StackOpPush( pStackOp, Oper ); + break; + } + else + { + Parse_StackFnPush( pStackFn, Hop_Not((Hop_Obj_t *)Parse_StackFnPop(pStackFn)) ); + } + } + else // if ( Flag == PARSE_EQN_FLAG_OPER ) + while ( 1 ) + { // execute all the operations in the OpStack + // with precedence higher or equal than the last one + Oper1 = Parse_StackOpPop( pStackOp ); // the last operation + if ( Parse_StackOpIsEmpty(pStackOp) ) + { // if it is the only operation, push it back + Parse_StackOpPush( pStackOp, Oper1 ); + break; + } + Oper2 = Parse_StackOpPop( pStackOp ); // the operation before the last one + if ( Oper2 >= Oper1 ) + { // if Oper2 precedence is higher or equal, execute it + if ( Parse_ParserPerformTopOp( pMan, pStackFn, Oper2 ) == NULL ) + { + fprintf( pOutput, "Parse_FormulaParserEqn(): Unknown operation\n" ); + ABC_FREE( pFormula ); + Parse_StackFnFree( pStackFn ); + Parse_StackOpFree( pStackOp ); + return NULL; + } + Parse_StackOpPush( pStackOp, Oper1 ); // push the last operation back + } + else + { // if Oper2 precedence is lower, push them back and done + Parse_StackOpPush( pStackOp, Oper2 ); + Parse_StackOpPush( pStackOp, Oper1 ); + break; + } + } + } + + if ( Flag != PARSE_EQN_FLAG_ERROR ) + { + if ( !Parse_StackFnIsEmpty(pStackFn) ) + { + gFunc = (Hop_Obj_t *)Parse_StackFnPop(pStackFn); + if ( Parse_StackFnIsEmpty(pStackFn) ) + if ( Parse_StackOpIsEmpty(pStackOp) ) + { + Parse_StackFnFree(pStackFn); + Parse_StackOpFree(pStackOp); +// Cudd_Deref( gFunc ); + ABC_FREE( pFormula ); + return gFunc; + } + else + fprintf( pOutput, "Parse_FormulaParserEqn(): Something is left in the operation stack\n" ); + else + fprintf( pOutput, "Parse_FormulaParserEqn(): Something is left in the function stack\n" ); + } + else + fprintf( pOutput, "Parse_FormulaParserEqn(): The input string is empty\n" ); + } + ABC_FREE( pFormula ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Performs the operation on the top entries in the stack.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Parse_ParserPerformTopOp( Hop_Man_t * pMan, Parse_StackFn_t * pStackFn, int Oper ) +{ + Hop_Obj_t * gArg1, * gArg2, * gFunc; + // perform the given operation + gArg2 = (Hop_Obj_t *)Parse_StackFnPop( pStackFn ); + gArg1 = (Hop_Obj_t *)Parse_StackFnPop( pStackFn ); + if ( Oper == PARSE_EQN_OPER_AND ) + gFunc = Hop_And( pMan, gArg1, gArg2 ); + else if ( Oper == PARSE_EQN_OPER_OR ) + gFunc = Hop_Or( pMan, gArg1, gArg2 ); + else + return NULL; +// Cudd_Ref( gFunc ); +// Cudd_RecursiveDeref( dd, gArg1 ); +// Cudd_RecursiveDeref( dd, gArg2 ); + Parse_StackFnPush( pStackFn, gFunc ); + return gFunc; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// +ABC_NAMESPACE_IMPL_END + diff --git a/src/misc/parse/parseInt.h b/src/misc/parse/parseInt.h new file mode 100644 index 00000000..42a9805b --- /dev/null +++ b/src/misc/parse/parseInt.h @@ -0,0 +1,77 @@ +/**CFile**************************************************************** + + FileName [parseInt.h] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Parsing symbolic Boolean formulas into BDDs.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 8, 2003.] + + Revision [$Id: parseInt.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__bdd__parse__parseInt_h +#define ABC__bdd__parse__parseInt_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "aig/hop/hop.h" +#include "misc/vec/vec.h" + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct ParseStackFnStruct Parse_StackFn_t; // the function stack +typedef struct ParseStackOpStruct Parse_StackOp_t; // the operation stack + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== parseStack.c =============================================================*/ +extern Parse_StackFn_t * Parse_StackFnStart ( int nDepth ); +extern int Parse_StackFnIsEmpty( Parse_StackFn_t * p ); +extern void Parse_StackFnPush ( Parse_StackFn_t * p, void * bFunc ); +extern void * Parse_StackFnPop ( Parse_StackFn_t * p ); +extern void Parse_StackFnFree ( Parse_StackFn_t * p ); + +extern Parse_StackOp_t * Parse_StackOpStart ( int nDepth ); +extern int Parse_StackOpIsEmpty( Parse_StackOp_t * p ); +extern void Parse_StackOpPush ( Parse_StackOp_t * p, int Oper ); +extern int Parse_StackOpPop ( Parse_StackOp_t * p ); +extern void Parse_StackOpFree ( Parse_StackOp_t * p ); + + + +ABC_NAMESPACE_HEADER_END + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/src/misc/parse/parseStack.c b/src/misc/parse/parseStack.c new file mode 100644 index 00000000..2e6d266d --- /dev/null +++ b/src/misc/parse/parseStack.c @@ -0,0 +1,248 @@ +/**CFile**************************************************************** + + FileName [parseStack.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Stacks used by the formula parser.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 18, 2003.] + + Revision [$Id: parseStack.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "parseInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +struct ParseStackFnStruct +{ + void ** pData; // the array of elements + int Top; // the index + int Size; // the stack size +}; + +struct ParseStackOpStruct +{ + int * pData; // the array of elements + int Top; // the index + int Size; // the stack size +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the stack.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Parse_StackFn_t * Parse_StackFnStart( int nDepth ) +{ + Parse_StackFn_t * p; + p = ABC_ALLOC( Parse_StackFn_t, 1 ); + memset( p, 0, sizeof(Parse_StackFn_t) ); + p->pData = ABC_ALLOC( void *, nDepth ); + p->Size = nDepth; + return p; +} + +/**Function************************************************************* + + Synopsis [Checks whether the stack is empty.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Parse_StackFnIsEmpty( Parse_StackFn_t * p ) +{ + return (int)(p->Top == 0); +} + +/**Function************************************************************* + + Synopsis [Pushes an entry into the stack.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Parse_StackFnPush( Parse_StackFn_t * p, void * bFunc ) +{ + if ( p->Top >= p->Size ) + { + printf( "Parse_StackFnPush(): Stack size is too small!\n" ); + return; + } + p->pData[ p->Top++ ] = bFunc; +} + +/**Function************************************************************* + + Synopsis [Pops an entry out of the stack.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Parse_StackFnPop( Parse_StackFn_t * p ) +{ + if ( p->Top == 0 ) + { + printf( "Parse_StackFnPush(): Trying to extract data from the empty stack!\n" ); + return NULL; + } + return p->pData[ --p->Top ]; +} + +/**Function************************************************************* + + Synopsis [Deletes the stack.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Parse_StackFnFree( Parse_StackFn_t * p ) +{ + ABC_FREE( p->pData ); + ABC_FREE( p ); +} + + + + +/**Function************************************************************* + + Synopsis [Starts the stack.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Parse_StackOp_t * Parse_StackOpStart( int nDepth ) +{ + Parse_StackOp_t * p; + p = ABC_ALLOC( Parse_StackOp_t, 1 ); + memset( p, 0, sizeof(Parse_StackOp_t) ); + p->pData = ABC_ALLOC( int, nDepth ); + p->Size = nDepth; + return p; +} + +/**Function************************************************************* + + Synopsis [Checks whether the stack is empty.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Parse_StackOpIsEmpty( Parse_StackOp_t * p ) +{ + return (int)(p->Top == 0); +} + +/**Function************************************************************* + + Synopsis [Pushes an entry into the stack.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Parse_StackOpPush( Parse_StackOp_t * p, int Oper ) +{ + if ( p->Top >= p->Size ) + { + printf( "Parse_StackOpPush(): Stack size is too small!\n" ); + return; + } + p->pData[ p->Top++ ] = Oper; +} + +/**Function************************************************************* + + Synopsis [Pops an entry out of the stack.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Parse_StackOpPop( Parse_StackOp_t * p ) +{ + if ( p->Top == 0 ) + { + printf( "Parse_StackOpPush(): Trying to extract data from the empty stack!\n" ); + return -1; + } + return p->pData[ --p->Top ]; +} + +/**Function************************************************************* + + Synopsis [Deletes the stack.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Parse_StackOpFree( Parse_StackOp_t * p ) +{ + ABC_FREE( p->pData ); + ABC_FREE( p ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/proof/bbr/bbr.h b/src/proof/bbr/bbr.h deleted file mode 100644 index 1db638e8..00000000 --- a/src/proof/bbr/bbr.h +++ /dev/null @@ -1,93 +0,0 @@ -/**CFile**************************************************************** - - FileName [bbr.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD-based reachability analysis.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: bbr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef ABC__aig__bbr__bbr_h -#define ABC__aig__bbr__bbr_h - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include "aig/aig/aig.h" -#include "aig/saig/saig.h" -#include "bdd/cudd/cuddInt.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline DdNode * Aig_ObjGlobalBdd( Aig_Obj_t * pObj ) { return (DdNode *)pObj->pData; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== bbrImage.c ==========================================================*/ -typedef struct Bbr_ImageTree_t_ Bbr_ImageTree_t; -extern Bbr_ImageTree_t * Bbr_bddImageStart( - DdManager * dd, DdNode * bCare, - int nParts, DdNode ** pbParts, - int nVars, DdNode ** pbVars, int nBddMax, int fVerbose ); -extern DdNode * Bbr_bddImageCompute( Bbr_ImageTree_t * pTree, DdNode * bCare ); -extern void Bbr_bddImageTreeDelete( Bbr_ImageTree_t * pTree ); -extern DdNode * Bbr_bddImageRead( Bbr_ImageTree_t * pTree ); -typedef struct Bbr_ImageTree2_t_ Bbr_ImageTree2_t; -extern Bbr_ImageTree2_t * Bbr_bddImageStart2( - DdManager * dd, DdNode * bCare, - int nParts, DdNode ** pbParts, - int nVars, DdNode ** pbVars, int fVerbose ); -extern DdNode * Bbr_bddImageCompute2( Bbr_ImageTree2_t * pTree, DdNode * bCare ); -extern void Bbr_bddImageTreeDelete2( Bbr_ImageTree2_t * pTree ); -extern DdNode * Bbr_bddImageRead2( Bbr_ImageTree2_t * pTree ); -/*=== bbrNtbdd.c ==========================================================*/ -extern void Aig_ManFreeGlobalBdds( Aig_Man_t * p, DdManager * dd ); -extern int Aig_ManSizeOfGlobalBdds( Aig_Man_t * p ); -extern DdManager * Aig_ManComputeGlobalBdds( Aig_Man_t * p, int nBddSizeMax, int fDropInternal, int fReorder, int fVerbose ); -/*=== bbrReach.c ==========================================================*/ -extern int Aig_ManVerifyUsingBdds( Aig_Man_t * p, Saig_ParBbr_t * pPars ); -extern void Bbr_ManSetDefaultParams( Saig_ParBbr_t * p ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/proof/bbr/bbrCex.c b/src/proof/bbr/bbrCex.c deleted file mode 100644 index 31a46d61..00000000 --- a/src/proof/bbr/bbrCex.c +++ /dev/null @@ -1,172 +0,0 @@ -/**CFile**************************************************************** - - FileName [bbrCex.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD-based reachability analysis.] - - Synopsis [Procedures to derive a satisfiable counter-example.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: bbrCex.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "bbr.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern DdNode * Bbr_bddComputeRangeCube( DdManager * dd, int iStart, int iStop ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Derives the counter-example using the set of reached states.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Cex_t * Aig_ManVerifyUsingBddsCountExample( Aig_Man_t * p, DdManager * dd, - DdNode ** pbParts, Vec_Ptr_t * vOnionRings, DdNode * bCubeFirst, - int iOutput, int fVerbose, int fSilent ) -{ - Abc_Cex_t * pCex; - Aig_Obj_t * pObj; - Bbr_ImageTree_t * pTree; - DdNode * bCubeNs, * bState, * bImage; - DdNode * bTemp, * bVar, * bRing; - int i, v, RetValue, nPiOffset; - char * pValues; - abctime clk = Abc_Clock(); -//printf( "\nDeriving counter-example.\n" ); - - // allocate room for the counter-example - pCex = Abc_CexAlloc( Saig_ManRegNum(p), Saig_ManPiNum(p), Vec_PtrSize(vOnionRings)+1 ); - pCex->iFrame = Vec_PtrSize(vOnionRings); - pCex->iPo = iOutput; - nPiOffset = Saig_ManRegNum(p) + Saig_ManPiNum(p) * Vec_PtrSize(vOnionRings); - - // create the cube of NS variables - bCubeNs = Bbr_bddComputeRangeCube( dd, Saig_ManCiNum(p), Saig_ManCiNum(p)+Saig_ManRegNum(p) ); Cudd_Ref( bCubeNs ); - pTree = Bbr_bddImageStart( dd, bCubeNs, Saig_ManRegNum(p), pbParts, Saig_ManCiNum(p), dd->vars, 100000000, fVerbose ); - Cudd_RecursiveDeref( dd, bCubeNs ); - if ( pTree == NULL ) - { - if ( !fSilent ) - printf( "BDDs blew up during qualitification scheduling. " ); - return NULL; - } - - // allocate room for the cube - pValues = ABC_ALLOC( char, dd->size ); - - // get the last cube - RetValue = Cudd_bddPickOneCube( dd, bCubeFirst, pValues ); - assert( RetValue ); - - // write PIs of counter-example - Saig_ManForEachPi( p, pObj, i ) - if ( pValues[i] == 1 ) - Abc_InfoSetBit( pCex->pData, nPiOffset + i ); - nPiOffset -= Saig_ManPiNum(p); - - // write state in terms of NS variables - bState = (dd)->one; Cudd_Ref( bState ); - Saig_ManForEachLo( p, pObj, i ) - { - bVar = Cudd_NotCond( dd->vars[Saig_ManCiNum(p)+i], pValues[Saig_ManPiNum(p)+i] != 1 ); - bState = Cudd_bddAnd( dd, bTemp = bState, bVar ); Cudd_Ref( bState ); - Cudd_RecursiveDeref( dd, bTemp ); - } - - // perform backward analysis - Vec_PtrForEachEntryReverse( DdNode *, vOnionRings, bRing, v ) - { - // compute the next states - bImage = Bbr_bddImageCompute( pTree, bState ); - if ( bImage == NULL ) - { - Cudd_RecursiveDeref( dd, bState ); - if ( !fSilent ) - printf( "BDDs blew up during image computation. " ); - Bbr_bddImageTreeDelete( pTree ); - ABC_FREE( pValues ); - return NULL; - } - Cudd_Ref( bImage ); - Cudd_RecursiveDeref( dd, bState ); - - // intersect with the previous set - bImage = Cudd_bddAnd( dd, bTemp = bImage, bRing ); Cudd_Ref( bImage ); - Cudd_RecursiveDeref( dd, bTemp ); - - // find any assignment of the BDD - RetValue = Cudd_bddPickOneCube( dd, bImage, pValues ); - assert( RetValue ); - Cudd_RecursiveDeref( dd, bImage ); - - // write PIs of counter-example - Saig_ManForEachPi( p, pObj, i ) - if ( pValues[i] == 1 ) - Abc_InfoSetBit( pCex->pData, nPiOffset + i ); - nPiOffset -= Saig_ManPiNum(p); - - // check that we get the init state - if ( v == 0 ) - { - Saig_ManForEachLo( p, pObj, i ) - assert( pValues[Saig_ManPiNum(p)+i] == 0 ); - break; - } - - // write state in terms of NS variables - bState = (dd)->one; Cudd_Ref( bState ); - Saig_ManForEachLo( p, pObj, i ) - { - bVar = Cudd_NotCond( dd->vars[Saig_ManCiNum(p)+i], pValues[Saig_ManPiNum(p)+i] != 1 ); - bState = Cudd_bddAnd( dd, bTemp = bState, bVar ); Cudd_Ref( bState ); - Cudd_RecursiveDeref( dd, bTemp ); - } - } - // cleanup - Bbr_bddImageTreeDelete( pTree ); - ABC_FREE( pValues ); - // verify the counter example - if ( Vec_PtrSize(vOnionRings) < 1000 ) - { - RetValue = Saig_ManVerifyCex( p, pCex ); - if ( RetValue == 0 && !fSilent ) - printf( "Aig_ManVerifyUsingBdds(): Counter-example verification has FAILED.\n" ); - } - if ( fVerbose && !fSilent ) - { - ABC_PRT( "Counter-example generation time", Abc_Clock() - clk ); - } - return pCex; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/bbr/bbrImage.c b/src/proof/bbr/bbrImage.c deleted file mode 100644 index 1ff3d0b6..00000000 --- a/src/proof/bbr/bbrImage.c +++ /dev/null @@ -1,1327 +0,0 @@ -/**CFile**************************************************************** - - FileName [bbrImage.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD-based reachability analysis.] - - Synopsis [Performs image computation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: bbrImage.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "bbr.h" -#include "bdd/mtr/mtr.h" - -ABC_NAMESPACE_IMPL_START - - -/* - The ideas implemented in this file are inspired by the paper: - Pankaj Chauhan, Edmund Clarke, Somesh Jha, Jim Kukula, Tom Shiple, - Helmut Veith, Dong Wang. Non-linear Quantification Scheduling in - Image Computation. ICCAD, 2001. -*/ - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -typedef struct Bbr_ImageNode_t_ Bbr_ImageNode_t; -typedef struct Bbr_ImagePart_t_ Bbr_ImagePart_t; -typedef struct Bbr_ImageVar_t_ Bbr_ImageVar_t; - -struct Bbr_ImageTree_t_ -{ - Bbr_ImageNode_t * pRoot; // the root of quantification tree - Bbr_ImageNode_t * pCare; // the leaf node with the care set - DdNode * bCareSupp; // the cube to quantify from the care - int fVerbose; // the verbosity flag - int nNodesMax; // the max number of nodes in one iter - int nNodesMaxT; // the overall max number of nodes - int nIter; // the number of iterations with this tree - int nBddMax; // the number of node to stop -}; - -struct Bbr_ImageNode_t_ -{ - DdManager * dd; // the manager - DdNode * bCube; // the cube to quantify - DdNode * bImage; // the partial image - Bbr_ImageNode_t * pNode1; // the first branch - Bbr_ImageNode_t * pNode2; // the second branch - Bbr_ImagePart_t * pPart; // the partition (temporary) -}; - -struct Bbr_ImagePart_t_ -{ - DdNode * bFunc; // the partition - DdNode * bSupp; // the support of this partition - int nNodes; // the number of BDD nodes - short nSupp; // the number of support variables - short iPart; // the number of this partition -}; - -struct Bbr_ImageVar_t_ -{ - int iNum; // the BDD index of this variable - DdNode * bParts; // the partition numbers - int nParts; // the number of partitions -}; - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -#define b0 Cudd_Not((dd)->one) -#define b1 (dd)->one - -#ifndef ABC_PRB -#define ABC_PRB(dd,f) printf("%s = ", #f); Bbr_bddPrint(dd,f); printf("\n") -#endif - -/**AutomaticStart*************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static Bbr_ImagePart_t ** Bbr_CreateParts( DdManager * dd, - int nParts, DdNode ** pbParts, DdNode * bCare ); -static Bbr_ImageVar_t ** Bbr_CreateVars( DdManager * dd, - int nParts, Bbr_ImagePart_t ** pParts, - int nVars, DdNode ** pbVarsNs ); -static Bbr_ImageNode_t ** Bbr_CreateNodes( DdManager * dd, - int nParts, Bbr_ImagePart_t ** pParts, - int nVars, Bbr_ImageVar_t ** pVars ); -static void Bbr_DeleteParts_rec( Bbr_ImageNode_t * pNode ); -static int Bbr_BuildTreeNode( DdManager * dd, - int nNodes, Bbr_ImageNode_t ** pNodes, - int nVars, Bbr_ImageVar_t ** pVars, int * pfStop, int nBddMax ); -static Bbr_ImageNode_t * Bbr_MergeTopNodes( DdManager * dd, - int nNodes, Bbr_ImageNode_t ** pNodes ); -static void Bbr_bddImageTreeDelete_rec( Bbr_ImageNode_t * pNode ); -static int Bbr_bddImageCompute_rec( Bbr_ImageTree_t * pTree, Bbr_ImageNode_t * pNode ); -static int Bbr_FindBestVariable( DdManager * dd, - int nNodes, Bbr_ImageNode_t ** pNodes, - int nVars, Bbr_ImageVar_t ** pVars ); -static void Bbr_FindBestPartitions( DdManager * dd, DdNode * bParts, - int nNodes, Bbr_ImageNode_t ** pNodes, - int * piNode1, int * piNode2 ); -static Bbr_ImageNode_t * Bbr_CombineTwoNodes( DdManager * dd, DdNode * bCube, - Bbr_ImageNode_t * pNode1, Bbr_ImageNode_t * pNode2 ); - -static void Bbr_bddImagePrintLatchDependency( DdManager * dd, DdNode * bCare, - int nParts, DdNode ** pbParts, - int nVars, DdNode ** pbVars ); -static void Bbr_bddImagePrintLatchDependencyOne( DdManager * dd, DdNode * bFunc, - DdNode * bVarsCs, DdNode * bVarsNs, int iPart ); - -static void Bbr_bddImagePrintTree( Bbr_ImageTree_t * pTree ); -static void Bbr_bddImagePrintTree_rec( Bbr_ImageNode_t * pNode, int nOffset ); - -static void Bbr_bddPrint( DdManager * dd, DdNode * F ); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function************************************************************* - - Synopsis [Starts the image computation using tree-based scheduling.] - - Description [This procedure starts the image computation. It uses - the given care set to test-run the image computation and creates the - quantification tree by scheduling variable quantifications. The tree can - be used to compute images for other care sets without rescheduling. - In this case, Bbr_bddImageCompute() should be called.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bbr_ImageTree_t * Bbr_bddImageStart( - DdManager * dd, DdNode * bCare, // the care set - int nParts, DdNode ** pbParts, // the partitions for image computation - int nVars, DdNode ** pbVars, int nBddMax, int fVerbose ) // the NS and parameter variables (not quantified!) -{ - Bbr_ImageTree_t * pTree; - Bbr_ImagePart_t ** pParts; - Bbr_ImageVar_t ** pVars; - Bbr_ImageNode_t ** pNodes, * pCare; - int fStop, v; - - if ( fVerbose && dd->size <= 80 ) - Bbr_bddImagePrintLatchDependency( dd, bCare, nParts, pbParts, nVars, pbVars ); - - // create variables, partitions and leaf nodes - pParts = Bbr_CreateParts( dd, nParts, pbParts, bCare ); - pVars = Bbr_CreateVars( dd, nParts + 1, pParts, nVars, pbVars ); - pNodes = Bbr_CreateNodes( dd, nParts + 1, pParts, dd->size, pVars ); - pCare = pNodes[nParts]; - - // process the nodes - while ( Bbr_BuildTreeNode( dd, nParts + 1, pNodes, dd->size, pVars, &fStop, nBddMax ) ); - - // consider the case of BDD node blowup - if ( fStop ) - { - for ( v = 0; v < dd->size; v++ ) - if ( pVars[v] ) - ABC_FREE( pVars[v] ); - ABC_FREE( pVars ); - for ( v = 0; v <= nParts; v++ ) - if ( pNodes[v] ) - { - Bbr_DeleteParts_rec( pNodes[v] ); - Bbr_bddImageTreeDelete_rec( pNodes[v] ); - } - ABC_FREE( pNodes ); - ABC_FREE( pParts ); - return NULL; - } - - // make sure the variables are gone - for ( v = 0; v < dd->size; v++ ) - assert( pVars[v] == NULL ); - ABC_FREE( pVars ); - - // create the tree - pTree = ABC_ALLOC( Bbr_ImageTree_t, 1 ); - memset( pTree, 0, sizeof(Bbr_ImageTree_t) ); - pTree->pCare = pCare; - pTree->nBddMax = nBddMax; - pTree->fVerbose = fVerbose; - - // merge the topmost nodes - while ( (pTree->pRoot = Bbr_MergeTopNodes( dd, nParts + 1, pNodes )) == NULL ); - - // make sure the nodes are gone - for ( v = 0; v < nParts + 1; v++ ) - assert( pNodes[v] == NULL ); - ABC_FREE( pNodes ); - -// if ( fVerbose ) -// Bbr_bddImagePrintTree( pTree ); - - // set the support of the care set - pTree->bCareSupp = Cudd_Support( dd, bCare ); Cudd_Ref( pTree->bCareSupp ); - - // clean the partitions - Bbr_DeleteParts_rec( pTree->pRoot ); - ABC_FREE( pParts ); - - return pTree; -} - -/**Function************************************************************* - - Synopsis [Compute the image.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Bbr_bddImageCompute( Bbr_ImageTree_t * pTree, DdNode * bCare ) -{ - DdManager * dd = pTree->pCare->dd; - DdNode * bSupp, * bRem; - - pTree->nIter++; - - // make sure the supports are okay - bSupp = Cudd_Support( dd, bCare ); Cudd_Ref( bSupp ); - if ( bSupp != pTree->bCareSupp ) - { - bRem = Cudd_bddExistAbstract( dd, bSupp, pTree->bCareSupp ); Cudd_Ref( bRem ); - if ( bRem != b1 ) - { -printf( "Original care set support: " ); -ABC_PRB( dd, pTree->bCareSupp ); -printf( "Current care set support: " ); -ABC_PRB( dd, bSupp ); - Cudd_RecursiveDeref( dd, bSupp ); - Cudd_RecursiveDeref( dd, bRem ); - printf( "The care set depends on some vars that were not in the care set during scheduling.\n" ); - return NULL; - } - Cudd_RecursiveDeref( dd, bRem ); - } - Cudd_RecursiveDeref( dd, bSupp ); - - // remove the previous image - Cudd_RecursiveDeref( dd, pTree->pCare->bImage ); - pTree->pCare->bImage = bCare; Cudd_Ref( bCare ); - - // compute the image - pTree->nNodesMax = 0; - if ( !Bbr_bddImageCompute_rec( pTree, pTree->pRoot ) ) - return NULL; - if ( pTree->nNodesMaxT < pTree->nNodesMax ) - pTree->nNodesMaxT = pTree->nNodesMax; - -// if ( pTree->fVerbose ) -// printf( "Iter %2d : Max nodes = %5d.\n", pTree->nIter, pTree->nNodesMax ); - return pTree->pRoot->bImage; -} - -/**Function************************************************************* - - Synopsis [Delete the tree.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbr_bddImageTreeDelete( Bbr_ImageTree_t * pTree ) -{ - if ( pTree->bCareSupp ) - Cudd_RecursiveDeref( pTree->pRoot->dd, pTree->bCareSupp ); - Bbr_bddImageTreeDelete_rec( pTree->pRoot ); - ABC_FREE( pTree ); -} - -/**Function************************************************************* - - Synopsis [Reads the image from the tree.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Bbr_bddImageRead( Bbr_ImageTree_t * pTree ) -{ - return pTree->pRoot->bImage; -} - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Outputs the BDD in a readable format.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void Bbr_bddPrint( DdManager * dd, DdNode * F ) -{ - DdGen * Gen; - int * Cube; - CUDD_VALUE_TYPE Value; - int nVars = dd->size; - int fFirstCube = 1; - int i; - - if ( F == NULL ) - { - printf("NULL"); - return; - } - if ( F == b0 ) - { - printf("Constant 0"); - return; - } - if ( F == b1 ) - { - printf("Constant 1"); - return; - } - - Cudd_ForeachCube( dd, F, Gen, Cube, Value ) - { - if ( fFirstCube ) - fFirstCube = 0; - else -// Output << " + "; - printf( " + " ); - - for ( i = 0; i < nVars; i++ ) - if ( Cube[i] == 0 ) - printf( "[%d]'", i ); -// printf( "%c'", (char)('a'+i) ); - else if ( Cube[i] == 1 ) - printf( "[%d]", i ); -// printf( "%c", (char)('a'+i) ); - } - -// printf("\n"); -} - -/*---------------------------------------------------------------------------*/ -/* Definition of static Functions */ -/*---------------------------------------------------------------------------*/ - -/**Function************************************************************* - - Synopsis [Creates partitions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bbr_ImagePart_t ** Bbr_CreateParts( DdManager * dd, - int nParts, DdNode ** pbParts, DdNode * bCare ) -{ - Bbr_ImagePart_t ** pParts; - int i; - - // start the partitions - pParts = ABC_ALLOC( Bbr_ImagePart_t *, nParts + 1 ); - // create structures for each variable - for ( i = 0; i < nParts; i++ ) - { - pParts[i] = ABC_ALLOC( Bbr_ImagePart_t, 1 ); - pParts[i]->bFunc = pbParts[i]; Cudd_Ref( pParts[i]->bFunc ); - pParts[i]->bSupp = Cudd_Support( dd, pParts[i]->bFunc ); Cudd_Ref( pParts[i]->bSupp ); - pParts[i]->nSupp = Cudd_SupportSize( dd, pParts[i]->bSupp ); - pParts[i]->nNodes = Cudd_DagSize( pParts[i]->bFunc ); - pParts[i]->iPart = i; - } - // add the care set as the last partition - pParts[nParts] = ABC_ALLOC( Bbr_ImagePart_t, 1 ); - pParts[nParts]->bFunc = bCare; Cudd_Ref( pParts[nParts]->bFunc ); - pParts[nParts]->bSupp = Cudd_Support( dd, pParts[nParts]->bFunc ); Cudd_Ref( pParts[nParts]->bSupp ); - pParts[nParts]->nSupp = Cudd_SupportSize( dd, pParts[nParts]->bSupp ); - pParts[nParts]->nNodes = Cudd_DagSize( pParts[nParts]->bFunc ); - pParts[nParts]->iPart = nParts; - return pParts; -} - -/**Function************************************************************* - - Synopsis [Creates variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bbr_ImageVar_t ** Bbr_CreateVars( DdManager * dd, - int nParts, Bbr_ImagePart_t ** pParts, - int nVars, DdNode ** pbVars ) -{ - Bbr_ImageVar_t ** pVars; - DdNode ** pbFuncs; - DdNode * bCubeNs, * bSupp, * bParts, * bTemp, * bSuppTemp; - int nVarsTotal, iVar, p, Counter; - - // put all the functions into one array - pbFuncs = ABC_ALLOC( DdNode *, nParts ); - for ( p = 0; p < nParts; p++ ) - pbFuncs[p] = pParts[p]->bSupp; - bSupp = Cudd_VectorSupport( dd, pbFuncs, nParts ); Cudd_Ref( bSupp ); - ABC_FREE( pbFuncs ); - - // remove the NS vars - bCubeNs = Cudd_bddComputeCube( dd, pbVars, NULL, nVars ); Cudd_Ref( bCubeNs ); - bSupp = Cudd_bddExistAbstract( dd, bTemp = bSupp, bCubeNs ); Cudd_Ref( bSupp ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bCubeNs ); - - // get the number of I and CS variables to be quantified - nVarsTotal = Cudd_SupportSize( dd, bSupp ); - - // start the variables - pVars = ABC_ALLOC( Bbr_ImageVar_t *, dd->size ); - memset( pVars, 0, sizeof(Bbr_ImageVar_t *) * dd->size ); - // create structures for each variable - for ( bSuppTemp = bSupp; bSuppTemp != b1; bSuppTemp = cuddT(bSuppTemp) ) - { - iVar = bSuppTemp->index; - pVars[iVar] = ABC_ALLOC( Bbr_ImageVar_t, 1 ); - pVars[iVar]->iNum = iVar; - // collect all the parts this var belongs to - Counter = 0; - bParts = b1; Cudd_Ref( bParts ); - for ( p = 0; p < nParts; p++ ) - if ( Cudd_bddLeq( dd, pParts[p]->bSupp, dd->vars[bSuppTemp->index] ) ) - { - bParts = Cudd_bddAnd( dd, bTemp = bParts, dd->vars[p] ); Cudd_Ref( bParts ); - Cudd_RecursiveDeref( dd, bTemp ); - Counter++; - } - pVars[iVar]->bParts = bParts; // takes ref - pVars[iVar]->nParts = Counter; - } - Cudd_RecursiveDeref( dd, bSupp ); - return pVars; -} - -/**Function************************************************************* - - Synopsis [Creates variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bbr_ImageNode_t ** Bbr_CreateNodes( DdManager * dd, - int nParts, Bbr_ImagePart_t ** pParts, - int nVars, Bbr_ImageVar_t ** pVars ) -{ - Bbr_ImageNode_t ** pNodes; - Bbr_ImageNode_t * pNode; - DdNode * bTemp; - int i, v, iPart; -/* - DdManager * dd; // the manager - DdNode * bCube; // the cube to quantify - DdNode * bImage; // the partial image - Bbr_ImageNode_t * pNode1; // the first branch - Bbr_ImageNode_t * pNode2; // the second branch - Bbr_ImagePart_t * pPart; // the partition (temporary) -*/ - // start the partitions - pNodes = ABC_ALLOC( Bbr_ImageNode_t *, nParts ); - // create structures for each leaf nodes - for ( i = 0; i < nParts; i++ ) - { - pNodes[i] = ABC_ALLOC( Bbr_ImageNode_t, 1 ); - memset( pNodes[i], 0, sizeof(Bbr_ImageNode_t) ); - pNodes[i]->dd = dd; - pNodes[i]->pPart = pParts[i]; - } - // find the quantification cubes for each leaf node - for ( v = 0; v < nVars; v++ ) - { - if ( pVars[v] == NULL ) - continue; - assert( pVars[v]->nParts > 0 ); - if ( pVars[v]->nParts > 1 ) - continue; - iPart = pVars[v]->bParts->index; - if ( pNodes[iPart]->bCube == NULL ) - { - pNodes[iPart]->bCube = dd->vars[v]; - Cudd_Ref( dd->vars[v] ); - } - else - { - pNodes[iPart]->bCube = Cudd_bddAnd( dd, bTemp = pNodes[iPart]->bCube, dd->vars[v] ); - Cudd_Ref( pNodes[iPart]->bCube ); - Cudd_RecursiveDeref( dd, bTemp ); - } - // remove these variables - Cudd_RecursiveDeref( dd, pVars[v]->bParts ); - ABC_FREE( pVars[v] ); - } - - // assign the leaf node images - for ( i = 0; i < nParts; i++ ) - { - pNode = pNodes[i]; - if ( pNode->bCube ) - { - // update the partition - pParts[i]->bFunc = Cudd_bddExistAbstract( dd, bTemp = pParts[i]->bFunc, pNode->bCube ); - Cudd_Ref( pParts[i]->bFunc ); - Cudd_RecursiveDeref( dd, bTemp ); - // update the support the partition - pParts[i]->bSupp = Cudd_bddExistAbstract( dd, bTemp = pParts[i]->bSupp, pNode->bCube ); - Cudd_Ref( pParts[i]->bSupp ); - Cudd_RecursiveDeref( dd, bTemp ); - // update the numbers - pParts[i]->nSupp = Cudd_SupportSize( dd, pParts[i]->bSupp ); - pParts[i]->nNodes = Cudd_DagSize( pParts[i]->bFunc ); - // get rid of the cube - // save the last (care set) quantification cube - if ( i < nParts - 1 ) - { - Cudd_RecursiveDeref( dd, pNode->bCube ); - pNode->bCube = NULL; - } - } - // copy the function - pNode->bImage = pParts[i]->bFunc; Cudd_Ref( pNode->bImage ); - } -/* - for ( i = 0; i < nParts; i++ ) - { - pNode = pNodes[i]; -ABC_PRB( dd, pNode->bCube ); -ABC_PRB( dd, pNode->pPart->bFunc ); -ABC_PRB( dd, pNode->pPart->bSupp ); -printf( "\n" ); - } -*/ - return pNodes; -} - - -/**Function************************************************************* - - Synopsis [Delete the partitions from the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbr_DeleteParts_rec( Bbr_ImageNode_t * pNode ) -{ - Bbr_ImagePart_t * pPart; - if ( pNode->pNode1 ) - Bbr_DeleteParts_rec( pNode->pNode1 ); - if ( pNode->pNode2 ) - Bbr_DeleteParts_rec( pNode->pNode2 ); - pPart = pNode->pPart; - Cudd_RecursiveDeref( pNode->dd, pPart->bFunc ); - Cudd_RecursiveDeref( pNode->dd, pPart->bSupp ); - ABC_FREE( pNode->pPart ); -} - -/**Function************************************************************* - - Synopsis [Delete the partitions from the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbr_bddImageTreeDelete_rec( Bbr_ImageNode_t * pNode ) -{ - if ( pNode->pNode1 ) - Bbr_bddImageTreeDelete_rec( pNode->pNode1 ); - if ( pNode->pNode2 ) - Bbr_bddImageTreeDelete_rec( pNode->pNode2 ); - if ( pNode->bCube ) - Cudd_RecursiveDeref( pNode->dd, pNode->bCube ); - if ( pNode->bImage ) - Cudd_RecursiveDeref( pNode->dd, pNode->bImage ); - assert( pNode->pPart == NULL ); - ABC_FREE( pNode ); -} - -/**Function************************************************************* - - Synopsis [Recompute the image.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Bbr_bddImageCompute_rec( Bbr_ImageTree_t * pTree, Bbr_ImageNode_t * pNode ) -{ - DdManager * dd = pNode->dd; - DdNode * bTemp; - int nNodes; - - // trivial case - if ( pNode->pNode1 == NULL ) - { - if ( pNode->bCube ) - { - pNode->bImage = Cudd_bddExistAbstract( dd, bTemp = pNode->bImage, pNode->bCube ); - Cudd_Ref( pNode->bImage ); - Cudd_RecursiveDeref( dd, bTemp ); - } - return 1; - } - - // compute the children - if ( pNode->pNode1 ) - if ( !Bbr_bddImageCompute_rec( pTree, pNode->pNode1 ) ) - return 0; - if ( pNode->pNode2 ) - if ( !Bbr_bddImageCompute_rec( pTree, pNode->pNode2 ) ) - return 0; - - // clean the old image - if ( pNode->bImage ) - Cudd_RecursiveDeref( dd, pNode->bImage ); - pNode->bImage = NULL; - - // compute the new image - if ( pNode->bCube ) - pNode->bImage = Cudd_bddAndAbstract( dd, - pNode->pNode1->bImage, pNode->pNode2->bImage, pNode->bCube ); - else - pNode->bImage = Cudd_bddAnd( dd, pNode->pNode1->bImage, pNode->pNode2->bImage ); - Cudd_Ref( pNode->bImage ); - - if ( pTree->fVerbose ) - { - nNodes = Cudd_DagSize( pNode->bImage ); - if ( pTree->nNodesMax < nNodes ) - pTree->nNodesMax = nNodes; - } - if ( dd->keys-dd->dead > (unsigned)pTree->nBddMax ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Builds the tree.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Bbr_BuildTreeNode( DdManager * dd, - int nNodes, Bbr_ImageNode_t ** pNodes, - int nVars, Bbr_ImageVar_t ** pVars, int * pfStop, int nBddMax ) -{ - Bbr_ImageNode_t * pNode1, * pNode2; - Bbr_ImageVar_t * pVar; - Bbr_ImageNode_t * pNode; - DdNode * bCube, * bTemp, * bSuppTemp;//, * bParts; - int iNode1, iNode2; - int iVarBest, nSupp, v; - - // find the best variable - iVarBest = Bbr_FindBestVariable( dd, nNodes, pNodes, nVars, pVars ); - if ( iVarBest == -1 ) - return 0; -/* -for ( v = 0; v < nVars; v++ ) -{ - DdNode * bSupp; - if ( pVars[v] == NULL ) - continue; - printf( "%3d :", v ); - printf( "%3d ", pVars[v]->nParts ); - bSupp = Cudd_Support( dd, pVars[v]->bParts ); Cudd_Ref( bSupp ); - Bbr_bddPrint( dd, bSupp ); printf( "\n" ); - Cudd_RecursiveDeref( dd, bSupp ); -} -*/ - pVar = pVars[iVarBest]; - - // this var cannot appear in one partition only - nSupp = Cudd_SupportSize( dd, pVar->bParts ); - assert( nSupp == pVar->nParts ); - assert( nSupp != 1 ); -//printf( "var = %d supp = %d\n\n", iVarBest, nSupp ); - - // if it appears in only two partitions, quantify it - if ( pVar->nParts == 2 ) - { - // get the nodes - iNode1 = pVar->bParts->index; - iNode2 = cuddT(pVar->bParts)->index; - pNode1 = pNodes[iNode1]; - pNode2 = pNodes[iNode2]; - - // get the quantification cube - bCube = dd->vars[pVar->iNum]; Cudd_Ref( bCube ); - // add the variables that appear only in these partitions - for ( v = 0; v < nVars; v++ ) - if ( pVars[v] && v != iVarBest && pVars[v]->bParts == pVars[iVarBest]->bParts ) - { - // add this var - bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[pVars[v]->iNum] ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( dd, bTemp ); - // clean this var - Cudd_RecursiveDeref( dd, pVars[v]->bParts ); - ABC_FREE( pVars[v] ); - } - // clean the best var - Cudd_RecursiveDeref( dd, pVars[iVarBest]->bParts ); - ABC_FREE( pVars[iVarBest] ); - - // combines two nodes - pNode = Bbr_CombineTwoNodes( dd, bCube, pNode1, pNode2 ); - Cudd_RecursiveDeref( dd, bCube ); - } - else // if ( pVar->nParts > 2 ) - { - // find two smallest BDDs that have this var - Bbr_FindBestPartitions( dd, pVar->bParts, nNodes, pNodes, &iNode1, &iNode2 ); - pNode1 = pNodes[iNode1]; - pNode2 = pNodes[iNode2]; -//printf( "smallest bdds with this var: %d %d\n", iNode1, iNode2 ); -/* - // it is not possible that a var appears only in these two - // otherwise, it would have a different cost - bParts = Cudd_bddAnd( dd, dd->vars[iNode1], dd->vars[iNode2] ); Cudd_Ref( bParts ); - for ( v = 0; v < nVars; v++ ) - if ( pVars[v] && pVars[v]->bParts == bParts ) - assert( 0 ); - Cudd_RecursiveDeref( dd, bParts ); -*/ - // combines two nodes - pNode = Bbr_CombineTwoNodes( dd, b1, pNode1, pNode2 ); - } - - // clean the old nodes - pNodes[iNode1] = pNode; - pNodes[iNode2] = NULL; -//printf( "Removing node %d (leaving node %d)\n", iNode2, iNode1 ); - - // update the variables that appear in pNode[iNode2] - for ( bSuppTemp = pNode2->pPart->bSupp; bSuppTemp != b1; bSuppTemp = cuddT(bSuppTemp) ) - { - pVar = pVars[bSuppTemp->index]; - if ( pVar == NULL ) // this variable is not be quantified - continue; - // quantify this var - assert( Cudd_bddLeq( dd, pVar->bParts, dd->vars[iNode2] ) ); - pVar->bParts = Cudd_bddExistAbstract( dd, bTemp = pVar->bParts, dd->vars[iNode2] ); Cudd_Ref( pVar->bParts ); - Cudd_RecursiveDeref( dd, bTemp ); - // add the new var - pVar->bParts = Cudd_bddAnd( dd, bTemp = pVar->bParts, dd->vars[iNode1] ); Cudd_Ref( pVar->bParts ); - Cudd_RecursiveDeref( dd, bTemp ); - // update the score - pVar->nParts = Cudd_SupportSize( dd, pVar->bParts ); - } - - *pfStop = 0; - if ( dd->keys-dd->dead > (unsigned)nBddMax ) - { - *pfStop = 1; - return 0; - } - return 1; -} - - -/**Function************************************************************* - - Synopsis [Merges the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bbr_ImageNode_t * Bbr_MergeTopNodes( - DdManager * dd, int nNodes, Bbr_ImageNode_t ** pNodes ) -{ - Bbr_ImageNode_t * pNode; - int n1 = -1, n2 = -1, n; - - // find the first and the second non-empty spots - for ( n = 0; n < nNodes; n++ ) - if ( pNodes[n] ) - { - if ( n1 == -1 ) - n1 = n; - else if ( n2 == -1 ) - { - n2 = n; - break; - } - } - assert( n1 != -1 ); - // check the situation when only one such node is detected - if ( n2 == -1 ) - { - // save the node - pNode = pNodes[n1]; - // clean the node - pNodes[n1] = NULL; - return pNode; - } - - // combines two nodes - pNode = Bbr_CombineTwoNodes( dd, b1, pNodes[n1], pNodes[n2] ); - - // clean the old nodes - pNodes[n1] = pNode; - pNodes[n2] = NULL; - return NULL; -} - -/**Function************************************************************* - - Synopsis [Merges two nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bbr_ImageNode_t * Bbr_CombineTwoNodes( DdManager * dd, DdNode * bCube, - Bbr_ImageNode_t * pNode1, Bbr_ImageNode_t * pNode2 ) -{ - Bbr_ImageNode_t * pNode; - Bbr_ImagePart_t * pPart; - - // create a new partition - pPart = ABC_ALLOC( Bbr_ImagePart_t, 1 ); - memset( pPart, 0, sizeof(Bbr_ImagePart_t) ); - // create the function - pPart->bFunc = Cudd_bddAndAbstract( dd, pNode1->pPart->bFunc, pNode2->pPart->bFunc, bCube ); - Cudd_Ref( pPart->bFunc ); - // update the support the partition - pPart->bSupp = Cudd_bddAndAbstract( dd, pNode1->pPart->bSupp, pNode2->pPart->bSupp, bCube ); - Cudd_Ref( pPart->bSupp ); - // update the numbers - pPart->nSupp = Cudd_SupportSize( dd, pPart->bSupp ); - pPart->nNodes = Cudd_DagSize( pPart->bFunc ); - pPart->iPart = -1; -/* -ABC_PRB( dd, pNode1->pPart->bSupp ); -ABC_PRB( dd, pNode2->pPart->bSupp ); -ABC_PRB( dd, pPart->bSupp ); -*/ - // create a new node - pNode = ABC_ALLOC( Bbr_ImageNode_t, 1 ); - memset( pNode, 0, sizeof(Bbr_ImageNode_t) ); - pNode->dd = dd; - pNode->pPart = pPart; - pNode->pNode1 = pNode1; - pNode->pNode2 = pNode2; - // compute the image - pNode->bImage = Cudd_bddAndAbstract( dd, pNode1->bImage, pNode2->bImage, bCube ); - Cudd_Ref( pNode->bImage ); - // save the cube - if ( bCube != b1 ) - { - pNode->bCube = bCube; Cudd_Ref( bCube ); - } - return pNode; -} - -/**Function************************************************************* - - Synopsis [Computes the best variable.] - - Description [The variables is the best if the sum of squares of the - BDD sizes of the partitions, in which it participates, is the minimum.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Bbr_FindBestVariable( DdManager * dd, - int nNodes, Bbr_ImageNode_t ** pNodes, - int nVars, Bbr_ImageVar_t ** pVars ) -{ - DdNode * bTemp; - int iVarBest, v; - double CostBest, CostCur; - - CostBest = 100000000000000.0; - iVarBest = -1; - - // check if there are two-variable partitions - for ( v = 0; v < nVars; v++ ) - if ( pVars[v] && pVars[v]->nParts == 2 ) - { - CostCur = 0; - for ( bTemp = pVars[v]->bParts; bTemp != b1; bTemp = cuddT(bTemp) ) - CostCur += pNodes[bTemp->index]->pPart->nNodes * - pNodes[bTemp->index]->pPart->nNodes; - if ( CostBest > CostCur ) - { - CostBest = CostCur; - iVarBest = v; - } - } - if ( iVarBest >= 0 ) - return iVarBest; - - // find other partition - for ( v = 0; v < nVars; v++ ) - if ( pVars[v] ) - { - assert( pVars[v]->nParts > 1 ); - CostCur = 0; - for ( bTemp = pVars[v]->bParts; bTemp != b1; bTemp = cuddT(bTemp) ) - CostCur += pNodes[bTemp->index]->pPart->nNodes * - pNodes[bTemp->index]->pPart->nNodes; - if ( CostBest > CostCur ) - { - CostBest = CostCur; - iVarBest = v; - } - } - return iVarBest; -} - -/**Function************************************************************* - - Synopsis [Computes two smallest partions that have this var.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbr_FindBestPartitions( DdManager * dd, DdNode * bParts, - int nNodes, Bbr_ImageNode_t ** pNodes, - int * piNode1, int * piNode2 ) -{ - DdNode * bTemp; - int iPart1, iPart2; - int CostMin1, CostMin2, Cost; - - // go through the partitions - iPart1 = iPart2 = -1; - CostMin1 = CostMin2 = 1000000; - for ( bTemp = bParts; bTemp != b1; bTemp = cuddT(bTemp) ) - { - Cost = pNodes[bTemp->index]->pPart->nNodes; - if ( CostMin1 > Cost ) - { - CostMin2 = CostMin1; iPart2 = iPart1; - CostMin1 = Cost; iPart1 = bTemp->index; - } - else if ( CostMin2 > Cost ) - { - CostMin2 = Cost; iPart2 = bTemp->index; - } - } - - *piNode1 = iPart1; - *piNode2 = iPart2; -} - -/**Function************************************************************* - - Synopsis [Prints the latch dependency matrix.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbr_bddImagePrintLatchDependency( - DdManager * dd, DdNode * bCare, // the care set - int nParts, DdNode ** pbParts, // the partitions for image computation - int nVars, DdNode ** pbVars ) // the NS and parameter variables (not quantified!) -{ - int i; - DdNode * bVarsCs, * bVarsNs; - - bVarsCs = Cudd_Support( dd, bCare ); Cudd_Ref( bVarsCs ); - bVarsNs = Cudd_bddComputeCube( dd, pbVars, NULL, nVars ); Cudd_Ref( bVarsNs ); - - printf( "The latch dependency matrix:\n" ); - printf( "Partitions = %d Variables: total = %d non-quantifiable = %d\n", - nParts, dd->size, nVars ); - printf( " : " ); - for ( i = 0; i < dd->size; i++ ) - printf( "%d", i % 10 ); - printf( "\n" ); - - for ( i = 0; i < nParts; i++ ) - Bbr_bddImagePrintLatchDependencyOne( dd, pbParts[i], bVarsCs, bVarsNs, i ); - Bbr_bddImagePrintLatchDependencyOne( dd, bCare, bVarsCs, bVarsNs, nParts ); - - Cudd_RecursiveDeref( dd, bVarsCs ); - Cudd_RecursiveDeref( dd, bVarsNs ); -} - -/**Function************************************************************* - - Synopsis [Prints one row of the latch dependency matrix.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbr_bddImagePrintLatchDependencyOne( - DdManager * dd, DdNode * bFunc, // the function - DdNode * bVarsCs, DdNode * bVarsNs, // the current/next state vars - int iPart ) -{ - DdNode * bSupport; - int v; - bSupport = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupport ); - printf( " %3d : ", iPart ); - for ( v = 0; v < dd->size; v++ ) - { - if ( Cudd_bddLeq( dd, bSupport, dd->vars[v] ) ) - { - if ( Cudd_bddLeq( dd, bVarsCs, dd->vars[v] ) ) - printf( "c" ); - else if ( Cudd_bddLeq( dd, bVarsNs, dd->vars[v] ) ) - printf( "n" ); - else - printf( "i" ); - } - else - printf( "." ); - } - printf( "\n" ); - Cudd_RecursiveDeref( dd, bSupport ); -} - - -/**Function************************************************************* - - Synopsis [Prints the tree for quenstification scheduling.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbr_bddImagePrintTree( Bbr_ImageTree_t * pTree ) -{ - printf( "The quantification scheduling tree:\n" ); - Bbr_bddImagePrintTree_rec( pTree->pRoot, 1 ); -} - -/**Function************************************************************* - - Synopsis [Prints the tree for quenstification scheduling.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbr_bddImagePrintTree_rec( Bbr_ImageNode_t * pNode, int Offset ) -{ - DdNode * Cube; - int i; - - Cube = pNode->bCube; - - if ( pNode->pNode1 == NULL ) - { - printf( "<%d> ", pNode->pPart->iPart ); - if ( Cube != NULL ) - { - ABC_PRB( pNode->dd, Cube ); - } - else - printf( "\n" ); - return; - } - - printf( "<*> " ); - if ( Cube != NULL ) - { - ABC_PRB( pNode->dd, Cube ); - } - else - printf( "\n" ); - - for ( i = 0; i < Offset; i++ ) - printf( " " ); - Bbr_bddImagePrintTree_rec( pNode->pNode1, Offset + 1 ); - - for ( i = 0; i < Offset; i++ ) - printf( " " ); - Bbr_bddImagePrintTree_rec( pNode->pNode2, Offset + 1 ); -} - -/**Function******************************************************************** - - Synopsis [Computes the positive polarty cube composed of the first vars in the array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Bbr_bddComputeCube( DdManager * dd, DdNode ** bXVars, int nVars ) -{ - DdNode * bRes; - DdNode * bTemp; - int i; - - bRes = b1; Cudd_Ref( bRes ); - for ( i = 0; i < nVars; i++ ) - { - bRes = Cudd_bddAnd( dd, bTemp = bRes, bXVars[i] ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - } - - Cudd_Deref( bRes ); - return bRes; -} - - - - - -struct Bbr_ImageTree2_t_ -{ - DdManager * dd; - DdNode * bRel; - DdNode * bCube; - DdNode * bImage; -}; - -/**Function************************************************************* - - Synopsis [Starts the monolithic image computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bbr_ImageTree2_t * Bbr_bddImageStart2( - DdManager * dd, DdNode * bCare, - int nParts, DdNode ** pbParts, - int nVars, DdNode ** pbVars, int fVerbose ) -{ - Bbr_ImageTree2_t * pTree; - DdNode * bCubeAll, * bCubeNot, * bTemp; - int i; - - pTree = ABC_ALLOC( Bbr_ImageTree2_t, 1 ); - pTree->dd = dd; - pTree->bImage = NULL; - - bCubeAll = Bbr_bddComputeCube( dd, dd->vars, dd->size ); Cudd_Ref( bCubeAll ); - bCubeNot = Bbr_bddComputeCube( dd, pbVars, nVars ); Cudd_Ref( bCubeNot ); - pTree->bCube = Cudd_bddExistAbstract( dd, bCubeAll, bCubeNot ); Cudd_Ref( pTree->bCube ); - Cudd_RecursiveDeref( dd, bCubeAll ); - Cudd_RecursiveDeref( dd, bCubeNot ); - - // derive the monolithic relation - pTree->bRel = b1; Cudd_Ref( pTree->bRel ); - for ( i = 0; i < nParts; i++ ) - { - pTree->bRel = Cudd_bddAnd( dd, bTemp = pTree->bRel, pbParts[i] ); Cudd_Ref( pTree->bRel ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Bbr_bddImageCompute2( pTree, bCare ); - return pTree; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Bbr_bddImageCompute2( Bbr_ImageTree2_t * pTree, DdNode * bCare ) -{ - if ( pTree->bImage ) - Cudd_RecursiveDeref( pTree->dd, pTree->bImage ); - pTree->bImage = Cudd_bddAndAbstract( pTree->dd, pTree->bRel, bCare, pTree->bCube ); - Cudd_Ref( pTree->bImage ); - return pTree->bImage; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbr_bddImageTreeDelete2( Bbr_ImageTree2_t * pTree ) -{ - if ( pTree->bRel ) - Cudd_RecursiveDeref( pTree->dd, pTree->bRel ); - if ( pTree->bCube ) - Cudd_RecursiveDeref( pTree->dd, pTree->bCube ); - if ( pTree->bImage ) - Cudd_RecursiveDeref( pTree->dd, pTree->bImage ); - ABC_FREE( pTree ); -} - -/**Function************************************************************* - - Synopsis [Returns the previously computed image.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Bbr_bddImageRead2( Bbr_ImageTree2_t * pTree ) -{ - return pTree->bImage; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/bbr/bbrNtbdd.c b/src/proof/bbr/bbrNtbdd.c deleted file mode 100644 index f61c3d73..00000000 --- a/src/proof/bbr/bbrNtbdd.c +++ /dev/null @@ -1,218 +0,0 @@ -/**CFile**************************************************************** - - FileName [bbrNtbdd.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD-based reachability analysis.] - - Synopsis [Procedures to construct global BDDs for the network.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: bbrNtbdd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "bbr.h" -//#include "bar.h" - -ABC_NAMESPACE_IMPL_START - - -typedef char ProgressBar; - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline void Aig_ObjSetGlobalBdd( Aig_Obj_t * pObj, DdNode * bFunc ) { pObj->pData = bFunc; } -static inline void Aig_ObjCleanGlobalBdd( DdManager * dd, Aig_Obj_t * pObj ) { Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); pObj->pData = NULL; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Derives the global BDD for one AIG node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Bbr_NodeGlobalBdds_rec( DdManager * dd, Aig_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose ) -{ - DdNode * bFunc, * bFunc0, * bFunc1; - assert( !Aig_IsComplement(pNode) ); - if ( Cudd_ReadKeys(dd)-Cudd_ReadDead(dd) > (unsigned)nBddSizeMax ) - { -// Extra_ProgressBarStop( pProgress ); - if ( fVerbose ) - printf( "The number of live nodes reached %d.\n", nBddSizeMax ); - fflush( stdout ); - return NULL; - } - // if the result is available return - if ( Aig_ObjGlobalBdd(pNode) == NULL ) - { - // compute the result for both branches - bFunc0 = Bbr_NodeGlobalBdds_rec( dd, Aig_ObjFanin0(pNode), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); - if ( bFunc0 == NULL ) - return NULL; - Cudd_Ref( bFunc0 ); - bFunc1 = Bbr_NodeGlobalBdds_rec( dd, Aig_ObjFanin1(pNode), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); - if ( bFunc1 == NULL ) - return NULL; - Cudd_Ref( bFunc1 ); - bFunc0 = Cudd_NotCond( bFunc0, Aig_ObjFaninC0(pNode) ); - bFunc1 = Cudd_NotCond( bFunc1, Aig_ObjFaninC1(pNode) ); - // get the final result - bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bFunc0 ); - Cudd_RecursiveDeref( dd, bFunc1 ); - // add the number of used nodes - (*pCounter)++; - // set the result - assert( Aig_ObjGlobalBdd(pNode) == NULL ); - Aig_ObjSetGlobalBdd( pNode, bFunc ); - // increment the progress bar -// if ( pProgress ) -// Extra_ProgressBarUpdate( pProgress, *pCounter, NULL ); - } - // prepare the return value - bFunc = Aig_ObjGlobalBdd(pNode); - // dereference BDD at the node - if ( --pNode->nRefs == 0 && fDropInternal ) - { - Cudd_Deref( bFunc ); - Aig_ObjSetGlobalBdd( pNode, NULL ); - } - return bFunc; -} - -/**Function************************************************************* - - Synopsis [Frees the global BDDs of the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManFreeGlobalBdds( Aig_Man_t * p, DdManager * dd ) -{ - Aig_Obj_t * pObj; - int i; - Aig_ManForEachObj( p, pObj, i ) - if ( Aig_ObjGlobalBdd(pObj) ) - Aig_ObjCleanGlobalBdd( dd, pObj ); -} - -/**Function************************************************************* - - Synopsis [Returns the shared size of global BDDs of the COs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManSizeOfGlobalBdds( Aig_Man_t * p ) -{ - Vec_Ptr_t * vFuncsGlob; - Aig_Obj_t * pObj; - int RetValue, i; - // complement the global functions - vFuncsGlob = Vec_PtrAlloc( Aig_ManCoNum(p) ); - Aig_ManForEachCo( p, pObj, i ) - Vec_PtrPush( vFuncsGlob, Aig_ObjGlobalBdd(pObj) ); - RetValue = Cudd_SharingSize( (DdNode **)Vec_PtrArray(vFuncsGlob), Vec_PtrSize(vFuncsGlob) ); - Vec_PtrFree( vFuncsGlob ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Recursively computes global BDDs for the AIG in the manager.] - - Description [On exit, BDDs are stored in the pNode->pData fields.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdManager * Aig_ManComputeGlobalBdds( Aig_Man_t * p, int nBddSizeMax, int fDropInternal, int fReorder, int fVerbose ) -{ - ProgressBar * pProgress = NULL; - Aig_Obj_t * pObj; - DdManager * dd; - DdNode * bFunc; - int i, Counter; - // start the manager - dd = Cudd_Init( Aig_ManCiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - // set reordering - if ( fReorder ) - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - // prepare to construct global BDDs - Aig_ManCleanData( p ); - // assign the constant node BDD - Aig_ObjSetGlobalBdd( Aig_ManConst1(p), dd->one ); Cudd_Ref( dd->one ); - // set the elementary variables - Aig_ManForEachCi( p, pObj, i ) - { - Aig_ObjSetGlobalBdd( pObj, dd->vars[i] ); Cudd_Ref( dd->vars[i] ); - } - - // collect the global functions of the COs - Counter = 0; - // construct the BDDs -// pProgress = Extra_ProgressBarStart( stdout, Aig_ManNodeNum(p) ); - Aig_ManForEachCo( p, pObj, i ) - { - bFunc = Bbr_NodeGlobalBdds_rec( dd, Aig_ObjFanin0(pObj), nBddSizeMax, fDropInternal, pProgress, &Counter, fVerbose ); - if ( bFunc == NULL ) - { - if ( fVerbose ) - printf( "Constructing global BDDs is aborted.\n" ); - Aig_ManFreeGlobalBdds( p, dd ); - Cudd_Quit( dd ); - // reset references - Aig_ManResetRefs( p ); - return NULL; - } - bFunc = Cudd_NotCond( bFunc, Aig_ObjFaninC0(pObj) ); Cudd_Ref( bFunc ); - Aig_ObjSetGlobalBdd( pObj, bFunc ); - } -// Extra_ProgressBarStop( pProgress ); - // reset references - Aig_ManResetRefs( p ); - // reorder one more time - if ( fReorder ) - { - Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); - Cudd_AutodynDisable( dd ); - } -// Cudd_PrintInfo( dd, stdout ); - return dd; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/bbr/bbrReach.c b/src/proof/bbr/bbrReach.c deleted file mode 100644 index b5125ec7..00000000 --- a/src/proof/bbr/bbrReach.c +++ /dev/null @@ -1,615 +0,0 @@ -/**CFile**************************************************************** - - FileName [bbrReach.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD-based reachability analysis.] - - Synopsis [Procedures to perform reachability analysis.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: bbrReach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "bbr.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern Abc_Cex_t * Aig_ManVerifyUsingBddsCountExample( Aig_Man_t * p, DdManager * dd, - DdNode ** pbParts, Vec_Ptr_t * vOnionRings, DdNode * bCubeFirst, - int iOutput, int fVerbose, int fSilent ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [This procedure sets default resynthesis parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbr_ManSetDefaultParams( Saig_ParBbr_t * p ) -{ - memset( p, 0, sizeof(Saig_ParBbr_t) ); - p->TimeLimit = 0; - p->nBddMax = 50000; - p->nIterMax = 1000; - p->fPartition = 1; - p->fReorder = 1; - p->fReorderImage = 1; - p->fVerbose = 0; - p->fSilent = 0; - p->iFrame = -1; -} - -/**Function******************************************************************** - - Synopsis [Performs the reordering-sensitive step of Extra_bddMove().] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Bbr_bddComputeRangeCube( DdManager * dd, int iStart, int iStop ) -{ - DdNode * bTemp, * bProd; - int i; - assert( iStart <= iStop ); - assert( iStart >= 0 && iStart <= dd->size ); - assert( iStop >= 0 && iStop <= dd->size ); - bProd = (dd)->one; Cudd_Ref( bProd ); - for ( i = iStart; i < iStop; i++ ) - { - bProd = Cudd_bddAnd( dd, bTemp = bProd, dd->vars[i] ); Cudd_Ref( bProd ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bProd ); - return bProd; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bbr_StopManager( DdManager * dd ) -{ - int RetValue; - // check for remaining references in the package - RetValue = Cudd_CheckZeroRef( dd ); - if ( RetValue > 0 ) - printf( "\nThe number of referenced nodes = %d\n\n", RetValue ); -// Cudd_PrintInfo( dd, stdout ); - Cudd_Quit( dd ); -} - -/**Function************************************************************* - - Synopsis [Computes the initial state and sets up the variable map.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Aig_ManInitStateVarMap( DdManager * dd, Aig_Man_t * p, int fVerbose ) -{ - DdNode ** pbVarsX, ** pbVarsY; - DdNode * bTemp, * bProd; - Aig_Obj_t * pLatch; - int i; - - // set the variable mapping for Cudd_bddVarMap() - pbVarsX = ABC_ALLOC( DdNode *, dd->size ); - pbVarsY = ABC_ALLOC( DdNode *, dd->size ); - bProd = (dd)->one; Cudd_Ref( bProd ); - Saig_ManForEachLo( p, pLatch, i ) - { - pbVarsX[i] = dd->vars[ Saig_ManPiNum(p) + i ]; - pbVarsY[i] = dd->vars[ Saig_ManCiNum(p) + i ]; - // get the initial value of the latch - bProd = Cudd_bddAnd( dd, bTemp = bProd, Cudd_Not(pbVarsX[i]) ); Cudd_Ref( bProd ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_SetVarMap( dd, pbVarsX, pbVarsY, Saig_ManRegNum(p) ); - ABC_FREE( pbVarsX ); - ABC_FREE( pbVarsY ); - - Cudd_Deref( bProd ); - return bProd; -} - -/**Function************************************************************* - - Synopsis [Collects the array of output BDDs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode ** Aig_ManCreateOutputs( DdManager * dd, Aig_Man_t * p ) -{ - DdNode ** pbOutputs; - Aig_Obj_t * pNode; - int i; - // compute the transition relation - pbOutputs = ABC_ALLOC( DdNode *, Saig_ManPoNum(p) ); - Saig_ManForEachPo( p, pNode, i ) - { - pbOutputs[i] = Aig_ObjGlobalBdd(pNode); Cudd_Ref( pbOutputs[i] ); - } - return pbOutputs; -} - -/**Function************************************************************* - - Synopsis [Collects the array of partition BDDs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode ** Aig_ManCreatePartitions( DdManager * dd, Aig_Man_t * p, int fReorder, int fVerbose ) -{ - DdNode ** pbParts; - DdNode * bVar; - Aig_Obj_t * pNode; - int i; - - // extand the BDD manager to represent NS variables - assert( dd->size == Saig_ManCiNum(p) ); - Cudd_bddIthVar( dd, Saig_ManCiNum(p) + Saig_ManRegNum(p) - 1 ); - - // enable reordering - if ( fReorder ) - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - else - Cudd_AutodynDisable( dd ); - - // compute the transition relation - pbParts = ABC_ALLOC( DdNode *, Saig_ManRegNum(p) ); - Saig_ManForEachLi( p, pNode, i ) - { - bVar = Cudd_bddIthVar( dd, Saig_ManCiNum(p) + i ); - pbParts[i] = Cudd_bddXnor( dd, bVar, Aig_ObjGlobalBdd(pNode) ); Cudd_Ref( pbParts[i] ); - } - // free global BDDs - Aig_ManFreeGlobalBdds( p, dd ); - - // reorder and disable reordering - if ( fReorder ) - { - if ( fVerbose ) - fprintf( stdout, "BDD nodes in the partitions before reordering %d.\n", Cudd_SharingSize(pbParts,Saig_ManRegNum(p)) ); - Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); - Cudd_AutodynDisable( dd ); - if ( fVerbose ) - fprintf( stdout, "BDD nodes in the partitions after reordering %d.\n", Cudd_SharingSize(pbParts,Saig_ManRegNum(p)) ); - } - return pbParts; -} - -/**Function************************************************************* - - Synopsis [Computes the set of unreachable states.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManComputeReachable( DdManager * dd, Aig_Man_t * p, DdNode ** pbParts, DdNode * bInitial, DdNode ** pbOutputs, Saig_ParBbr_t * pPars, int fCheckOutputs ) -{ - int fInternalReorder = 0; - Bbr_ImageTree_t * pTree = NULL; // Suppress "might be used uninitialized" - Bbr_ImageTree2_t * pTree2 = NULL; // Supprses "might be used uninitialized" - DdNode * bReached, * bCubeCs; - DdNode * bCurrent; - DdNode * bNext = NULL; // Suppress "might be used uninitialized" - DdNode * bTemp; - Cudd_ReorderingType method; - int i, nIters, nBddSize = 0, status; - int nThreshold = 10000; - abctime clk = Abc_Clock(); - Vec_Ptr_t * vOnionRings; - int fixedPoint = 0; - - status = Cudd_ReorderingStatus( dd, &method ); - if ( status ) - Cudd_AutodynDisable( dd ); - - // start the image computation - bCubeCs = Bbr_bddComputeRangeCube( dd, Saig_ManPiNum(p), Saig_ManCiNum(p) ); Cudd_Ref( bCubeCs ); - if ( pPars->fPartition ) - pTree = Bbr_bddImageStart( dd, bCubeCs, Saig_ManRegNum(p), pbParts, Saig_ManRegNum(p), dd->vars+Saig_ManCiNum(p), pPars->nBddMax, pPars->fVerbose ); - else - pTree2 = Bbr_bddImageStart2( dd, bCubeCs, Saig_ManRegNum(p), pbParts, Saig_ManRegNum(p), dd->vars+Saig_ManCiNum(p), pPars->fVerbose ); - Cudd_RecursiveDeref( dd, bCubeCs ); - if ( pTree == NULL ) - { - if ( !pPars->fSilent ) - printf( "BDDs blew up during qualitification scheduling. " ); - return -1; - } - - if ( status ) - Cudd_AutodynEnable( dd, method ); - - // start the onion rings - vOnionRings = Vec_PtrAlloc( 1000 ); - - // perform reachability analysis - bCurrent = bInitial; Cudd_Ref( bCurrent ); - bReached = bInitial; Cudd_Ref( bReached ); - Vec_PtrPush( vOnionRings, bCurrent ); Cudd_Ref( bCurrent ); - for ( nIters = 0; nIters < pPars->nIterMax; nIters++ ) - { - // check the runtime limit - if ( pPars->TimeLimit && pPars->TimeLimit <= (Abc_Clock()-clk)/CLOCKS_PER_SEC ) - { - printf( "Reached timeout after image computation (%d seconds).\n", pPars->TimeLimit ); - Vec_PtrFree( vOnionRings ); - // undo the image tree - if ( pPars->fPartition ) - Bbr_bddImageTreeDelete( pTree ); - else - Bbr_bddImageTreeDelete2( pTree2 ); - pPars->iFrame = nIters - 1; - return -1; - } - - // compute the next states - if ( pPars->fPartition ) - bNext = Bbr_bddImageCompute( pTree, bCurrent ); - else - bNext = Bbr_bddImageCompute2( pTree2, bCurrent ); - if ( bNext == NULL ) - { - if ( !pPars->fSilent ) - printf( "BDDs blew up during image computation. " ); - if ( pPars->fPartition ) - Bbr_bddImageTreeDelete( pTree ); - else - Bbr_bddImageTreeDelete2( pTree2 ); - Vec_PtrFree( vOnionRings ); - pPars->iFrame = nIters - 1; - return -1; - } - Cudd_Ref( bNext ); - Cudd_RecursiveDeref( dd, bCurrent ); - - // remap these states into the current state vars - bNext = Cudd_bddVarMap( dd, bTemp = bNext ); Cudd_Ref( bNext ); - Cudd_RecursiveDeref( dd, bTemp ); - // check if there are any new states - if ( Cudd_bddLeq( dd, bNext, bReached ) ) { - fixedPoint = 1; - break; - } - // check the BDD size - nBddSize = Cudd_DagSize(bNext); - if ( nBddSize > pPars->nBddMax ) - break; - // check the result - for ( i = 0; i < Saig_ManPoNum(p); i++ ) - { - if ( fCheckOutputs && !Cudd_bddLeq( dd, bNext, Cudd_Not(pbOutputs[i]) ) ) - { - DdNode * bIntersect; - bIntersect = Cudd_bddIntersect( dd, bNext, pbOutputs[i] ); Cudd_Ref( bIntersect ); - assert( p->pSeqModel == NULL ); - p->pSeqModel = Aig_ManVerifyUsingBddsCountExample( p, dd, pbParts, - vOnionRings, bIntersect, i, pPars->fVerbose, pPars->fSilent ); - Cudd_RecursiveDeref( dd, bIntersect ); - if ( !pPars->fSilent ) - Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", i, p->pName, Vec_PtrSize(vOnionRings) ); - Cudd_RecursiveDeref( dd, bReached ); - bReached = NULL; - pPars->iFrame = nIters; - break; - } - } - if ( i < Saig_ManPoNum(p) ) - break; - // get the new states - bCurrent = Cudd_bddAnd( dd, bNext, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); - Vec_PtrPush( vOnionRings, bCurrent ); Cudd_Ref( bCurrent ); - // minimize the new states with the reached states -// bCurrent = Cudd_bddConstrain( dd, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); -// Cudd_RecursiveDeref( dd, bTemp ); - // add to the reached states - bReached = Cudd_bddOr( dd, bTemp = bReached, bNext ); Cudd_Ref( bReached ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bNext ); - if ( pPars->fVerbose ) - fprintf( stdout, "Frame = %3d. BDD = %5d. ", nIters, nBddSize ); - if ( fInternalReorder && pPars->fReorder && nBddSize > nThreshold ) - { - if ( pPars->fVerbose ) - fprintf( stdout, "Reordering... Before = %5d. ", Cudd_DagSize(bReached) ); - Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); - Cudd_AutodynDisable( dd ); - if ( pPars->fVerbose ) - fprintf( stdout, "After = %5d.\r", Cudd_DagSize(bReached) ); - nThreshold *= 2; - } - if ( pPars->fVerbose ) -// fprintf( stdout, "\r" ); - fprintf( stdout, "\n" ); - - if ( pPars->fVerbose ) - { - double nMints = Cudd_CountMinterm(dd, bReached, Saig_ManRegNum(p) ); -// Extra_bddPrint( dd, bReached );printf( "\n" ); - fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p)) ); - fflush( stdout ); - } - - } - Cudd_RecursiveDeref( dd, bNext ); - // free the onion rings - Vec_PtrForEachEntry( DdNode *, vOnionRings, bTemp, i ) - Cudd_RecursiveDeref( dd, bTemp ); - Vec_PtrFree( vOnionRings ); - // undo the image tree - if ( pPars->fPartition ) - Bbr_bddImageTreeDelete( pTree ); - else - Bbr_bddImageTreeDelete2( pTree2 ); - if ( bReached == NULL ) - return 0; // proved reachable - // report the stats - if ( pPars->fVerbose ) - { - double nMints = Cudd_CountMinterm(dd, bReached, Saig_ManRegNum(p) ); - if ( nIters > pPars->nIterMax || nBddSize > pPars->nBddMax ) - fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters ); - else - fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters ); - fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p)) ); - fflush( stdout ); - } -//ABC_PRB( dd, bReached ); - Cudd_RecursiveDeref( dd, bReached ); - // SPG - // - if ( fixedPoint ) { - if ( !pPars->fSilent ) { - printf( "The miter is proved unreachable after %d iterations. ", nIters ); - } - pPars->iFrame = nIters - 1; - return 1; - } - assert(nIters >= pPars->nIterMax || nBddSize >= pPars->nBddMax); - if ( !pPars->fSilent ) - printf( "Verified only for states reachable in %d frames. ", nIters ); - pPars->iFrame = nIters - 1; - return -1; // undecided -} - -/**Function************************************************************* - - Synopsis [Performs reachability to see if any PO can be asserted.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManVerifyUsingBdds_int( Aig_Man_t * p, Saig_ParBbr_t * pPars ) -{ - int fCheckOutputs = !pPars->fSkipOutCheck; - DdManager * dd; - DdNode ** pbParts, ** pbOutputs; - DdNode * bInitial, * bTemp; - int RetValue, i; - abctime clk = Abc_Clock(); - Vec_Ptr_t * vOnionRings; - - assert( Saig_ManRegNum(p) > 0 ); - - // compute the global BDDs of the latches - dd = Aig_ManComputeGlobalBdds( p, pPars->nBddMax, 1, pPars->fReorder, pPars->fVerbose ); - if ( dd == NULL ) - { - if ( !pPars->fSilent ) - printf( "The number of intermediate BDD nodes exceeded the limit (%d).\n", pPars->nBddMax ); - return -1; - } - if ( pPars->fVerbose ) - printf( "Shared BDD size is %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); - - // check the runtime limit - if ( pPars->TimeLimit && pPars->TimeLimit <= (Abc_Clock()-clk)/CLOCKS_PER_SEC ) - { - printf( "Reached timeout after constructing global BDDs (%d seconds).\n", pPars->TimeLimit ); - Cudd_Quit( dd ); - return -1; - } - - // start the onion rings - vOnionRings = Vec_PtrAlloc( 1000 ); - - // save outputs - pbOutputs = Aig_ManCreateOutputs( dd, p ); - - // create partitions - pbParts = Aig_ManCreatePartitions( dd, p, pPars->fReorder, pPars->fVerbose ); - - // create the initial state and the variable map - bInitial = Aig_ManInitStateVarMap( dd, p, pPars->fVerbose ); Cudd_Ref( bInitial ); - - // set reordering - if ( pPars->fReorderImage ) - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - - // check the result - RetValue = -1; - for ( i = 0; i < Saig_ManPoNum(p); i++ ) - { - if ( fCheckOutputs && !Cudd_bddLeq( dd, bInitial, Cudd_Not(pbOutputs[i]) ) ) - { - DdNode * bIntersect; - bIntersect = Cudd_bddIntersect( dd, bInitial, pbOutputs[i] ); Cudd_Ref( bIntersect ); - assert( p->pSeqModel == NULL ); - p->pSeqModel = Aig_ManVerifyUsingBddsCountExample( p, dd, pbParts, - vOnionRings, bIntersect, i, pPars->fVerbose, pPars->fSilent ); - Cudd_RecursiveDeref( dd, bIntersect ); - if ( !pPars->fSilent ) - Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", i, p->pName, -1 ); - RetValue = 0; - break; - } - } - // free the onion rings - Vec_PtrForEachEntry( DdNode *, vOnionRings, bTemp, i ) - Cudd_RecursiveDeref( dd, bTemp ); - Vec_PtrFree( vOnionRings ); - // explore reachable states - if ( RetValue == -1 ) - RetValue = Aig_ManComputeReachable( dd, p, pbParts, bInitial, pbOutputs, pPars, fCheckOutputs ); - - // cleanup - Cudd_RecursiveDeref( dd, bInitial ); - for ( i = 0; i < Saig_ManRegNum(p); i++ ) - Cudd_RecursiveDeref( dd, pbParts[i] ); - ABC_FREE( pbParts ); - for ( i = 0; i < Saig_ManPoNum(p); i++ ) - Cudd_RecursiveDeref( dd, pbOutputs[i] ); - ABC_FREE( pbOutputs ); -// if ( RetValue == -1 ) - Cudd_Quit( dd ); -// else -// Bbr_StopManager( dd ); - - // report the runtime - if ( !pPars->fSilent ) - { - ABC_PRT( "Time", Abc_Clock() - clk ); - fflush( stdout ); - } - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Performs reachability to see if any PO can be asserted.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManVerifyUsingBdds( Aig_Man_t * pInit, Saig_ParBbr_t * pPars ) -{ - Abc_Cex_t * pCexOld, * pCexNew; - Aig_Man_t * p; - Aig_Obj_t * pObj; - Vec_Int_t * vInputMap; - int i, k, Entry, iBitOld, iBitNew, RetValue; -// pPars->fVerbose = 1; - // check if there are PIs without fanout - Saig_ManForEachPi( pInit, pObj, i ) - if ( Aig_ObjRefs(pObj) == 0 ) - break; - if ( i == Saig_ManPiNum(pInit) ) - return Aig_ManVerifyUsingBdds_int( pInit, pPars ); - // create new AIG - p = Aig_ManDupTrim( pInit ); - assert( Aig_ManCiNum(p) < Aig_ManCiNum(pInit) ); - assert( Aig_ManRegNum(p) == Aig_ManRegNum(pInit) ); - RetValue = Aig_ManVerifyUsingBdds_int( p, pPars ); - if ( RetValue != 0 ) - { - Aig_ManStop( p ); - return RetValue; - } - // the problem is satisfiable - remap the pattern - pCexOld = p->pSeqModel; - assert( pCexOld != NULL ); - // create input map - vInputMap = Vec_IntAlloc( Saig_ManPiNum(pInit) ); - Saig_ManForEachPi( pInit, pObj, i ) - if ( pObj->pData != NULL ) - Vec_IntPush( vInputMap, Aig_ObjCioId((Aig_Obj_t *)pObj->pData) ); - else - Vec_IntPush( vInputMap, -1 ); - // create new pattern - pCexNew = Abc_CexAlloc( Saig_ManRegNum(pInit), Saig_ManPiNum(pInit), pCexOld->iFrame+1 ); - pCexNew->iFrame = pCexOld->iFrame; - pCexNew->iPo = pCexOld->iPo; - // copy the bit-data - for ( iBitOld = 0; iBitOld < pCexOld->nRegs; iBitOld++ ) - if ( Abc_InfoHasBit( pCexOld->pData, iBitOld ) ) - Abc_InfoSetBit( pCexNew->pData, iBitOld ); - // copy the primary input data - iBitNew = iBitOld; - for ( i = 0; i <= pCexNew->iFrame; i++ ) - { - Vec_IntForEachEntry( vInputMap, Entry, k ) - { - if ( Entry == -1 ) - continue; - if ( Abc_InfoHasBit( pCexOld->pData, iBitOld + Entry ) ) - Abc_InfoSetBit( pCexNew->pData, iBitNew + k ); - } - iBitOld += Saig_ManPiNum(p); - iBitNew += Saig_ManPiNum(pInit); - } - assert( iBitOld < iBitNew ); - assert( iBitOld == pCexOld->nBits ); - assert( iBitNew == pCexNew->nBits ); - Vec_IntFree( vInputMap ); - pInit->pSeqModel = pCexNew; - Aig_ManStop( p ); - return 0; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/bbr/bbr_.c b/src/proof/bbr/bbr_.c deleted file mode 100644 index df934f7d..00000000 --- a/src/proof/bbr/bbr_.c +++ /dev/null @@ -1,52 +0,0 @@ -/**CFile**************************************************************** - - FileName [.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: .c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "__Int.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/bbr/module.make b/src/proof/bbr/module.make deleted file mode 100644 index 11ba768e..00000000 --- a/src/proof/bbr/module.make +++ /dev/null @@ -1,4 +0,0 @@ -SRC += src/proof/bbr/bbrCex.c \ - src/proof/bbr/bbrImage.c \ - src/proof/bbr/bbrNtbdd.c \ - src/proof/bbr/bbrReach.c diff --git a/src/proof/llb/llb.c b/src/proof/llb/llb.c deleted file mode 100644 index 348c0622..00000000 --- a/src/proof/llb/llb.c +++ /dev/null @@ -1,52 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/llb/llb.h b/src/proof/llb/llb.h deleted file mode 100644 index f465359d..00000000 --- a/src/proof/llb/llb.h +++ /dev/null @@ -1,96 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD-based reachability.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 8, 2010.] - - Revision [$Id: llb.h,v 1.00 2010/05/08 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef ABC__aig__llb__llb_h -#define ABC__aig__llb__llb_h - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Gia_ParLlb_t_ Gia_ParLlb_t; -struct Gia_ParLlb_t_ -{ - int nBddMax; // maximum BDD size - int nIterMax; // maximum iteration count - int nClusterMax; // maximum cluster size - int nHintDepth; // the number of times to cofactor - int HintFirst; // the number of first hint to use - int fUseFlow; // use flow computation - int nVolumeMax; // the largest volume - int nVolumeMin; // the smallest volume - int nPartValue; // partitioning value - int fBackward; // enable backward reachability - int fReorder; // enable dynamic variable reordering - int fIndConstr; // extract inductive constraints - int fUsePivots; // use internal pivot variables - int fCluster; // use partition clustering - int fSchedule; // use cluster scheduling - int fDumpReached; // dump reached states into a file - int fVerbose; // print verbose information - int fVeryVerbose; // print dependency matrices - int fSilent; // do not print any infomation - int fSkipReach; // skip reachability (preparation phase only) - int fSkipOutCheck; // does not check the property output - int TimeLimit; // time limit for one reachability run - int TimeLimitGlo; // time limit for all reachability runs - // internal parameters - abctime TimeTarget; // the time to stop - int iFrame; // explored up to this frame -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== llbCore.c ==========================================================*/ -extern void Llb_ManSetDefaultParams( Gia_ParLlb_t * pPars ); -/*=== llb4Nonlin.c ==========================================================*/ -extern int Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ); - - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/proof/llb/llb1Cluster.c b/src/proof/llb/llb1Cluster.c deleted file mode 100644 index 1356e484..00000000 --- a/src/proof/llb/llb1Cluster.c +++ /dev/null @@ -1,356 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb1Cluster.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Clustering algorithm.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb1Cluster.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManComputeCommonQuant( Llb_Mtr_t * p, int iCol1, int iCol2 ) -{ - int iVar, Weight = 0; - for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ ) - { - // count each removed variable as 2 - if ( p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 1 && p->pRowSums[iVar] == 2 ) - Weight += 2; - // count each added variale as -1 - else if ( (p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 0) || - (p->pMatrix[iCol1][iVar] == 0 && p->pMatrix[iCol2][iVar] == 1) ) - Weight--; - } - return Weight; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManComputeBestQuant( Llb_Mtr_t * p ) -{ - int i, k, WeightBest = -100000, WeightCur, RetValue = -1; - for ( i = 1; i < p->nCols-1; i++ ) - for ( k = i+1; k < p->nCols-1; k++ ) - { - if ( p->pColSums[i] == 0 || p->pColSums[i] > p->pMan->pPars->nClusterMax ) - continue; - if ( p->pColSums[k] == 0 || p->pColSums[k] > p->pMan->pPars->nClusterMax ) - continue; - - WeightCur = Llb_ManComputeCommonQuant( p, i, k ); - if ( WeightCur <= 0 ) - continue; - if ( WeightBest < WeightCur ) - { - WeightBest = WeightCur; - RetValue = (i << 16) | k; - } - } -// printf( "Choosing best quant Weight %4d\n", WeightCur ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float ** Llb_ManComputeQuant( Llb_Mtr_t * p ) -{ - float ** pCosts; - int i, k; - // alloc and clean - pCosts = (float **)Extra_ArrayAlloc( p->nCols, p->nCols, sizeof(float) ); - for ( i = 0; i < p->nCols; i++ ) - for ( k = 0; k < p->nCols; k++ ) - pCosts[i][i] = 0.0; - // fill up - for ( i = 1; i < p->nCols-1; i++ ) - for ( k = i+1; k < p->nCols-1; k++ ) - pCosts[i][k] = pCosts[k][i] = Llb_ManComputeCommonQuant( p, i, k ); - return pCosts; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Llb_ManComputeCommonAttr( Llb_Mtr_t * p, int iCol1, int iCol2 ) -{ - int iVar, CountComm = 0, CountDiff = 0; - for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ ) - { - if ( p->pMatrix[iCol1][iVar] == 1 && p->pMatrix[iCol2][iVar] == 1 ) - CountComm++; - else if ( p->pMatrix[iCol1][iVar] == 1 || p->pMatrix[iCol2][iVar] == 1 ) - CountDiff++; - } -/* - printf( "Attr cost for %4d and %4d: %4d %4d (%5.2f)\n", - iCol1, iCol2, - CountDiff, CountComm, - -1.0 * CountDiff / ( CountComm + CountDiff ) ); -*/ - return -1.0 * CountDiff / ( CountComm + CountDiff ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManComputeBestAttr( Llb_Mtr_t * p ) -{ - float WeightBest = -100000, WeightCur; - int i, k, RetValue = -1; - for ( i = 1; i < p->nCols-1; i++ ) - for ( k = i+1; k < p->nCols-1; k++ ) - { - if ( p->pColSums[i] == 0 || p->pColSums[i] > p->pMan->pPars->nClusterMax ) - continue; - if ( p->pColSums[k] == 0 || p->pColSums[k] > p->pMan->pPars->nClusterMax ) - continue; - WeightCur = Llb_ManComputeCommonAttr( p, i, k ); - if ( WeightBest < WeightCur ) - { - WeightBest = WeightCur; - RetValue = (i << 16) | k; - } - } - return RetValue; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float ** Llb_ManComputeAttr( Llb_Mtr_t * p ) -{ - float ** pCosts; - int i, k; - // alloc and clean - pCosts = (float **)Extra_ArrayAlloc( p->nCols, p->nCols, sizeof(float) ); - for ( i = 0; i < p->nCols; i++ ) - for ( k = 0; k < p->nCols; k++ ) - pCosts[i][i] = 0.0; - // fill up - for ( i = 1; i < p->nCols-1; i++ ) - for ( k = i+1; k < p->nCols-1; k++ ) - pCosts[i][k] = pCosts[k][i] = Llb_ManComputeCommonAttr( p, i, k ); - return pCosts; -} - - -/**Function************************************************************* - - Synopsis [Returns the number of variables that will be saved.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrCombineSelectedColumns( Llb_Mtr_t * p, int iGrp1, int iGrp2 ) -{ - int iVar; - assert( iGrp1 >= 1 && iGrp1 < p->nCols - 1 ); - assert( iGrp2 >= 1 && iGrp2 < p->nCols - 1 ); - assert( p->pColGrps[iGrp1] != NULL ); - assert( p->pColGrps[iGrp2] != NULL ); - for ( iVar = 0; iVar < p->nRows; iVar++ ) - { - if ( p->pMatrix[iGrp1][iVar] == 1 && p->pMatrix[iGrp2][iVar] == 1 ) - p->pRowSums[iVar]--; - if ( p->pMatrix[iGrp1][iVar] == 0 && p->pMatrix[iGrp2][iVar] == 1 ) - { - p->pMatrix[iGrp1][iVar] = 1; - p->pColSums[iGrp1]++; - } - if ( p->pMatrix[iGrp2][iVar] == 1 ) - p->pMatrix[iGrp2][iVar] = 0; - } - p->pColSums[iGrp2] = 0; -} - - -/**Function************************************************************* - - Synopsis [Combines one pair of columns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManClusterOne( Llb_Mtr_t * p, int iCol1, int iCol2 ) -{ - int fVerbose = 0; - Llb_Grp_t * pGrp; - int iVar; - - if ( fVerbose ) - { - printf( "Combining %d and %d\n", iCol1, iCol2 ); - for ( iVar = 0; iVar < p->nRows; iVar++ ) - { - if ( p->pMatrix[iCol1][iVar] == 0 && p->pMatrix[iCol2][iVar] == 0 ) - continue; - printf( "%3d : %c%c\n", iVar, - p->pMatrix[iCol1][iVar]? '*':' ', - p->pMatrix[iCol2][iVar]? '*':' ' ); - } - } - pGrp = Llb_ManGroupsCombine( p->pColGrps[iCol1], p->pColGrps[iCol2] ); - Llb_MtrCombineSelectedColumns( p, iCol1, iCol2 ); - p->pColGrps[iCol1] = pGrp; - p->pColGrps[iCol2] = NULL; -} - -/**Function************************************************************* - - Synopsis [Removes empty columns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManClusterCompress( Llb_Mtr_t * p ) -{ - int i, k = 0; - for ( i = 0; i < p->nCols; i++ ) - { - if ( p->pColGrps[i] == NULL ) - { - assert( p->pColSums[i] == 0 ); - assert( p->pMatrix[i] != NULL ); - ABC_FREE( p->pMatrix[i] ); - continue; - } - p->pMatrix[k] = p->pMatrix[i]; - p->pColGrps[k] = p->pColGrps[i]; - p->pColSums[k] = p->pColSums[i]; - k++; - } - p->nCols = k; -} - -/**Function************************************************************* - - Synopsis [Combines one pair of columns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManCluster( Llb_Mtr_t * p ) -{ - int RetValue; - do - { - do { - RetValue = Llb_ManComputeBestQuant( p ); - if ( RetValue > 0 ) - Llb_ManClusterOne( p, RetValue >> 16, RetValue & 0xffff ); - } - while ( RetValue > 0 ); - - RetValue = Llb_ManComputeBestAttr( p ); - if ( RetValue > 0 ) - Llb_ManClusterOne( p, RetValue >> 16, RetValue & 0xffff ); - - Llb_MtrVerifyMatrix( p ); - } - while ( RetValue > 0 ); - - Llb_ManClusterCompress( p ); - - Llb_MtrVerifyMatrix( p ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/llb/llb1Constr.c b/src/proof/llb/llb1Constr.c deleted file mode 100644 index 1ef4ce14..00000000 --- a/src/proof/llb/llb1Constr.c +++ /dev/null @@ -1,313 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb1Constr.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Computing inductive constraints.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb1Constr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns the array of constraint candidates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManCountEntries( Vec_Int_t * vCands ) -{ - int i, Entry, Counter = 0; - Vec_IntForEachEntry( vCands, Entry, i ) - Counter += ((Entry == 0) || (Entry == 1)); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Returns the array of constraint candidates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManPrintEntries( Aig_Man_t * p, Vec_Int_t * vCands ) -{ - int i, Entry; - if ( vCands == NULL ) - { - printf( "There is no hints.\n" ); - return; - } - Entry = Llb_ManCountEntries(vCands); - printf( "\n*** Using %d hint%s:\n", Entry, (Entry != 1 ? "s":"") ); - Vec_IntForEachEntry( vCands, Entry, i ) - { - if ( Entry != 0 && Entry != 1 ) - continue; - printf( "%c", Entry ? '+' : '-' ); - printf( "%-6d : ", i ); - Aig_ObjPrint( p, Aig_ManObj(p, i) ); - printf( "\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Dereference BDD nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManDerefenceBdds( Aig_Man_t * p, DdManager * dd ) -{ - Aig_Obj_t * pObj; - int i; - Aig_ManForEachObj( p, pObj, i ) - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); -} - -/**Function************************************************************* - - Synopsis [Returns the array of constraint candidates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ManComputeIndCase_rec( Aig_Man_t * p, Aig_Obj_t * pObj, DdManager * dd, Vec_Ptr_t * vBdds ) -{ - DdNode * bBdd0, * bBdd1; - DdNode * bFunc = (DdNode *)Vec_PtrEntry( vBdds, Aig_ObjId(pObj) ); - if ( bFunc != NULL ) - return bFunc; - assert( Aig_ObjIsNode(pObj) ); - bBdd0 = Llb_ManComputeIndCase_rec( p, Aig_ObjFanin0(pObj), dd, vBdds ); - bBdd1 = Llb_ManComputeIndCase_rec( p, Aig_ObjFanin1(pObj), dd, vBdds ); - bBdd0 = Cudd_NotCond( bBdd0, Aig_ObjFaninC0(pObj) ); - bBdd1 = Cudd_NotCond( bBdd1, Aig_ObjFaninC1(pObj) ); - bFunc = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bFunc ); - Vec_PtrWriteEntry( vBdds, Aig_ObjId(pObj), bFunc ); - return bFunc; -} - -/**Function************************************************************* - - Synopsis [Returns the array of constraint candidates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManComputeIndCase( Aig_Man_t * p, DdManager * dd, Vec_Int_t * vNodes ) -{ - Vec_Ptr_t * vBdds; - Aig_Obj_t * pObj; - DdNode * bFunc; - int i, Entry; - vBdds = Vec_PtrStart( Aig_ManObjNumMax(p) ); - bFunc = Cudd_ReadOne(dd); Cudd_Ref( bFunc ); - Vec_PtrWriteEntry( vBdds, Aig_ObjId(Aig_ManConst1(p)), bFunc ); - Saig_ManForEachPi( p, pObj, i ) - { - bFunc = Cudd_bddIthVar( dd, Aig_ManCiNum(p) + i ); Cudd_Ref( bFunc ); - Vec_PtrWriteEntry( vBdds, Aig_ObjId(pObj), bFunc ); - } - Saig_ManForEachLi( p, pObj, i ) - { - bFunc = (DdNode *)pObj->pData; Cudd_Ref( bFunc ); - Vec_PtrWriteEntry( vBdds, Aig_ObjId(Saig_ObjLiToLo(p, pObj)), bFunc ); - } - Vec_IntForEachEntry( vNodes, Entry, i ) - { - if ( Entry != 0 && Entry != 1 ) - continue; - pObj = Aig_ManObj( p, i ); - bFunc = Llb_ManComputeIndCase_rec( p, pObj, dd, vBdds ); - if ( Entry == 0 ) - { -// Extra_bddPrint( dd, Cudd_Not(pObj->pData) ); printf( "\n" ); -// Extra_bddPrint( dd, Cudd_Not(bFunc) ); printf( "\n" ); - if ( !Cudd_bddLeq( dd, Cudd_Not(pObj->pData), Cudd_Not(bFunc) ) ) - Vec_IntWriteEntry( vNodes, i, -1 ); - } - else if ( Entry == 1 ) - { -// Extra_bddPrint( dd, pObj->pData ); printf( "\n" ); -// Extra_bddPrint( dd, bFunc ); printf( "\n" ); - if ( !Cudd_bddLeq( dd, (DdNode *)pObj->pData, bFunc ) ) - Vec_IntWriteEntry( vNodes, i, -1 ); - } - } - Vec_PtrForEachEntry( DdNode *, vBdds, bFunc, i ) - if ( bFunc ) - Cudd_RecursiveDeref( dd, bFunc ); - Vec_PtrFree( vBdds ); -} - -/**Function************************************************************* - - Synopsis [Returns the array of constraint candidates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_ManComputeBaseCase( Aig_Man_t * p, DdManager * dd ) -{ - Vec_Int_t * vNodes; - Aig_Obj_t * pObj, * pRoot; - int i; - pRoot = Aig_ManCo( p, 0 ); - vNodes = Vec_IntStartFull( Aig_ManObjNumMax(p) ); - Aig_ManForEachObj( p, pObj, i ) - { - if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) ) - continue; - if ( Cudd_bddLeq( dd, (DdNode *)pObj->pData, Cudd_Not(pRoot->pData) ) ) - Vec_IntWriteEntry( vNodes, i, 1 ); - else if ( Cudd_bddLeq( dd, Cudd_Not((DdNode *)pObj->pData), Cudd_Not(pRoot->pData) ) ) - Vec_IntWriteEntry( vNodes, i, 0 ); - } - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Constructs global BDDs for each object in the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdManager * Llb_ManConstructGlobalBdds( Aig_Man_t * p ) -{ - DdManager * dd; - DdNode * bBdd0, * bBdd1; - Aig_Obj_t * pObj; - int i; - dd = Cudd_Init( Aig_ManCiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - pObj = Aig_ManConst1(p); - pObj->pData = Cudd_ReadOne(dd); Cudd_Ref( (DdNode *)pObj->pData ); - Aig_ManForEachCi( p, pObj, i ) - { - pObj->pData = Cudd_bddIthVar(dd, i); Cudd_Ref( (DdNode *)pObj->pData ); - } - Aig_ManForEachNode( p, pObj, i ) - { - bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); - pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData ); - } - Aig_ManForEachCo( p, pObj, i ) - { - pObj->pData = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); Cudd_Ref( (DdNode *)pObj->pData ); - } - return dd; -} - -/**Function************************************************************* - - Synopsis [Derives inductive constraints.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_ManDeriveConstraints( Aig_Man_t * p ) -{ - DdManager * dd; - Vec_Int_t * vNodes; - if ( Saig_ManPoNum(p) != 1 ) - { - printf( "The AIG has %d property outputs.\n", Saig_ManPoNum(p) ); - return NULL; - } - assert( Saig_ManPoNum(p) == 1 ); - dd = Llb_ManConstructGlobalBdds( p ); - vNodes = Llb_ManComputeBaseCase( p, dd ); - if ( Llb_ManCountEntries(vNodes) > 0 ) - Llb_ManComputeIndCase( p, dd, vNodes ); - if ( Llb_ManCountEntries(vNodes) == 0 ) - Vec_IntFreeP( &vNodes ); - Llb_ManDerefenceBdds( p, dd ); - Extra_StopManager( dd ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Tests derived constraints.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManConstrTest( Aig_Man_t * p ) -{ - Vec_Int_t * vNodes; - vNodes = Llb_ManDeriveConstraints( p ); - Llb_ManPrintEntries( p, vNodes ); - Vec_IntFreeP( &vNodes ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/llb/llb1Core.c b/src/proof/llb/llb1Core.c deleted file mode 100644 index 213f2cd9..00000000 --- a/src/proof/llb/llb1Core.c +++ /dev/null @@ -1,222 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb1Core.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Top-level procedure.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb1Core.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" -#include "aig/gia/gia.h" -#include "aig/gia/giaAig.h" - -ABC_NAMESPACE_IMPL_START - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManSetDefaultParams( Gia_ParLlb_t * p ) -{ - memset( p, 0, sizeof(Gia_ParLlb_t) ); - p->nBddMax = 10000000; - p->nIterMax = 10000000; - p->nClusterMax = 20; - p->nHintDepth = 0; - p->HintFirst = 0; - p->fUseFlow = 0; // use flow - p->nVolumeMax = 100; // max volume - p->nVolumeMin = 30; // min volume - p->nPartValue = 5; // partitioning value - p->fBackward = 0; // forward by default - p->fReorder = 1; - p->fIndConstr = 0; - p->fUsePivots = 0; - p->fCluster = 0; - p->fSchedule = 0; - p->fDumpReached = 0; - p->fVerbose = 0; - p->fVeryVerbose = 0; - p->fSilent = 0; - p->TimeLimit = 0; -// p->TimeLimit = 0; - p->TimeLimitGlo = 0; - p->TimeTarget = 0; - p->iFrame = -1; -} - - -/**Function************************************************************* - - Synopsis [Prints statistics about MFFCs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManPrintAig( Llb_Man_t * p ) -{ - Abc_Print( 1, "pi =%3d ", Saig_ManPiNum(p->pAig) ); - Abc_Print( 1, "po =%3d ", Saig_ManPoNum(p->pAig) ); - Abc_Print( 1, "ff =%3d ", Saig_ManRegNum(p->pAig) ); - Abc_Print( 1, "int =%5d ", Vec_IntSize(p->vVar2Obj)-Aig_ManCiNum(p->pAig)-Saig_ManRegNum(p->pAig) ); - Abc_Print( 1, "var =%5d ", Vec_IntSize(p->vVar2Obj) ); - Abc_Print( 1, "part =%5d ", Vec_PtrSize(p->vGroups)-2 ); - Abc_Print( 1, "and =%5d ", Aig_ManNodeNum(p->pAig) ); - Abc_Print( 1, "lev =%4d ", Aig_ManLevelNum(p->pAig) ); -// Abc_Print( 1, "cut =%4d ", Llb_ManCrossCut(p->pAig) ); - Abc_Print( 1, "\n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManModelCheckAig( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars, Vec_Int_t * vHints, DdManager ** pddGlo ) -{ - Llb_Man_t * p = NULL; - Aig_Man_t * pAig; - int RetValue = -1; - abctime clk = Abc_Clock(); - - if ( pPars->fIndConstr ) - { - assert( vHints == NULL ); - vHints = Llb_ManDeriveConstraints( pAigGlo ); - } - - // derive AIG for hints - if ( vHints == NULL ) - pAig = Aig_ManDupSimple( pAigGlo ); - else - { - if ( pPars->fVerbose ) - Llb_ManPrintEntries( pAigGlo, vHints ); - pAig = Aig_ManDupSimpleWithHints( pAigGlo, vHints ); - } - - - if ( pPars->fUseFlow ) - { -// p = Llb_ManStartFlow( pAigGlo, pAig, pPars ); - } - else - { - p = Llb_ManStart( pAigGlo, pAig, pPars ); - if ( pPars->fVerbose ) - { - Llb_ManPrintAig( p ); - printf( "Original matrix: " ); - Llb_MtrPrintMatrixStats( p->pMatrix ); - if ( pPars->fVeryVerbose ) - Llb_MtrPrint( p->pMatrix, 1 ); - } - if ( pPars->fCluster ) - { - Llb_ManCluster( p->pMatrix ); - if ( pPars->fVerbose ) - { - printf( "Matrix after clustering: " ); - Llb_MtrPrintMatrixStats( p->pMatrix ); - if ( pPars->fVeryVerbose ) - Llb_MtrPrint( p->pMatrix, 1 ); - } - } - if ( pPars->fSchedule ) - { - Llb_MtrSchedule( p->pMatrix ); - if ( pPars->fVerbose ) - { - printf( "Matrix after scheduling: " ); - Llb_MtrPrintMatrixStats( p->pMatrix ); - if ( pPars->fVeryVerbose ) - Llb_MtrPrint( p->pMatrix, 1 ); - } - } - } - - if ( !p->pPars->fSkipReach ) - RetValue = Llb_ManReachability( p, vHints, pddGlo ); - Llb_ManStop( p ); - - Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); - - if ( pPars->fIndConstr ) - Vec_IntFreeP( &vHints ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManModelCheckGia( Gia_Man_t * pGia, Gia_ParLlb_t * pPars ) -{ - Gia_Man_t * pGia2; - Aig_Man_t * pAig; - int RetValue = -1; - pGia2 = Gia_ManDupDfs( pGia ); - pAig = Gia_ManToAigSimple( pGia2 ); - Gia_ManStop( pGia2 ); -//Aig_ManShow( pAig, 0, NULL ); - - if ( pPars->nHintDepth == 0 ) - RetValue = Llb_ManModelCheckAig( pAig, pPars, NULL, NULL ); - else - RetValue = Llb_ManModelCheckAigWithHints( pAig, pPars ); - pGia->pCexSeq = pAig->pSeqModel; pAig->pSeqModel = NULL; - Aig_ManStop( pAig ); - return RetValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/llb/llb1Group.c b/src/proof/llb/llb1Group.c deleted file mode 100644 index 1099b2cd..00000000 --- a/src/proof/llb/llb1Group.c +++ /dev/null @@ -1,474 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb1Group.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Initial partition computation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb1Group.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Grp_t * Llb_ManGroupAlloc( Llb_Man_t * pMan ) -{ - Llb_Grp_t * p; - p = ABC_CALLOC( Llb_Grp_t, 1 ); - p->pMan = pMan; - p->vIns = Vec_PtrAlloc( 8 ); - p->vOuts = Vec_PtrAlloc( 8 ); - p->Id = Vec_PtrSize( pMan->vGroups ); - Vec_PtrPush( pMan->vGroups, p ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManGroupStop( Llb_Grp_t * p ) -{ - if ( p == NULL ) - return; - Vec_PtrWriteEntry( p->pMan->vGroups, p->Id, NULL ); - Vec_PtrFreeP( &p->vIns ); - Vec_PtrFreeP( &p->vOuts ); - Vec_PtrFreeP( &p->vNodes ); - ABC_FREE( p ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManGroupCollect_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) -{ - if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) - return; - Aig_ObjSetTravIdCurrent(pAig, pObj); - if ( Aig_ObjIsConst1(pObj) ) - return; - if ( Aig_ObjIsCo(pObj) ) - { - Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin0(pObj), vNodes ); - return; - } - assert( Aig_ObjIsAnd(pObj) ); - Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin0(pObj), vNodes ); - Llb_ManGroupCollect_rec( pAig, Aig_ObjFanin1(pObj), vNodes ); - Vec_PtrPush( vNodes, pObj ); -} - -/**Function************************************************************* - - Synopsis [Collects the support of MFFC.] - - Description [Returns the number of internal nodes in the MFFC.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManGroupCollect( Llb_Grp_t * pGroup ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i; - vNodes = Vec_PtrAlloc( 100 ); - Aig_ManIncrementTravId( pGroup->pMan->pAig ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) - Aig_ObjSetTravIdCurrent( pGroup->pMan->pAig, pObj ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) - Aig_ObjSetTravIdPrevious( pGroup->pMan->pAig, pObj ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) - Llb_ManGroupCollect_rec( pGroup->pMan->pAig, pObj, vNodes ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManGroupCreate_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vSupp ) -{ - if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) - return; - Aig_ObjSetTravIdCurrent(pAig, pObj); - if ( Aig_ObjIsConst1(pObj) ) - return; - if ( pObj->fMarkA ) - { - Vec_PtrPush( vSupp, pObj ); - return; - } - assert( Aig_ObjIsAnd(pObj) ); - Llb_ManGroupCreate_rec( pAig, Aig_ObjFanin0(pObj), vSupp ); - Llb_ManGroupCreate_rec( pAig, Aig_ObjFanin1(pObj), vSupp ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Grp_t * Llb_ManGroupCreate( Llb_Man_t * pMan, Aig_Obj_t * pObj ) -{ - Llb_Grp_t * p; - assert( pObj->fMarkA == 1 ); - // derive group - p = Llb_ManGroupAlloc( pMan ); - Vec_PtrPush( p->vOuts, pObj ); - Aig_ManIncrementTravId( pMan->pAig ); - if ( Aig_ObjIsCo(pObj) ) - Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin0(pObj), p->vIns ); - else - { - Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin0(pObj), p->vIns ); - Llb_ManGroupCreate_rec( pMan->pAig, Aig_ObjFanin1(pObj), p->vIns ); - } - // derive internal objects - assert( p->vNodes == NULL ); - p->vNodes = Llb_ManGroupCollect( p ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Grp_t * Llb_ManGroupCreateFirst( Llb_Man_t * pMan ) -{ - Llb_Grp_t * p; - Aig_Obj_t * pObj; - int i; - p = Llb_ManGroupAlloc( pMan ); - Saig_ManForEachLo( pMan->pAig, pObj, i ) - Vec_PtrPush( p->vOuts, pObj ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Grp_t * Llb_ManGroupCreateLast( Llb_Man_t * pMan ) -{ - Llb_Grp_t * p; - Aig_Obj_t * pObj; - int i; - p = Llb_ManGroupAlloc( pMan ); - Saig_ManForEachLi( pMan->pAig, pObj, i ) - Vec_PtrPush( p->vIns, pObj ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Grp_t * Llb_ManGroupsCombine( Llb_Grp_t * p1, Llb_Grp_t * p2 ) -{ - Llb_Grp_t * p; - Aig_Obj_t * pObj; - int i; - p = Llb_ManGroupAlloc( p1->pMan ); - // create inputs - Vec_PtrForEachEntry( Aig_Obj_t *, p1->vIns, pObj, i ) - Vec_PtrPush( p->vIns, pObj ); - Vec_PtrForEachEntry( Aig_Obj_t *, p2->vIns, pObj, i ) - Vec_PtrPushUnique( p->vIns, pObj ); - // create outputs - Vec_PtrForEachEntry( Aig_Obj_t *, p1->vOuts, pObj, i ) - Vec_PtrPush( p->vOuts, pObj ); - Vec_PtrForEachEntry( Aig_Obj_t *, p2->vOuts, pObj, i ) - Vec_PtrPushUnique( p->vOuts, pObj ); - - // derive internal objects - assert( p->vNodes == NULL ); - p->vNodes = Llb_ManGroupCollect( p ); - return p; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManGroupMarkNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return; - if ( Aig_ObjIsTravIdPrevious(p, pObj) ) - { - Aig_ObjSetTravIdCurrent(p, pObj); - return; - } - Aig_ObjSetTravIdCurrent(p, pObj); - assert( Aig_ObjIsNode(pObj) ); - Llb_ManGroupMarkNodes_rec( p, Aig_ObjFanin0(pObj) ); - Llb_ManGroupMarkNodes_rec( p, Aig_ObjFanin1(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Creates group from two cuts derived by the flow computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Grp_t * Llb_ManGroupCreateFromCuts( Llb_Man_t * pMan, Vec_Int_t * vCut1, Vec_Int_t * vCut2 ) -{ - Llb_Grp_t * p; - Aig_Obj_t * pObj; - int i; - p = Llb_ManGroupAlloc( pMan ); - - // mark Cut1 - Aig_ManIncrementTravId( pMan->pAig ); - Aig_ManForEachObjVec( vCut1, pMan->pAig, pObj, i ) - Aig_ObjSetTravIdCurrent( pMan->pAig, pObj ); - // collect unmarked Cut2 - Aig_ManForEachObjVec( vCut2, pMan->pAig, pObj, i ) - if ( !Aig_ObjIsTravIdCurrent( pMan->pAig, pObj ) ) - Vec_PtrPush( p->vOuts, pObj ); - - // mark nodes reachable from Cut2 - Aig_ManIncrementTravId( pMan->pAig ); - Aig_ManForEachObjVec( vCut2, pMan->pAig, pObj, i ) - Llb_ManGroupMarkNodes_rec( pMan->pAig, pObj ); - // collect marked Cut1 - Aig_ManForEachObjVec( vCut1, pMan->pAig, pObj, i ) - if ( Aig_ObjIsTravIdCurrent( pMan->pAig, pObj ) ) - Vec_PtrPush( p->vIns, pObj ); - - // derive internal objects - assert( p->vNodes == NULL ); - p->vNodes = Llb_ManGroupCollect( p ); - return p; -} - - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManPrepareGroups( Llb_Man_t * pMan ) -{ - Aig_Obj_t * pObj; - int i; - assert( pMan->vGroups == NULL ); - pMan->vGroups = Vec_PtrAlloc( 1000 ); - Llb_ManGroupCreateFirst( pMan ); - Aig_ManForEachNode( pMan->pAig, pObj, i ) - { - if ( pObj->fMarkA ) - Llb_ManGroupCreate( pMan, pObj ); - } - Saig_ManForEachLi( pMan->pAig, pObj, i ) - { - if ( pObj->fMarkA ) - Llb_ManGroupCreate( pMan, pObj ); - } - Llb_ManGroupCreateLast( pMan ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManPrintSpan( Llb_Man_t * p ) -{ - Llb_Grp_t * pGroup; - Aig_Obj_t * pVar; - int i, k, Span = 0, SpanMax = 0; - Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGroup, i ) - { - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) - if ( Vec_IntEntry(p->vVarBegs, pVar->Id) == i ) - Span++; - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) - if ( Vec_IntEntry(p->vVarBegs, pVar->Id) == i ) - Span++; - - SpanMax = Abc_MaxInt( SpanMax, Span ); -printf( "%d ", Span ); - - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) - if ( Vec_IntEntry(p->vVarEnds, pVar->Id) == i ) - Span--; - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) - if ( Vec_IntEntry(p->vVarEnds, pVar->Id) == i ) - Span--; - } -printf( "\n" ); -printf( "Max = %d\n", SpanMax ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManGroupHasVar( Llb_Man_t * p, int iGroup, int iVar ) -{ - Llb_Grp_t * pGroup = (Llb_Grp_t *)Vec_PtrEntry( p->vGroups, iGroup ); - Aig_Obj_t * pObj; - int i; - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) - if ( pObj->Id == iVar ) - return 1; - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) - if ( pObj->Id == iVar ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManPrintHisto( Llb_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i, k; - Aig_ManForEachObj( p->pAig, pObj, i ) - { - if ( Vec_IntEntry(p->vObj2Var, i) < 0 ) - continue; - printf( "%3d :", i ); - for ( k = 0; k < Vec_IntEntry(p->vVarBegs, i); k++ ) - printf( " " ); - for ( ; k <= Vec_IntEntry(p->vVarEnds, i); k++ ) - printf( "%c", Llb_ManGroupHasVar(p, k, i)? '*':'-' ); - printf( "\n" ); - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/llb/llb1Hint.c b/src/proof/llb/llb1Hint.c deleted file mode 100644 index 353b4c69..00000000 --- a/src/proof/llb/llb1Hint.c +++ /dev/null @@ -1,226 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb1Hint.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Cofactors the circuit w.r.t. the high-fanout variables.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb1Hint.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns CI index with the largest number of fanouts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManMaxFanoutCi( Aig_Man_t * pAig ) -{ - Aig_Obj_t * pObj; - int i, WeightMax = -ABC_INFINITY, iInput = -1; - Aig_ManForEachCi( pAig, pObj, i ) - if ( WeightMax < Aig_ObjRefs(pObj) ) - { - WeightMax = Aig_ObjRefs(pObj); - iInput = i; - } - assert( iInput >= 0 ); - return iInput; -} - -/**Function************************************************************* - - Synopsis [Derives AIG whose PI is substituted by a constant.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Llb_ManPerformHints( Aig_Man_t * pAig, int nHintDepth ) -{ - Aig_Man_t * pNew, * pTemp; - int i, iInput; - pNew = Aig_ManDupDfs( pAig ); - for ( i = 0; i < nHintDepth; i++ ) - { - iInput = Llb_ManMaxFanoutCi( pNew ); - Abc_Print( 1, "%d %3d\n", i, iInput ); - pNew = Aig_ManDupCof( pTemp = pNew, iInput, 1 ); - Aig_ManStop( pTemp ); - } - return pNew; -} - -/**Function************************************************************* - - Synopsis [Returns CI index with the largest number of fanouts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_ManCollectHighFanoutObjects( Aig_Man_t * pAig, int nCandMax, int fCisOnly ) -{ - Vec_Int_t * vFanouts, * vResult; - Aig_Obj_t * pObj; - int i, fChanges, PivotValue; -// int Entry; - // collect fanout counts - vFanouts = Vec_IntAlloc( 100 ); - Aig_ManForEachObj( pAig, pObj, i ) - { -// if ( !Aig_ObjIsCi(pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) - if ( !Saig_ObjIsLo(pAig,pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) - continue; - Vec_IntPush( vFanouts, Aig_ObjRefs(pObj) ); - } - Vec_IntSort( vFanouts, 1 ); - // pick the separator - nCandMax = Abc_MinInt( nCandMax, Vec_IntSize(vFanouts) - 1 ); - PivotValue = Vec_IntEntry( vFanouts, nCandMax ); - Vec_IntFree( vFanouts ); - // collect obj satisfying the constraints - vResult = Vec_IntAlloc( 100 ); - Aig_ManForEachObj( pAig, pObj, i ) - { -// if ( !Aig_ObjIsCi(pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) - if ( !Saig_ObjIsLo(pAig,pObj) && (fCisOnly || !Aig_ObjIsNode(pObj)) ) - continue; - if ( Aig_ObjRefs(pObj) < PivotValue ) - continue; - Vec_IntPush( vResult, Aig_ObjId(pObj) ); - } - assert( Vec_IntSize(vResult) >= nCandMax ); - // order in the decreasing order of fanouts - do - { - fChanges = 0; - for ( i = 0; i < Vec_IntSize(vResult) - 1; i++ ) - if ( Aig_ObjRefs(Aig_ManObj(pAig, Vec_IntEntry(vResult, i))) < - Aig_ObjRefs(Aig_ManObj(pAig, Vec_IntEntry(vResult, i+1))) ) - { - int Temp = Vec_IntEntry( vResult, i ); - Vec_IntWriteEntry( vResult, i, Vec_IntEntry(vResult, i+1) ); - Vec_IntWriteEntry( vResult, i+1, Temp ); - fChanges = 1; - } - } - while ( fChanges ); -/* - Vec_IntForEachEntry( vResult, Entry, i ) - printf( "%d ", Aig_ObjRefs(Aig_ManObj(pAig, Entry)) ); -printf( "\n" ); -*/ - return vResult; -} - -/**Function************************************************************* - - Synopsis [Derives AIG whose PI is substituted by a constant.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManModelCheckAigWithHints( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars ) -{ - DdManager * ddGlo = NULL; - Vec_Int_t * vHints; - Vec_Int_t * vHFCands; - int i, Entry, RetValue = -1; - abctime clk = Abc_Clock(); - assert( pPars->nHintDepth > 0 ); -/* - // perform reachability without hints - RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, NULL, NULL ); - if ( RetValue >= 0 ) - return RetValue; -*/ - // create hints representation - vHFCands = Llb_ManCollectHighFanoutObjects( pAigGlo, pPars->nHintDepth+pPars->HintFirst, 1 ); - vHints = Vec_IntStartFull( Aig_ManObjNumMax(pAigGlo) ); - // add one hint at a time till the problem is solved - Vec_IntForEachEntryStart( vHFCands, Entry, i, pPars->HintFirst ) - { - Vec_IntWriteEntry( vHints, Entry, 1 ); // change to 1 to start from zero cof!!! - // solve under hints - RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, vHints, &ddGlo ); - if ( RetValue == 0 ) - goto Finish; - if ( RetValue == 1 ) - break; - } - if ( RetValue == -1 ) - goto Finish; - // undo the hints one at a time - for ( ; i >= pPars->HintFirst; i-- ) - { - Entry = Vec_IntEntry( vHFCands, i ); - Vec_IntWriteEntry( vHints, Entry, -1 ); - // solve under relaxed hints - RetValue = Llb_ManModelCheckAig( pAigGlo, pPars, vHints, &ddGlo ); - if ( RetValue == 0 ) - goto Finish; - if ( RetValue == 1 ) - continue; - break; - } -Finish: - if ( ddGlo ) - { - if ( ddGlo->bFunc ) - Cudd_RecursiveDeref( ddGlo, ddGlo->bFunc ); - Extra_StopManager( ddGlo ); - } - Vec_IntFreeP( &vHFCands ); - Vec_IntFreeP( &vHints ); - if ( pPars->fVerbose ) - Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clk ); - return RetValue; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/llb/llb1Man.c b/src/proof/llb/llb1Man.c deleted file mode 100644 index f5de25e0..00000000 --- a/src/proof/llb/llb1Man.c +++ /dev/null @@ -1,218 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb1Man.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Reachability manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb1Man.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManPrepareVarMap( Llb_Man_t * p ) -{ - Aig_Obj_t * pObjLi, * pObjLo; - int i, iVarLi, iVarLo; - assert( p->vNs2Glo == NULL ); - assert( p->vCs2Glo == NULL ); - assert( p->vGlo2Cs == NULL ); - assert( p->vGlo2Ns == NULL ); - p->vNs2Glo = Vec_IntStartFull( Vec_IntSize(p->vVar2Obj) ); - p->vCs2Glo = Vec_IntStartFull( Vec_IntSize(p->vVar2Obj) ); - p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); - p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); - Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) - { - iVarLi = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLi)); - iVarLo = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLo)); - assert( iVarLi >= 0 && iVarLi < Vec_IntSize(p->vVar2Obj) ); - assert( iVarLo >= 0 && iVarLo < Vec_IntSize(p->vVar2Obj) ); - Vec_IntWriteEntry( p->vNs2Glo, iVarLi, i ); - Vec_IntWriteEntry( p->vCs2Glo, iVarLo, i ); - Vec_IntWriteEntry( p->vGlo2Cs, i, iVarLo ); - Vec_IntWriteEntry( p->vGlo2Ns, i, iVarLi ); - } - // add mapping of the PIs - Saig_ManForEachPi( p->pAig, pObjLo, i ) - { - iVarLo = Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObjLo)); - Vec_IntWriteEntry( p->vCs2Glo, iVarLo, Aig_ManRegNum(p->pAig)+i ); - Vec_IntWriteEntry( p->vNs2Glo, iVarLo, Aig_ManRegNum(p->pAig)+i ); - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManPrepareVarLimits( Llb_Man_t * p ) -{ - Llb_Grp_t * pGroup; - Aig_Obj_t * pVar; - int i, k; - assert( p->vVarBegs == NULL ); - assert( p->vVarEnds == NULL ); - p->vVarEnds = Vec_IntStart( Aig_ManObjNumMax(p->pAig) ); - p->vVarBegs = Vec_IntStart( Aig_ManObjNumMax(p->pAig) ); - Vec_IntFill( p->vVarBegs, Aig_ManObjNumMax(p->pAig), p->pMatrix->nCols ); - - for ( i = 0; i < p->pMatrix->nCols; i++ ) - { - pGroup = p->pMatrix->pColGrps[i]; - - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) - if ( Vec_IntEntry(p->vVarBegs, pVar->Id) > i ) - Vec_IntWriteEntry( p->vVarBegs, pVar->Id, i ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) - if ( Vec_IntEntry(p->vVarBegs, pVar->Id) > i ) - Vec_IntWriteEntry( p->vVarBegs, pVar->Id, i ); - - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pVar, k ) - if ( Vec_IntEntry(p->vVarEnds, pVar->Id) < i ) - Vec_IntWriteEntry( p->vVarEnds, pVar->Id, i ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pVar, k ) - if ( Vec_IntEntry(p->vVarEnds, pVar->Id) < i ) - Vec_IntWriteEntry( p->vVarEnds, pVar->Id, i ); - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManStop( Llb_Man_t * p ) -{ - Llb_Grp_t * pGrp; - DdNode * bTemp; - int i; - -// Vec_IntFreeP( &p->vMem ); -// Vec_PtrFreeP( &p->vTops ); -// Vec_PtrFreeP( &p->vBots ); -// Vec_VecFreeP( (Vec_Vec_t **)&p->vCuts ); - - if ( p->pMatrix ) - Llb_MtrFree( p->pMatrix ); - Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGrp, i ) - Llb_ManGroupStop( pGrp ); - if ( p->dd ) - { -// printf( "Manager dd\n" ); - Extra_StopManager( p->dd ); - } - if ( p->ddG ) - { -// printf( "Manager ddG\n" ); - if ( p->ddG->bFunc ) - Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc ); - Extra_StopManager( p->ddG ); - } - if ( p->ddR ) - { -// printf( "Manager ddR\n" ); - if ( p->ddR->bFunc ) - Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc ); - Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i ) - Cudd_RecursiveDeref( p->ddR, bTemp ); - Extra_StopManager( p->ddR ); - } - Aig_ManStop( p->pAig ); - Vec_PtrFreeP( &p->vGroups ); - Vec_IntFreeP( &p->vVar2Obj ); - Vec_IntFreeP( &p->vObj2Var ); - Vec_IntFreeP( &p->vVarBegs ); - Vec_IntFreeP( &p->vVarEnds ); - Vec_PtrFreeP( &p->vRings ); - Vec_IntFreeP( &p->vNs2Glo ); - Vec_IntFreeP( &p->vCs2Glo ); - Vec_IntFreeP( &p->vGlo2Cs ); - Vec_IntFreeP( &p->vGlo2Ns ); -// Vec_IntFreeP( &p->vHints ); - ABC_FREE( p ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Man_t * Llb_ManStart( Aig_Man_t * pAigGlo, Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) -{ - Llb_Man_t * p; - Aig_ManCleanMarkA( pAig ); - p = ABC_CALLOC( Llb_Man_t, 1 ); - p->pAigGlo = pAigGlo; - p->pPars = pPars; - p->pAig = pAig; - p->vVar2Obj = Llb_ManMarkPivotNodes( p->pAig, pPars->fUsePivots ); - p->vObj2Var = Vec_IntInvert( p->vVar2Obj, -1 ); - p->vRings = Vec_PtrAlloc( 100 ); - Llb_ManPrepareVarMap( p ); - Llb_ManPrepareGroups( p ); - Aig_ManCleanMarkA( pAig ); - p->pMatrix = Llb_MtrCreate( p ); - p->pMatrix->pMan = p; - return p; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/llb/llb1Matrix.c b/src/proof/llb/llb1Matrix.c deleted file mode 100644 index 7aa9c744..00000000 --- a/src/proof/llb/llb1Matrix.c +++ /dev/null @@ -1,430 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb1Matrix.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Partition clustering as a matrix problem.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb1Matrix.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// 0123 nCols -// +---------------------> -// pi 0 | 111 row0 pRowSums[0] -// pi 1 | 1 11 row1 pRowSums[1] -// pi 2 | 1 11 row2 pRowSums[2] -// CS |1 1 -// CS |1 111 -// CS |111 111 -// int | 11111 -// int | 111 -// int | 111 -// int | 111 -// NS | 11 11 -// NS | 11 1 -// NS | 111 -// nRows | -// v -// cccc pColSums[0] -// oooo pColSums[1] -// llll pColSums[2] -// 0123 pColSums[3] - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Verify columns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrVerifyRowsAll( Llb_Mtr_t * p ) -{ - int iRow, iCol, Counter; - for ( iCol = 0; iCol < p->nCols; iCol++ ) - { - Counter = 0; - for ( iRow = 0; iRow < p->nRows; iRow++ ) - if ( p->pMatrix[iCol][iRow] == 1 ) - Counter++; - assert( Counter == p->pColSums[iCol] ); - } -} - -/**Function************************************************************* - - Synopsis [Verify columns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrVerifyColumnsAll( Llb_Mtr_t * p ) -{ - int iRow, iCol, Counter; - for ( iRow = 0; iRow < p->nRows; iRow++ ) - { - Counter = 0; - for ( iCol = 0; iCol < p->nCols; iCol++ ) - if ( p->pMatrix[iCol][iRow] == 1 ) - Counter++; - assert( Counter == p->pRowSums[iRow] ); - } -} - -/**Function************************************************************* - - Synopsis [Verify columns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrVerifyMatrix( Llb_Mtr_t * p ) -{ - Llb_MtrVerifyRowsAll( p ); - Llb_MtrVerifyColumnsAll( p ); -} - -/**Function************************************************************* - - Synopsis [Sort variables in the order of removal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int * Llb_MtrFindVarOrder( Llb_Mtr_t * p ) -{ - int * pOrder, * pLast; - int i, k, fChanges, Temp; - pOrder = ABC_CALLOC( int, p->nRows ); - pLast = ABC_CALLOC( int, p->nRows ); - for ( i = 0; i < p->nRows; i++ ) - { - pOrder[i] = i; - for ( k = p->nCols - 1; k >= 0; k-- ) - if ( p->pMatrix[k][i] ) - { - pLast[i] = k; - break; - } - } - do - { - fChanges = 0; - for ( i = 0; i < p->nRows - 1; i++ ) - if ( pLast[i] > pLast[i+1] ) - { - Temp = pOrder[i]; - pOrder[i] = pOrder[i+1]; - pOrder[i+1] = Temp; - - Temp = pLast[i]; - pLast[i] = pLast[i+1]; - pLast[i+1] = Temp; - - fChanges = 1; - } - } - while ( fChanges ); - ABC_FREE( pLast ); - return pOrder; -} - -/**Function************************************************************* - - Synopsis [Returns type of a variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Llb_MtrVarName( Llb_Mtr_t * p, int iVar ) -{ - static char Buffer[10]; - if ( iVar < p->nPis ) - strcpy( Buffer, "pi" ); - else if ( iVar < p->nPis + p->nFfs ) - strcpy( Buffer, "CS" ); - else if ( iVar >= p->nRows - p->nFfs ) - strcpy( Buffer, "NS" ); - else - strcpy( Buffer, "int" ); - return Buffer; -} - -/**Function************************************************************* - - Synopsis [Creates one column with vars in the array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrPrint( Llb_Mtr_t * p, int fOrder ) -{ - int * pOrder = NULL; - int i, iRow, iCol; - if ( fOrder ) - pOrder = Llb_MtrFindVarOrder( p ); - for ( i = 0; i < p->nRows; i++ ) - { - iRow = pOrder ? pOrder[i] : i; - printf( "%3d : ", iRow ); - printf( "%3d ", p->pRowSums[iRow] ); - printf( "%3s ", Llb_MtrVarName(p, iRow) ); - for ( iCol = 0; iCol < p->nCols; iCol++ ) - printf( "%c", p->pMatrix[iCol][iRow] ? '*' : ' ' ); - printf( "\n" ); - } - ABC_FREE( pOrder ); -} - -/**Function************************************************************* - - Synopsis [Verify columns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrPrintMatrixStats( Llb_Mtr_t * p ) -{ - int iVar, iGrp, iGrp1, iGrp2, Span = 0, nCutSize = 0, nCutSizeMax = 0; - int * pGrp1 = ABC_CALLOC( int, p->nRows ); - int * pGrp2 = ABC_CALLOC( int, p->nRows ); - for ( iVar = 0; iVar < p->nRows; iVar++ ) - { - if ( p->pRowSums[iVar] == 0 ) - continue; - for ( iGrp1 = 0; iGrp1 < p->nCols; iGrp1++ ) - if ( p->pMatrix[iGrp1][iVar] == 1 ) - break; - for ( iGrp2 = p->nCols - 1; iGrp2 >= 0; iGrp2-- ) - if ( p->pMatrix[iGrp2][iVar] == 1 ) - break; - assert( iGrp1 <= iGrp2 ); - pGrp1[iVar] = iGrp1; - pGrp2[iVar] = iGrp2; - Span += iGrp2 - iGrp1; - } - // compute span - for ( iGrp = 0; iGrp < p->nCols; iGrp++ ) - { - for ( iVar = 0; iVar < p->nRows; iVar++ ) - if ( pGrp1[iVar] == iGrp ) - nCutSize++; - if ( nCutSizeMax < nCutSize ) - nCutSizeMax = nCutSize; - for ( iVar = 0; iVar < p->nRows; iVar++ ) - if ( pGrp2[iVar] == iGrp ) - nCutSize--; - } - ABC_FREE( pGrp1 ); - ABC_FREE( pGrp2 ); - printf( "[%4d x %4d] Life-span =%6.2f Max-cut =%5d\n", - p->nCols, p->nRows, 1.0*Span/p->nRows, nCutSizeMax ); - if ( nCutSize ) - Abc_Print( -1, "Cut size is not zero (%d).\n", nCutSize ); -} - - - -/**Function************************************************************* - - Synopsis [Starts the matrix representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Mtr_t * Llb_MtrAlloc( int nPis, int nFfs, int nCols, int nRows ) -{ - Llb_Mtr_t * p; - int i; - p = ABC_CALLOC( Llb_Mtr_t, 1 ); - p->nPis = nPis; - p->nFfs = nFfs; - p->nRows = nRows; - p->nCols = nCols; - p->pRowSums = ABC_CALLOC( int, nRows ); - p->pColSums = ABC_CALLOC( int, nCols ); - p->pColGrps = ABC_CALLOC( Llb_Grp_t *, nCols ); - p->pMatrix = ABC_CALLOC( char *, nCols ); - for ( i = 0; i < nCols; i++ ) - p->pMatrix[i] = ABC_CALLOC( char, nRows ); - // partial product - p->pProdVars = ABC_CALLOC( char, nRows ); // variables in the partial product - p->pProdNums = ABC_CALLOC( int, nRows ); // var counts in the remaining partitions - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the matrix representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrFree( Llb_Mtr_t * p ) -{ - int i; - ABC_FREE( p->pProdVars ); - ABC_FREE( p->pProdNums ); - for ( i = 0; i < p->nCols; i++ ) - ABC_FREE( p->pMatrix[i] ); - ABC_FREE( p->pRowSums ); - ABC_FREE( p->pColSums ); - ABC_FREE( p->pMatrix ); - ABC_FREE( p->pColGrps ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Creates one column with vars in the array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrAddColumn( Llb_Mtr_t * p, Llb_Grp_t * pGrp ) -{ - Aig_Obj_t * pVar; - int i, iRow, iCol = pGrp->Id; - assert( iCol >= 0 && iCol < p->nCols ); - p->pColGrps[iCol] = pGrp; - Vec_PtrForEachEntry( Aig_Obj_t *, pGrp->vIns, pVar, i ) - { - iRow = Vec_IntEntry( pGrp->pMan->vObj2Var, Aig_ObjId(pVar) ); - assert( iRow >= 0 && iRow < p->nRows ); - p->pMatrix[iCol][iRow] = 1; - p->pColSums[iCol]++; - p->pRowSums[iRow]++; - } - Vec_PtrForEachEntry( Aig_Obj_t *, pGrp->vOuts, pVar, i ) - { - iRow = Vec_IntEntry( pGrp->pMan->vObj2Var, Aig_ObjId(pVar) ); - assert( iRow >= 0 && iRow < p->nRows ); - p->pMatrix[iCol][iRow] = 1; - p->pColSums[iCol]++; - p->pRowSums[iRow]++; - } -} - -/**Function************************************************************* - - Synopsis [Matrix reduce.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrRemoveSingletonRows( Llb_Mtr_t * p ) -{ - int i, k; - for ( i = 0; i < p->nRows; i++ ) - if ( p->pRowSums[i] < 2 ) - { - p->pRowSums[i] = 0; - for ( k = 0; k < p->nCols; k++ ) - { - if ( p->pMatrix[k][i] == 1 ) - { - p->pMatrix[k][i] = 0; - p->pColSums[k]--; - } - } - } -} - -/**Function************************************************************* - - Synopsis [Matrix reduce.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Mtr_t * Llb_MtrCreate( Llb_Man_t * p ) -{ - Llb_Mtr_t * pMatrix; - Llb_Grp_t * pGroup; - int i; - pMatrix = Llb_MtrAlloc( Saig_ManPiNum(p->pAig), Saig_ManRegNum(p->pAig), - Vec_PtrSize(p->vGroups), Vec_IntSize(p->vVar2Obj) ); - Vec_PtrForEachEntry( Llb_Grp_t *, p->vGroups, pGroup, i ) - Llb_MtrAddColumn( pMatrix, pGroup ); -// Llb_MtrRemoveSingletonRows( pMatrix ); - return pMatrix; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/llb/llb1Pivot.c b/src/proof/llb/llb1Pivot.c deleted file mode 100644 index 7a5bb66f..00000000 --- a/src/proof/llb/llb1Pivot.c +++ /dev/null @@ -1,254 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb1Pivot.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Determining pivot variables.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb1Pivot.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManTracePaths_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pPivot ) -{ - Aig_Obj_t * pFanout; - int k, iFan = -1; - if ( Aig_ObjIsTravIdPrevious(p, pObj) ) - return 0; - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return 1; - if ( Saig_ObjIsLi(p, pObj) ) - return 0; - if ( Saig_ObjIsPo(p, pObj) ) - return 0; - if ( pObj == pPivot ) - return 1; - assert( Aig_ObjIsCand(pObj) ); - Aig_ObjForEachFanout( p, pObj, pFanout, iFan, k ) - if ( !Llb_ManTracePaths_rec( p, pFanout, pPivot ) ) - { - Aig_ObjSetTravIdPrevious(p, pObj); - return 0; - } - Aig_ObjSetTravIdCurrent(p, pObj); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManTracePaths( Aig_Man_t * p, Aig_Obj_t * pPivot ) -{ - Aig_Obj_t * pObj; - int i, Counter = 0; - Aig_ManIncrementTravId( p ); // prev = visited with path to LI (value 0) - Aig_ManIncrementTravId( p ); // cur = visited w/o path to LI (value 1) - Saig_ManForEachLo( p, pObj, i ) - Counter += Llb_ManTracePaths_rec( p, pObj, pPivot ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManTestCuts( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i, Count; - Aig_ManFanoutStart( p ); - Aig_ManForEachNode( p, pObj, i ) - { - if ( Aig_ObjRefs(pObj) <= 1 ) - continue; - Count = Llb_ManTracePaths( p, pObj ); - printf( "Obj =%5d. Lev =%3d. Fanout =%5d. Count = %3d.\n", - i, Aig_ObjLevel(pObj), Aig_ObjRefs(pObj), Count ); - } - Aig_ManFanoutStop( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManLabelLiCones_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - if ( pObj->fMarkB ) - return; - pObj->fMarkB = 1; - assert( Aig_ObjIsNode(pObj) ); - Llb_ManLabelLiCones_rec( p, Aig_ObjFanin0(pObj) ); - Llb_ManLabelLiCones_rec( p, Aig_ObjFanin1(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Determine starting cut-points.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManLabelLiCones( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - // mark const and PIs - Aig_ManConst1(p)->fMarkB = 1; - Aig_ManForEachCi( p, pObj, i ) - pObj->fMarkB = 1; - // mark cones - Saig_ManForEachLi( p, pObj, i ) - Llb_ManLabelLiCones_rec( p, Aig_ObjFanin0(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Determine starting cut-points.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManMarkInternalPivots( Aig_Man_t * p ) -{ - Vec_Ptr_t * vMuxes; - Aig_Obj_t * pObj; - int i, Counter = 0; - - // remove refs due to MUXes - vMuxes = Aig_ManMuxesCollect( p ); - Aig_ManMuxesDeref( p, vMuxes ); - - // mark nodes feeding into LIs - Aig_ManCleanMarkB( p ); - Llb_ManLabelLiCones( p ); - - // mark internal nodes - Aig_ManFanoutStart( p ); - Aig_ManForEachNode( p, pObj, i ) - if ( pObj->fMarkB && pObj->nRefs > 1 ) - { - if ( Llb_ManTracePaths(p, pObj) > 0 ) - pObj->fMarkA = 1; - Counter++; - } - Aig_ManFanoutStop( p ); -// printf( "TracePath tried = %d.\n", Counter ); - - // mark nodes feeding into LIs - Aig_ManCleanMarkB( p ); - - // add refs due to MUXes - Aig_ManMuxesRef( p, vMuxes ); - Vec_PtrFree( vMuxes ); -} - -/**Function************************************************************* - - Synopsis [Determine starting cut-points.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_ManMarkPivotNodes( Aig_Man_t * p, int fUseInternal ) -{ - Vec_Int_t * vVar2Obj; - Aig_Obj_t * pObj; - int i; - // mark inputs/outputs - Aig_ManForEachCi( p, pObj, i ) - pObj->fMarkA = 1; - Saig_ManForEachLi( p, pObj, i ) - pObj->fMarkA = 1; - - // mark internal pivot nodes - if ( fUseInternal ) - Llb_ManMarkInternalPivots( p ); - - // assign variable numbers - Aig_ManConst1(p)->fMarkA = 0; - vVar2Obj = Vec_IntAlloc( 100 ); - Aig_ManForEachCi( p, pObj, i ) - Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) ); - Aig_ManForEachNode( p, pObj, i ) - if ( pObj->fMarkA ) - Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) ); - Saig_ManForEachLi( p, pObj, i ) - Vec_IntPush( vVar2Obj, Aig_ObjId(pObj) ); - return vVar2Obj; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/llb/llb1Reach.c b/src/proof/llb/llb1Reach.c deleted file mode 100644 index fae7bee2..00000000 --- a/src/proof/llb/llb1Reach.c +++ /dev/null @@ -1,904 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb1Reach.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Reachability analysis.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb1Reach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Derives global BDD for the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ManConstructOutBdd( Aig_Man_t * pAig, Aig_Obj_t * pNode, DdManager * dd ) -{ - DdNode * bBdd0, * bBdd1, * bFunc; - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj = NULL; - int i; - abctime TimeStop; - if ( Aig_ObjFanin0(pNode) == Aig_ManConst1(pAig) ) - return Cudd_NotCond( Cudd_ReadOne(dd), Aig_ObjFaninC0(pNode) ); - TimeStop = dd->TimeStop; dd->TimeStop = 0; - vNodes = Aig_ManDfsNodes( pAig, &pNode, 1 ); - assert( Vec_PtrSize(vNodes) > 0 ); - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - { - if ( !Aig_ObjIsNode(pObj) ) - continue; - bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bBdd1 = Cudd_NotCond( Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); - pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData ); - } - bFunc = (DdNode *)pObj->pData; Cudd_Ref( bFunc ); - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - { - if ( !Aig_ObjIsNode(pObj) ) - continue; - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - } - Vec_PtrFree( vNodes ); - if ( Aig_ObjIsCo(pNode) ) - bFunc = Cudd_NotCond( bFunc, Aig_ObjFaninC0(pNode) ); - Cudd_Deref( bFunc ); - dd->TimeStop = TimeStop; - return bFunc; -} - -/**Function************************************************************* - - Synopsis [Derives BDD for the group.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ManConstructGroupBdd( Llb_Man_t * p, Llb_Grp_t * pGroup ) -{ - Aig_Obj_t * pObj; - DdNode * bBdd0, * bBdd1, * bRes, * bXor, * bTemp; - int i, k; - Aig_ManConst1(p->pAig)->pData = Cudd_ReadOne( p->dd ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) - pObj->pData = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vNodes, pObj, i ) - { - bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bBdd1 = Cudd_NotCond( Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); -// pObj->pData = Extra_bddAndTime( p->dd, bBdd0, bBdd1, p->pPars->TimeTarget ); - pObj->pData = Cudd_bddAnd( p->dd, bBdd0, bBdd1 ); - if ( pObj->pData == NULL ) - { - Vec_PtrForEachEntryStop( Aig_Obj_t *, pGroup->vNodes, pObj, k, i ) - if ( pObj->pData ) - Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData ); - return NULL; - } - Cudd_Ref( (DdNode *)pObj->pData ); - } - bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) - { - if ( Aig_ObjIsCo(pObj) ) - bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - else - bBdd0 = (DdNode *)pObj->pData; - bBdd1 = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); - bXor = Cudd_bddXor( p->dd, bBdd0, bBdd1 ); Cudd_Ref( bXor ); -// bRes = Extra_bddAndTime( p->dd, bTemp = bRes, Cudd_Not(bXor), p->pPars->TimeTarget ); - bRes = Cudd_bddAnd( p->dd, bTemp = bRes, Cudd_Not(bXor) ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bXor ); - Vec_PtrForEachEntryStop( Aig_Obj_t *, pGroup->vNodes, pObj, k, i ) - if ( pObj->pData ) - Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData ); - return NULL; - } - Cudd_Ref( bRes ); - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bXor ); - } - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vNodes, pObj, i ) - Cudd_RecursiveDeref( p->dd, (DdNode *)pObj->pData ); - Cudd_Deref( bRes ); - return bRes; -} - -/**Function************************************************************* - - Synopsis [Derives quantification cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ManConstructQuantCubeIntern( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace, int fBackward ) -{ - Aig_Obj_t * pObj; - DdNode * bRes, * bTemp, * bVar; - int i, iGroupFirst, iGroupLast; - abctime TimeStop; - TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; - bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) - { - if ( fBackward && Saig_ObjIsPi(p->pAig, pObj) ) - continue; - iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); - iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); - assert( iGroupFirst <= iGroupLast ); - if ( iGroupFirst < iGroupLast ) - continue; - bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); - bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) - { - if ( fBackward && Saig_ObjIsPi(p->pAig, pObj) ) - continue; - iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); - iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); - assert( iGroupFirst <= iGroupLast ); - if ( iGroupFirst < iGroupLast ) - continue; - bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); - bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - Cudd_Deref( bRes ); - p->dd->TimeStop = TimeStop; - return bRes; -} - -/**Function************************************************************* - - Synopsis [Derives quantification cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ManConstructQuantCubeFwd( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace ) -{ - Aig_Obj_t * pObj; - DdNode * bRes, * bTemp, * bVar; - int i, iGroupLast; - abctime TimeStop; - TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; - bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) - { - iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); - assert( iGroupLast >= iGrpPlace ); - if ( iGroupLast > iGrpPlace ) - continue; - bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); - bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) - { - iGroupLast = Vec_IntEntry(p->vVarEnds, Aig_ObjId(pObj)); - assert( iGroupLast >= iGrpPlace ); - if ( iGroupLast > iGrpPlace ) - continue; - bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); - bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - Cudd_Deref( bRes ); - p->dd->TimeStop = TimeStop; - return bRes; -} - -/**Function************************************************************* - - Synopsis [Derives quantification cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ManConstructQuantCubeBwd( Llb_Man_t * p, Llb_Grp_t * pGroup, int iGrpPlace ) -{ - Aig_Obj_t * pObj; - DdNode * bRes, * bTemp, * bVar; - int i, iGroupFirst; - abctime TimeStop; - TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; - bRes = Cudd_ReadOne( p->dd ); Cudd_Ref( bRes ); - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vIns, pObj, i ) - { - if ( Saig_ObjIsPi(p->pAig, pObj) ) - continue; - iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); - assert( iGroupFirst <= iGrpPlace ); - if ( iGroupFirst < iGrpPlace ) - continue; - bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); - bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - Vec_PtrForEachEntry( Aig_Obj_t *, pGroup->vOuts, pObj, i ) - { - if ( Saig_ObjIsPi(p->pAig, pObj) ) - continue; - iGroupFirst = Vec_IntEntry(p->vVarBegs, Aig_ObjId(pObj)); - assert( iGroupFirst <= iGrpPlace ); - if ( iGroupFirst < iGrpPlace ) - continue; - bVar = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)) ); - bRes = Cudd_bddAnd( p->dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - Cudd_Deref( bRes ); - p->dd->TimeStop = TimeStop; - return bRes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ManComputeInitState( Llb_Man_t * p, DdManager * dd ) -{ - Aig_Obj_t * pObj; - DdNode * bRes, * bVar, * bTemp; - int i, iVar; - abctime TimeStop; - TimeStop = dd->TimeStop; dd->TimeStop = 0; - bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); - Saig_ManForEachLo( p->pAig, pObj, i ) - { - iVar = (dd == p->ddG) ? i : Vec_IntEntry(p->vObj2Var, Aig_ObjId(pObj)); - bVar = Cudd_bddIthVar( dd, iVar ); - bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bRes ); - dd->TimeStop = TimeStop; - return bRes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ManComputeImage( Llb_Man_t * p, DdNode * bInit, int fBackward ) -{ - int fCheckSupport = 0; - Llb_Grp_t * pGroup; - DdNode * bImage, * bGroup, * bCube, * bTemp; - int k, Index; - bImage = bInit; Cudd_Ref( bImage ); - for ( k = 1; k < p->pMatrix->nCols-1; k++ ) - { - if ( fBackward ) - Index = p->pMatrix->nCols - 1 - k; - else - Index = k; - - // compute group BDD - pGroup = p->pMatrix->pColGrps[Index]; - bGroup = Llb_ManConstructGroupBdd( p, pGroup ); - if ( bGroup == NULL ) - { - Cudd_RecursiveDeref( p->dd, bImage ); - return NULL; - } - Cudd_Ref( bGroup ); - // quantify variables appearing only in this group - bCube = Llb_ManConstructQuantCubeIntern( p, pGroup, Index, fBackward ); Cudd_Ref( bCube ); - bGroup = Cudd_bddExistAbstract( p->dd, bTemp = bGroup, bCube ); - if ( bGroup == NULL ) - { - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bCube ); - return NULL; - } - Cudd_Ref( bGroup ); - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bCube ); - // perform partial product - if ( fBackward ) - bCube = Llb_ManConstructQuantCubeBwd( p, pGroup, Index ); - else - bCube = Llb_ManConstructQuantCubeFwd( p, pGroup, Index ); - Cudd_Ref( bCube ); -// bImage = Extra_bddAndAbstractTime( p->dd, bTemp = bImage, bGroup, bCube, p->pPars->TimeTarget ); - bImage = Cudd_bddAndAbstract( p->dd, bTemp = bImage, bGroup, bCube ); - if ( bImage == NULL ) - { - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bGroup ); - Cudd_RecursiveDeref( p->dd, bCube ); - return NULL; - } - Cudd_Ref( bImage ); - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bGroup ); - Cudd_RecursiveDeref( p->dd, bCube ); - } - - // make sure image depends on next state vars - if ( fCheckSupport ) - { - bCube = Cudd_Support( p->dd, bImage ); Cudd_Ref( bCube ); - for ( bTemp = bCube; bTemp != p->dd->one; bTemp = cuddT(bTemp) ) - { - int ObjId = Vec_IntEntry( p->vVar2Obj, bTemp->index ); - Aig_Obj_t * pObj = Aig_ManObj( p->pAig, ObjId ); - if ( !Saig_ObjIsLi(p->pAig, pObj) ) - printf( "Var %d assigned to obj %d that is not LI\n", bTemp->index, ObjId ); - } - Cudd_RecursiveDeref( p->dd, bCube ); - } - Cudd_Deref( bImage ); - return bImage; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ManCreateConstraints( Llb_Man_t * p, Vec_Int_t * vHints, int fUseNsVars ) -{ - DdNode * bConstr, * bFunc, * bTemp; - Aig_Obj_t * pObj; - int i, Entry; - abctime TimeStop; - if ( vHints == NULL ) - return Cudd_ReadOne( p->dd ); - TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; - assert( Aig_ManCiNum(p->pAig) == Aig_ManCiNum(p->pAigGlo) ); - // assign const and PI nodes to the original AIG - Aig_ManCleanData( p->pAig ); - Aig_ManConst1( p->pAig )->pData = Cudd_ReadOne( p->dd ); - Saig_ManForEachPi( p->pAig, pObj, i ) - pObj->pData = Cudd_bddIthVar( p->dd, Vec_IntEntry(p->vObj2Var,Aig_ObjId(pObj)) ); - Saig_ManForEachLo( p->pAig, pObj, i ) - { - if ( fUseNsVars ) - Entry = Vec_IntEntry( p->vObj2Var, Aig_ObjId(Saig_ObjLoToLi(p->pAig, pObj)) ); - else - Entry = Vec_IntEntry( p->vObj2Var, Aig_ObjId(pObj) ); - pObj->pData = Cudd_bddIthVar( p->dd, Entry ); - } - // transfer them to the global AIG - Aig_ManCleanData( p->pAigGlo ); - Aig_ManConst1( p->pAigGlo )->pData = Cudd_ReadOne( p->dd ); - Aig_ManForEachCi( p->pAigGlo, pObj, i ) - pObj->pData = Aig_ManCi(p->pAig, i)->pData; - // derive consraints - bConstr = Cudd_ReadOne( p->dd ); Cudd_Ref( bConstr ); - Vec_IntForEachEntry( vHints, Entry, i ) - { - if ( Entry != 0 && Entry != 1 ) - continue; - bFunc = Llb_ManConstructOutBdd( p->pAigGlo, Aig_ManObj(p->pAigGlo, i), p->dd ); Cudd_Ref( bFunc ); - bFunc = Cudd_NotCond( bFunc, Entry ); // restrict to not constraint - // make the product - bConstr = Cudd_bddAnd( p->dd, bTemp = bConstr, bFunc ); Cudd_Ref( bConstr ); - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bFunc ); - } - Cudd_Deref( bConstr ); - p->dd->TimeStop = TimeStop; - return bConstr; -} - -/**Function************************************************************* - - Synopsis [Perform reachability with hints and returns reached states in ppGlo.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Cex_t * Llb_ManReachDeriveCex( Llb_Man_t * p ) -{ - Abc_Cex_t * pCex; - Aig_Obj_t * pObj; - DdNode * bState = NULL, * bImage, * bOneCube, * bTemp, * bRing; - int i, v, RetValue, nPiOffset; - char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) ); - assert( Vec_PtrSize(p->vRings) > 0 ); - - p->dd->TimeStop = 0; - p->ddR->TimeStop = 0; - -/* - Saig_ManForEachLo( p->pAig, pObj, i ) - printf( "%d ", pObj->Id ); - printf( "\n" ); - Saig_ManForEachLi( p->pAig, pObj, i ) - printf( "%d(%d) ", pObj->Id, Aig_ObjFaninId0(pObj) ); - printf( "\n" ); -*/ - // allocate room for the counter-example - pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) ); - pCex->iFrame = Vec_PtrSize(p->vRings) - 1; - pCex->iPo = -1; - - // get the last cube - bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc ); Cudd_Ref( bOneCube ); - RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); - Cudd_RecursiveDeref( p->ddR, bOneCube ); - assert( RetValue ); - - // write PIs of counter-example - nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1); - Saig_ManForEachPi( p->pAig, pObj, i ) - if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) - Abc_InfoSetBit( pCex->pData, nPiOffset + i ); - - // write state in terms of NS variables - if ( Vec_PtrSize(p->vRings) > 1 ) - { - bState = Llb_CoreComputeCube( p->dd, p->vGlo2Ns, 1, pValues ); Cudd_Ref( bState ); - } - // perform backward analysis - Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v ) - { - if ( v == Vec_PtrSize(p->vRings) - 1 ) - continue; -//Extra_bddPrintSupport( p->dd, bState ); printf( "\n" ); -//Extra_bddPrintSupport( p->dd, bRing ); printf( "\n" ); - // compute the next states - bImage = Llb_ManComputeImage( p, bState, 1 ); - assert( bImage != NULL ); - Cudd_Ref( bImage ); - Cudd_RecursiveDeref( p->dd, bState ); -//Extra_bddPrintSupport( p->dd, bImage ); printf( "\n" ); - - // move reached states into ring manager - bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) ); Cudd_Ref( bImage ); - Cudd_RecursiveDeref( p->dd, bTemp ); -//Extra_bddPrintSupport( p->ddR, bImage ); printf( "\n" ); - - // intersect with the previous set - bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing ); Cudd_Ref( bOneCube ); - Cudd_RecursiveDeref( p->ddR, bImage ); - - // find any assignment of the BDD - RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); - Cudd_RecursiveDeref( p->ddR, bOneCube ); - assert( RetValue ); -/* - for ( i = 0; i < p->ddR->size; i++ ) - printf( "%d ", pValues[i] ); - printf( "\n" ); -*/ - // write PIs of counter-example - nPiOffset -= Saig_ManPiNum(p->pAig); - Saig_ManForEachPi( p->pAig, pObj, i ) - if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) - Abc_InfoSetBit( pCex->pData, nPiOffset + i ); - - // check that we get the init state - if ( v == 0 ) - { - Saig_ManForEachLo( p->pAig, pObj, i ) - assert( pValues[i] == 0 ); - break; - } - - // write state in terms of NS variables - bState = Llb_CoreComputeCube( p->dd, p->vGlo2Ns, 1, pValues ); Cudd_Ref( bState ); - } - assert( nPiOffset == Saig_ManRegNum(p->pAig) ); - // update the output number -//Abc_CexPrint( pCex ); - RetValue = Saig_ManFindFailedPoCex( p->pAigGlo, pCex ); - assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pAigGlo) ); // invalid CEX!!! - pCex->iPo = RetValue; - // cleanup - ABC_FREE( pValues ); - return pCex; -} - -/**Function************************************************************* - - Synopsis [Perform reachability with hints and returns reached states in ppGlo.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManReachability( Llb_Man_t * p, Vec_Int_t * vHints, DdManager ** pddGlo ) -{ - int * pNs2Glo = Vec_IntArray( p->vNs2Glo ); - int * pCs2Glo = Vec_IntArray( p->vCs2Glo ); - int * pGlo2Cs = Vec_IntArray( p->vGlo2Cs ); - DdNode * bCurrent, * bReached, * bNext, * bTemp, * bCube; - DdNode * bConstrCs, * bConstrNs; - abctime clk2, clk = Abc_Clock(); - int nIters, nBddSize = 0; -// int nThreshold = 10000; - - // compute time to stop - p->pPars->TimeTarget = p->pPars->TimeLimit ? p->pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0; - - // define variable limits - Llb_ManPrepareVarLimits( p ); - - // start the managers - assert( p->dd == NULL ); - assert( p->ddG == NULL ); - assert( p->ddR == NULL ); - p->dd = Cudd_Init( Vec_IntSize(p->vVar2Obj), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - p->ddR = Cudd_Init( Aig_ManCiNum(p->pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - if ( pddGlo && *pddGlo ) - p->ddG = *pddGlo, *pddGlo = NULL; - else - p->ddG = Cudd_Init( Aig_ManRegNum(p->pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - - if ( p->pPars->fReorder ) - { - Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); - Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT ); - Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT ); - } - else - { - Cudd_AutodynDisable( p->dd ); - Cudd_AutodynDisable( p->ddG ); - Cudd_AutodynDisable( p->ddR ); - } - - // set the stop time parameter - p->dd->TimeStop = p->pPars->TimeTarget; - p->ddG->TimeStop = p->pPars->TimeTarget; - p->ddR->TimeStop = p->pPars->TimeTarget; - - // create bad state in the ring manager - p->ddR->bFunc = Llb_BddComputeBad( p->pAigGlo, p->ddR, p->pPars->TimeTarget ); - if ( p->ddR->bFunc == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = -1; - return -1; - } - Cudd_Ref( p->ddR->bFunc ); - - // derive constraints - bConstrCs = Llb_ManCreateConstraints( p, vHints, 0 ); Cudd_Ref( bConstrCs ); - bConstrNs = Llb_ManCreateConstraints( p, vHints, 1 ); Cudd_Ref( bConstrNs ); -//Extra_bddPrint( p->dd, bConstrCs ); printf( "\n" ); -//Extra_bddPrint( p->dd, bConstrNs ); printf( "\n" ); - - // perform reachability analysis - // compute the starting set of states - if ( p->ddG->bFunc ) - { - bReached = p->ddG->bFunc; p->ddG->bFunc = NULL; - bCurrent = Extra_TransferPermute( p->ddG, p->dd, bReached, pGlo2Cs ); Cudd_Ref( bCurrent ); - } - else - { - bReached = Llb_ManComputeInitState( p, p->ddG ); Cudd_Ref( bReached ); - bCurrent = Llb_ManComputeInitState( p, p->dd ); Cudd_Ref( bCurrent ); - } -//Extra_bddPrintSupport( p->ddG, bReached ); printf( "\n" ); -//Extra_bddPrintSupport( p->dd, bCurrent ); printf( "\n" ); - -//Extra_bddPrintSupport( p->dd, bCurrent ); printf( "\n" ); - for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ ) - { - clk2 = Abc_Clock(); - // check the runtime limit - if ( p->pPars->TimeLimit && Abc_Clock() > p->pPars->TimeTarget ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout during image computation (%d seconds).\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; - Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; - Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return -1; - } - - // save the onion ring - bTemp = Extra_TransferPermute( p->dd, p->ddR, bCurrent, pCs2Glo ); - if ( bTemp == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during ring transfer.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; - Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; - Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return -1; - } - Cudd_Ref( bTemp ); - Vec_PtrPush( p->vRings, bTemp ); - - // check it for bad states - if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) ) - { - assert( p->pAigGlo->pSeqModel == NULL ); - if ( !p->pPars->fBackward ) - p->pAigGlo->pSeqModel = Llb_ManReachDeriveCex( p ); - if ( !p->pPars->fSilent ) - { - if ( !p->pPars->fBackward ) - Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", p->pAigGlo->pSeqModel->iPo, p->pAigGlo->pName, p->pAigGlo->pName, nIters ); - else - Abc_Print( 1, "Output ??? of miter \"%s\" was asserted in frame %d (counter-example is not produced). ", p->pAigGlo->pName, nIters ); - Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); - } - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; - Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; - Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return 0; - } - - // restrict reachable states using constraints - if ( vHints ) - { - bCurrent = Cudd_bddAnd( p->dd, bTemp = bCurrent, bConstrCs ); Cudd_Ref( bCurrent ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - - // quantify variables appearing only in the init state - bCube = Llb_ManConstructQuantCubeIntern( p, (Llb_Grp_t *)Vec_PtrEntry(p->vGroups,0), 0, 0 ); Cudd_Ref( bCube ); - bCurrent = Cudd_bddExistAbstract( p->dd, bTemp = bCurrent, bCube ); Cudd_Ref( bCurrent ); - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bCube ); - - // compute the next states - bNext = Llb_ManComputeImage( p, bCurrent, 0 ); - if ( bNext == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; - Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; - Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return -1; - } - Cudd_Ref( bNext ); - Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; - - // restrict reachable states using constraints - if ( vHints ) - { - bNext = Cudd_bddAnd( p->dd, bTemp = bNext, bConstrNs ); Cudd_Ref( bNext ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } -//Extra_bddPrintSupport( p->dd, bNext ); printf( "\n" ); - - // remap these states into the current state vars -// bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pNs2Glo ); Cudd_Ref( bNext ); -// Cudd_RecursiveDeref( p->dd, bTemp ); -// bNext = Extra_TransferPermuteTime( p->dd, p->ddG, bTemp = bNext, pNs2Glo, p->pPars->TimeTarget ); - bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pNs2Glo ); - if ( bNext == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; - Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return -1; - } - Cudd_Ref( bNext ); - Cudd_RecursiveDeref( p->dd, bTemp ); - - - // check if there are any new states - if ( Cudd_bddLeq( p->ddG, bNext, bReached ) ) // implication = no new states - { - Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; - break; - } - - // check the BDD size - nBddSize = Cudd_DagSize(bNext); - if ( nBddSize > p->pPars->nBddMax ) - { - Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; - break; - } - - // get the new states - bCurrent = Cudd_bddAnd( p->ddG, bNext, Cudd_Not(bReached) ); - if ( bCurrent == NULL ) - { - Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - break; - } - Cudd_Ref( bCurrent ); - // minimize the new states with the reached states -// bCurrent = Cudd_bddConstrain( p->ddG, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); -// bCurrent = Cudd_bddRestrict( p->ddG, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); -// Cudd_RecursiveDeref( p->ddG, bTemp ); -//printf( "Initial BDD =%7d. Constrained BDD =%7d.\n", Cudd_DagSize(bTemp), Cudd_DagSize(bCurrent) ); - - // remap these states into the current state vars -// bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs ); Cudd_Ref( bCurrent ); -// Cudd_RecursiveDeref( p->ddG, bTemp ); -// bCurrent = Extra_TransferPermuteTime( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs, p->pPars->TimeTarget ); - bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Cs ); - if ( bCurrent == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->ddG, bTemp ); - Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; - Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return -1; - } - Cudd_Ref( bCurrent ); - Cudd_RecursiveDeref( p->ddG, bTemp ); - - - // add to the reached states - bReached = Cudd_bddOr( p->ddG, bTemp = bReached, bNext ); - if ( bReached == NULL ) - { - Cudd_RecursiveDeref( p->ddG, bTemp ); bTemp = NULL; - Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; - break; - } - Cudd_Ref( bReached ); - Cudd_RecursiveDeref( p->ddG, bTemp ); - Cudd_RecursiveDeref( p->ddG, bNext ); - bNext = NULL; - - if ( p->pPars->fVerbose ) - { - fprintf( stdout, "F =%5d : ", nIters ); - fprintf( stdout, "Im =%6d ", nBddSize ); - fprintf( stdout, "(%4d %3d) ", Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) ); - fprintf( stdout, "Rea =%6d ", Cudd_DagSize(bReached) ); - fprintf( stdout, "(%4d%4d) ", Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) ); - Abc_PrintTime( 1, "Time", Abc_Clock() - clk2 ); - } -/* - if ( p->pPars->fVerbose ) - { - double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); -// Extra_bddPrint( p->ddG, bReached );printf( "\n" ); - fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); - fflush( stdout ); - } -*/ - } - Cudd_RecursiveDeref( p->dd, bConstrCs ); bConstrCs = NULL; - Cudd_RecursiveDeref( p->dd, bConstrNs ); bConstrNs = NULL; - if ( bReached == NULL ) - { - p->pPars->iFrame = nIters - 1; - return 0; // reachable - } -// assert( bCurrent == NULL ); - if ( bCurrent ) - Cudd_RecursiveDeref( p->dd, bCurrent ); - // report the stats - if ( p->pPars->fVerbose ) - { - double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); - if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) - fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters ); - else - fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters ); - fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); - fflush( stdout ); - } - if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) - { - if ( !p->pPars->fSilent ) - printf( "Verified only for states reachable in %d frames. ", nIters ); - p->pPars->iFrame = p->pPars->nIterMax; - Cudd_RecursiveDeref( p->ddG, bReached ); - return -1; // undecided - } - if ( pddGlo ) - { - assert( p->ddG->bFunc == NULL ); - p->ddG->bFunc = bReached; bReached = NULL; - assert( *pddGlo == NULL ); - *pddGlo = p->ddG; p->ddG = NULL; - } - else - Cudd_RecursiveDeref( p->ddG, bReached ); - if ( !p->pPars->fSilent ) - printf( "The miter is proved unreachable after %d iterations. ", nIters ); - p->pPars->iFrame = nIters - 1; - return 1; // unreachable -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/llb/llb1Sched.c b/src/proof/llb/llb1Sched.c deleted file mode 100644 index 51de973a..00000000 --- a/src/proof/llb/llb1Sched.c +++ /dev/null @@ -1,257 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb1Sched.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Partition scheduling algorithm.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb1Sched.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Swaps two rows.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrSwapColumns( Llb_Mtr_t * p, int iCol1, int iCol2 ) -{ - Llb_Grp_t * pGemp; - char * pTemp; - int iTemp; - assert( iCol1 >= 0 && iCol1 < p->nCols ); - assert( iCol2 >= 0 && iCol2 < p->nCols ); - if ( iCol1 == iCol2 ) - return; - assert( iCol1 != iCol2 ); - // swap col groups - pGemp = p->pColGrps[iCol1]; - p->pColGrps[iCol1] = p->pColGrps[iCol2]; - p->pColGrps[iCol2] = pGemp; - // swap col vectors - pTemp = p->pMatrix[iCol1]; - p->pMatrix[iCol1] = p->pMatrix[iCol2]; - p->pMatrix[iCol2] = pTemp; - // swap col sums - iTemp = p->pColSums[iCol1]; - p->pColSums[iCol1] = p->pColSums[iCol2]; - p->pColSums[iCol2] = iTemp; -} - -/**Function************************************************************* - - Synopsis [Find columns which brings as few vars as possible.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_MtrFindBestColumn( Llb_Mtr_t * p, int iGrpStart ) -{ - int Cost, Cost2, CostBest = ABC_INFINITY, Cost2Best = ABC_INFINITY; - int WeightCur, WeightBest = -ABC_INFINITY, iGrp = -1, iGrpBest = -1; - int k, c, iVar, Counter; - // find partition that reduces partial product as much as possible - for ( iVar = 0; iVar < p->nRows - p->nFfs; iVar++ ) - { - if ( p->pRowSums[iVar] < 2 ) - continue; - // look at present variables that can be quantified - if ( !(p->pProdVars[iVar] == 1 && p->pProdNums[iVar] == 1) ) - continue; - // check that it appears in one partition only - Counter = 0; - for ( c = iGrpStart; c < p->nCols-1; c++ ) - if ( p->pMatrix[c][iVar] == 1 ) - { - iGrp = c; - Counter++; - } - assert( Counter == 1 ); - if ( Counter != 1 ) - Abc_Print( -1, "Llb_MtrFindBestColumn() Internal error!\n" ); - // find weight of this column - WeightCur = 0; - for ( k = 0; k < p->nRows; k++ ) - { - // increase weight if variable k will be quantified from partial product - if ( p->pProdVars[k] == 1 && p->pMatrix[iGrp][k] == 1 && p->pProdNums[k] == 1 ) - WeightCur += 2; - // decrease weight if variable k will be added to partial product - if ( p->pProdVars[k] == 0 && p->pMatrix[iGrp][k] == 1 ) - WeightCur--; - } - if ( WeightCur > 0 && WeightBest < WeightCur ) - { - WeightBest = WeightCur; - iGrpBest = iGrp; - } - } - if ( iGrpBest >= 0 ) - return iGrpBest; - // could not find the group with any vars to quantify - // select the group that contains as few extra variables as possible - // if there is a tie, select variables that appear in less groups than others - for ( iGrp = iGrpStart; iGrp < p->nCols-1; iGrp++ ) - { - Cost = Cost2 = 0; - for ( k = 0; k < p->nRows; k++ ) - if ( p->pProdVars[k] == 0 && p->pMatrix[iGrp][k] == 1 ) - { - Cost++; - Cost2 += p->pProdNums[k]; - } - if ( CostBest > Cost || - (CostBest == Cost && Cost2 > Cost2Best) ) - { - CostBest = Cost; - Cost2Best = Cost2; - iGrpBest = iGrp; - } - } - return iGrpBest; -} - -/**Function************************************************************* - - Synopsis [Returns the number of variables that will be saved.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrUseSelectedColumn( Llb_Mtr_t * p, int iCol ) -{ - int iVar; - assert( iCol >= 1 && iCol < p->nCols - 1 ); - for ( iVar = 0; iVar < p->nRows; iVar++ ) - { - if ( p->pMatrix[iCol][iVar] == 0 ) - continue; - if ( p->pProdVars[iVar] == 1 && p->pProdNums[iVar] == 1 ) - { - p->pProdVars[iVar] = 0; - p->pProdNums[iVar] = 0; - continue; - } - if ( p->pProdVars[iVar] == 0 ) - { - p->pProdVars[iVar] = 1; - p->pProdNums[iVar] = p->pRowSums[iVar]; - } - p->pProdNums[iVar]--; - assert( p->pProdNums[iVar] >= 0 ); - if ( p->pProdNums[iVar] < 0 ) - Abc_Print( -1, "Llb_MtrUseSelectedColumn() Internal error!\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Verify columns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrVerifyColumns( Llb_Mtr_t * p, int iGrpStart ) -{ - int iVar, iGrp, Counter; - for ( iVar = 0; iVar < p->nRows; iVar++ ) - { - if ( p->pProdVars[iVar] == 0 ) - continue; - Counter = 0; - for ( iGrp = iGrpStart; iGrp < p->nCols; iGrp++ ) - if ( p->pMatrix[iGrp][iVar] == 1 ) - Counter++; - assert( Counter == p->pProdNums[iVar] ); - if ( Counter != p->pProdNums[iVar] ) - Abc_Print( -1, "Llb_MtrVerifyColumns(): Internal error.\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Matrix reduce.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MtrSchedule( Llb_Mtr_t * p ) -{ - int iGrp, iGrpBest, i; - // start partial product - for ( i = 0; i < p->nRows; i++ ) - { - if ( i >= p->nPis && i < p->nPis + p->nFfs ) - { - p->pProdVars[i] = 1; - p->pProdNums[i] = p->pRowSums[i] - 1; - } - else - { - p->pProdVars[i] = 0; - p->pProdNums[i] = p->pRowSums[i]; - } - } - // order the partitions - Llb_MtrVerifyMatrix( p ); - for ( iGrp = 1; iGrp < p->nCols-1; iGrp++ ) - { - Llb_MtrVerifyColumns( p, iGrp ); - iGrpBest = Llb_MtrFindBestColumn( p, iGrp ); - Llb_MtrUseSelectedColumn( p, iGrpBest ); - Llb_MtrSwapColumns( p, iGrp, iGrpBest ); - } - Llb_MtrVerifyMatrix( p ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/llb/llb2Bad.c b/src/proof/llb/llb2Bad.c deleted file mode 100644 index ac04b563..00000000 --- a/src/proof/llb/llb2Bad.c +++ /dev/null @@ -1,138 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb2Bad.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Computing bad states.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb2Bad.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes bad in working manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_BddComputeBad( Aig_Man_t * pInit, DdManager * dd, abctime TimeOut ) -{ - Vec_Ptr_t * vNodes; - DdNode * bBdd0, * bBdd1, * bTemp, * bResult; - Aig_Obj_t * pObj; - int i, k; - assert( Cudd_ReadSize(dd) == Aig_ManCiNum(pInit) ); - // initialize elementary variables - Aig_ManConst1(pInit)->pData = Cudd_ReadOne( dd ); - Saig_ManForEachLo( pInit, pObj, i ) - pObj->pData = Cudd_bddIthVar( dd, i ); - Saig_ManForEachPi( pInit, pObj, i ) - pObj->pData = Cudd_bddIthVar( dd, Aig_ManRegNum(pInit) + i ); - // compute internal nodes - vNodes = Aig_ManDfsNodes( pInit, (Aig_Obj_t **)Vec_PtrArray(pInit->vCos), Saig_ManPoNum(pInit) ); - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - { - if ( !Aig_ObjIsNode(pObj) ) - continue; - bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); -// pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeOut ); - pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); - if ( pObj->pData == NULL ) - { - Vec_PtrForEachEntryStop( Aig_Obj_t *, vNodes, pObj, k, i ) - if ( pObj->pData ) - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - Vec_PtrFree( vNodes ); - return NULL; - } - Cudd_Ref( (DdNode *)pObj->pData ); - } - // quantify PIs of each PO - bResult = Cudd_ReadLogicZero( dd ); Cudd_Ref( bResult ); - Saig_ManForEachPo( pInit, pObj, i ) - { - bBdd0 = Cudd_NotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bResult = Cudd_bddOr( dd, bTemp = bResult, bBdd0 ); Cudd_Ref( bResult ); - Cudd_RecursiveDeref( dd, bTemp ); - } - // deref - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - { - if ( !Aig_ObjIsNode(pObj) ) - continue; - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - } - Vec_PtrFree( vNodes ); - Cudd_Deref( bResult ); - return bResult; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_BddQuantifyPis( Aig_Man_t * pInit, DdManager * dd, DdNode * bFunc ) -{ - DdNode * bVar, * bCube, * bTemp; - Aig_Obj_t * pObj; - int i; - abctime TimeStop; - assert( Cudd_ReadSize(dd) == Aig_ManCiNum(pInit) ); - TimeStop = dd->TimeStop; dd->TimeStop = 0; - // create PI cube - bCube = Cudd_ReadOne( dd ); Cudd_Ref( bCube ); - Saig_ManForEachPi( pInit, pObj, i ) { - bVar = Cudd_bddIthVar( dd, Aig_ManRegNum(pInit) + i ); - bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( dd, bTemp ); - } - // quantify PI cube - bFunc = Cudd_bddExistAbstract( dd, bFunc, bCube ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bCube ); - Cudd_Deref( bFunc ); - dd->TimeStop = TimeStop; - return bFunc; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/llb/llb2Core.c b/src/proof/llb/llb2Core.c deleted file mode 100644 index 3d62b322..00000000 --- a/src/proof/llb/llb2Core.c +++ /dev/null @@ -1,777 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb2Core.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Core procedure.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb2Core.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Llb_Img_t_ Llb_Img_t; -struct Llb_Img_t_ -{ - Aig_Man_t * pInit; // AIG manager - Aig_Man_t * pAig; // AIG manager - Gia_ParLlb_t * pPars; // parameters - - DdManager * dd; // BDD manager - DdManager * ddG; // BDD manager - DdManager * ddR; // BDD manager - Vec_Ptr_t * vDdMans; // BDD managers for each partition - Vec_Ptr_t * vRings; // onion rings in ddR - - Vec_Int_t * vDriRefs; // driver references - Vec_Int_t * vVarsCs; // cur state variables - Vec_Int_t * vVarsNs; // next state variables - - Vec_Int_t * vCs2Glo; // cur state variables into global variables - Vec_Int_t * vNs2Glo; // next state variables into global variables - Vec_Int_t * vGlo2Cs; // global variables into cur state variables - Vec_Int_t * vGlo2Ns; // global variables into next state variables -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes cube composed of given variables with given values.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_CoreComputeCube( DdManager * dd, Vec_Int_t * vVars, int fUseVarIndex, char * pValues ) -{ - DdNode * bRes, * bVar, * bTemp; - int i, iVar, Index; - abctime TimeStop; - TimeStop = dd->TimeStop; dd->TimeStop = 0; - bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); - Vec_IntForEachEntry( vVars, Index, i ) - { - iVar = fUseVarIndex ? Index : i; - bVar = Cudd_NotCond( Cudd_bddIthVar(dd, iVar), (int)(pValues == NULL || pValues[i] != 1) ); - bRes = Cudd_bddAnd( dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bRes ); - dd->TimeStop = TimeStop; - return bRes; -} - -/**Function************************************************************* - - Synopsis [Derives counter-example by backward reachability.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Cex_t * Llb_CoreDeriveCex( Llb_Img_t * p ) -{ - Abc_Cex_t * pCex; - Aig_Obj_t * pObj; - Vec_Ptr_t * vSupps, * vQuant0, * vQuant1; - DdNode * bState = NULL, * bImage, * bOneCube, * bTemp, * bRing; - int i, v, RetValue, nPiOffset; - char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) ); - assert( Vec_PtrSize(p->vRings) > 0 ); - - p->dd->TimeStop = 0; - p->ddR->TimeStop = 0; - - // get supports and quantified variables - Vec_PtrReverseOrder( p->vDdMans ); - vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsNs, p->vVarsCs, 1, 0 ); - Llb_ImgSchedule( vSupps, &vQuant0, &vQuant1, 0 ); - Vec_VecFree( (Vec_Vec_t *)vSupps ); - Llb_ImgQuantifyReset( p->vDdMans ); -// Llb_ImgQuantifyFirst( p->pAig, p->vDdMans, vQuant0 ); - - // allocate room for the counter-example - pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) ); - pCex->iFrame = Vec_PtrSize(p->vRings) - 1; - pCex->iPo = -1; - - // get the last cube - bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc ); Cudd_Ref( bOneCube ); - RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); - Cudd_RecursiveDeref( p->ddR, bOneCube ); - assert( RetValue ); - - // write PIs of counter-example - nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1); - Saig_ManForEachPi( p->pAig, pObj, i ) - if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) - Abc_InfoSetBit( pCex->pData, nPiOffset + i ); - - // write state in terms of NS variables - if ( Vec_PtrSize(p->vRings) > 1 ) - { - bState = Llb_CoreComputeCube( p->dd, p->vVarsNs, 1, pValues ); Cudd_Ref( bState ); - } - // perform backward analysis - Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v ) - { - if ( v == Vec_PtrSize(p->vRings) - 1 ) - continue; - // compute the next states - bImage = Llb_ImgComputeImage( p->pAig, p->vDdMans, p->dd, bState, - vQuant0, vQuant1, p->vDriRefs, p->pPars->TimeTarget, 1, 0, 0 ); - assert( bImage != NULL ); - Cudd_Ref( bImage ); - Cudd_RecursiveDeref( p->dd, bState ); -//Extra_bddPrintSupport( p->dd, bImage ); printf( "\n" ); - - // move reached states into ring manager - bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) ); Cudd_Ref( bImage ); - Cudd_RecursiveDeref( p->dd, bTemp ); - - // intersect with the previous set - bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing ); Cudd_Ref( bOneCube ); - Cudd_RecursiveDeref( p->ddR, bImage ); - - // find any assignment of the BDD - RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); - Cudd_RecursiveDeref( p->ddR, bOneCube ); - assert( RetValue ); - - // write PIs of counter-example - nPiOffset -= Saig_ManPiNum(p->pAig); - Saig_ManForEachPi( p->pAig, pObj, i ) - if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) - Abc_InfoSetBit( pCex->pData, nPiOffset + i ); - - // check that we get the init state - if ( v == 0 ) - { - Saig_ManForEachLo( p->pAig, pObj, i ) - assert( pValues[i] == 0 ); - break; - } - - // write state in terms of NS variables - bState = Llb_CoreComputeCube( p->dd, p->vVarsNs, 1, pValues ); Cudd_Ref( bState ); - } - assert( nPiOffset == Saig_ManRegNum(p->pAig) ); - // update the output number - RetValue = Saig_ManFindFailedPoCex( p->pInit, pCex ); - assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pInit) ); // invalid CEX!!! - pCex->iPo = RetValue; - // cleanup - ABC_FREE( pValues ); - Vec_VecFree( (Vec_Vec_t *)vQuant0 ); - Vec_VecFree( (Vec_Vec_t *)vQuant1 ); - return pCex; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_CoreReachability_int( Llb_Img_t * p, Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1 ) -{ - int * pLoc2Glo = p->pPars->fBackward? Vec_IntArray( p->vCs2Glo ) : Vec_IntArray( p->vNs2Glo ); - int * pLoc2GloR = p->pPars->fBackward? Vec_IntArray( p->vNs2Glo ) : Vec_IntArray( p->vCs2Glo ); - int * pGlo2Loc = p->pPars->fBackward? Vec_IntArray( p->vGlo2Ns ) : Vec_IntArray( p->vGlo2Cs ); - DdNode * bCurrent, * bReached, * bNext, * bTemp; - abctime clk2, clk = Abc_Clock(); - int nIters, nBddSize;//, iOutFail = -1; -/* - // compute time to stop - if ( p->pPars->TimeLimit ) - p->pPars->TimeTarget = Abc_Clock() + p->pPars->TimeLimit * CLOCKS_PER_SEC; - else - p->pPars->TimeTarget = 0; -*/ - - if ( Abc_Clock() > p->pPars->TimeTarget ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) before image computation.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = -1; - return -1; - } - - // set the stop time parameter - p->dd->TimeStop = p->pPars->TimeTarget; - p->ddG->TimeStop = p->pPars->TimeTarget; - p->ddR->TimeStop = p->pPars->TimeTarget; - - // compute initial states - if ( p->pPars->fBackward ) - { - // create init state in the global manager - bTemp = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget ); - if ( bTemp == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) while computing bad states.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = -1; - return -1; - } - Cudd_Ref( bTemp ); - // create bad state in the ring manager - p->ddR->bFunc = Llb_CoreComputeCube( p->ddR, p->vVarsCs, 0, NULL ); Cudd_Ref( p->ddR->bFunc ); - bCurrent = Llb_BddQuantifyPis( p->pInit, p->ddR, bTemp ); Cudd_Ref( bCurrent ); - Cudd_RecursiveDeref( p->ddR, bTemp ); - bReached = Cudd_bddTransfer( p->ddR, p->ddG, bCurrent ); Cudd_Ref( bReached ); - Cudd_RecursiveDeref( p->ddR, bCurrent ); - // move init state to the working manager - bCurrent = Extra_TransferPermute( p->ddG, p->dd, bReached, pGlo2Loc ); - if ( bCurrent == NULL ) - { - Cudd_RecursiveDeref( p->ddG, bReached ); - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during transfer 0.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = -1; - return -1; - } - Cudd_Ref( bCurrent ); - } - else - { - // create bad state in the ring manager - p->ddR->bFunc = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget ); - if ( p->ddR->bFunc == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) while computing bad states.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = -1; - return -1; - } - Cudd_Ref( p->ddR->bFunc ); - // create init state in the working and global manager - bCurrent = Llb_CoreComputeCube( p->dd, p->vVarsCs, 1, NULL ); Cudd_Ref( bCurrent ); - bReached = Llb_CoreComputeCube( p->ddG, p->vVarsCs, 0, NULL ); Cudd_Ref( bReached ); -//Extra_bddPrint( p->dd, bCurrent ); printf( "\n" ); -//Extra_bddPrint( p->ddG, bReached ); printf( "\n" ); - } - - // compute onion rings - for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ ) - { - clk2 = Abc_Clock(); - // check the runtime limit - if ( p->pPars->TimeLimit && Abc_Clock() > p->pPars->TimeTarget ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return -1; - } - - // save the onion ring - bTemp = Extra_TransferPermute( p->dd, p->ddR, bCurrent, pLoc2GloR ); - if ( bTemp == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return -1; - } - Cudd_Ref( bTemp ); - Vec_PtrPush( p->vRings, bTemp ); - - // check it for bad states - if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) ) - { - assert( p->pInit->pSeqModel == NULL ); - if ( !p->pPars->fBackward ) - p->pInit->pSeqModel = Llb_CoreDeriveCex( p ); - Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - if ( !p->pPars->fSilent ) - { - if ( !p->pPars->fBackward ) - Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", p->pInit->pSeqModel->iPo, p->pInit->pName, nIters ); - else - Abc_Print( 1, "Output ??? was asserted in frame %d (counter-example is not produced). ", nIters ); - Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); - } - p->pPars->iFrame = nIters - 1; - return 0; - } - - // compute the next states - bNext = Llb_ImgComputeImage( p->pAig, p->vDdMans, p->dd, bCurrent, - vQuant0, vQuant1, p->vDriRefs, p->pPars->TimeTarget, - p->pPars->fBackward, p->pPars->fReorder, p->pPars->fVeryVerbose ); - if ( bNext == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return -1; - } - Cudd_Ref( bNext ); - Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; -//Extra_bddPrintSupport( p->dd, bNext ); printf( "\n" ); - - // remap these states into the global manager -// bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pLoc2Glo ); Cudd_Ref( bNext ); -// Cudd_RecursiveDeref( p->dd, bTemp ); - -// bNext = Extra_TransferPermuteTime( p->dd, p->ddG, bTemp = bNext, pLoc2Glo, p->pPars->TimeTarget ); - bNext = Extra_TransferPermute( p->dd, p->ddG, bTemp = bNext, pLoc2Glo ); - if ( bNext == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return -1; - } - Cudd_Ref( bNext ); - Cudd_RecursiveDeref( p->dd, bTemp ); - - nBddSize = Cudd_DagSize(bNext); - // check if there are any new states - if ( Cudd_bddLeq( p->ddG, bNext, bReached ) ) // implication = no new states - { - Cudd_RecursiveDeref( p->ddG, bNext ); bNext = NULL; - break; - } - - // get the new states - bCurrent = Cudd_bddAnd( p->ddG, bNext, Cudd_Not(bReached) ); - if ( bCurrent == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->ddG, bNext ); - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return -1; - } - Cudd_Ref( bCurrent ); - - // remap these states into the current state vars -// bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc ); Cudd_Ref( bCurrent ); -// Cudd_RecursiveDeref( p->ddG, bTemp ); - -// bCurrent = Extra_TransferPermuteTime( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc, p->pPars->TimeTarget ); - bCurrent = Extra_TransferPermute( p->ddG, p->dd, bTemp = bCurrent, pGlo2Loc ); - if ( bCurrent == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->ddG, bTemp ); - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return -1; - } - Cudd_Ref( bCurrent ); - Cudd_RecursiveDeref( p->ddG, bTemp ); - - // add to the reached states - bReached = Cudd_bddOr( p->ddG, bTemp = bReached, bNext ); Cudd_Ref( bReached ); - Cudd_RecursiveDeref( p->ddG, bTemp ); - Cudd_RecursiveDeref( p->ddG, bNext ); - bNext = NULL; - - if ( p->pPars->fVeryVerbose ) - { - double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); -// Extra_bddPrint( p->ddG, bReached );printf( "\n" ); - fprintf( stdout, " Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); - fflush( stdout ); - } - if ( p->pPars->fVerbose ) - { - fprintf( stdout, "F =%3d : ", nIters ); - fprintf( stdout, "Image =%6d ", nBddSize ); - fprintf( stdout, "(%4d%4d) ", - Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) ); - fprintf( stdout, "Reach =%6d ", Cudd_DagSize(bReached) ); - fprintf( stdout, "(%4d%4d) ", - Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) ); - Abc_PrintTime( 1, "Time", Abc_Clock() - clk2 ); - } - - // check timeframe limit - if ( nIters == p->pPars->nIterMax - 1 ) - { - if ( !p->pPars->fSilent ) - printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nIterMax ); - p->pPars->iFrame = nIters; - Cudd_RecursiveDeref( p->dd, bCurrent ); bCurrent = NULL; - Cudd_RecursiveDeref( p->ddG, bReached ); bReached = NULL; - return -1; - } - } - if ( bReached == NULL ) - { - p->pPars->iFrame = nIters - 1; - return 0; // reachable - } - if ( bCurrent ) - Cudd_RecursiveDeref( p->dd, bCurrent ); - // report the stats - if ( p->pPars->fVerbose ) - { - double nMints = Cudd_CountMinterm(p->ddG, bReached, Saig_ManRegNum(p->pAig) ); - if ( nIters >= p->pPars->nIterMax ) - fprintf( stdout, "Reachability analysis is stopped after %d frames.\n", nIters ); - else - fprintf( stdout, "Reachability analysis completed after %d frames.\n", nIters ); - fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); - fflush( stdout ); - } - if ( p->pPars->fDumpReached ) - { - Llb_ManDumpReached( p->ddG, bReached, p->pAig->pName, "reached.blif" ); - printf( "Reached states with %d BDD nodes are dumpted into file \"reached.blif\".\n", Cudd_DagSize(bReached) ); - } - Cudd_RecursiveDeref( p->ddG, bReached ); - if ( nIters >= p->pPars->nIterMax ) - { - if ( !p->pPars->fSilent ) - { - printf( "Verified only for states reachable in %d frames. ", nIters ); - Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); - } - p->pPars->iFrame = p->pPars->nIterMax; - return -1; // undecided - } - if ( !p->pPars->fSilent ) - { - printf( "The miter is proved unreachable after %d iterations. ", nIters ); - Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); - } - p->pPars->iFrame = nIters - 1; - return 1; // unreachable -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_CoreReachability( Llb_Img_t * p ) -{ - Vec_Ptr_t * vSupps, * vQuant0, * vQuant1; - int RetValue; - // get supports and quantified variables - if ( p->pPars->fBackward ) - { - Vec_PtrReverseOrder( p->vDdMans ); - vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsNs, p->vVarsCs, 0, p->pPars->fVeryVerbose ); - } - else - vSupps = Llb_ImgSupports( p->pAig, p->vDdMans, p->vVarsCs, p->vVarsNs, 0, p->pPars->fVeryVerbose ); - Llb_ImgSchedule( vSupps, &vQuant0, &vQuant1, p->pPars->fVeryVerbose ); - Vec_VecFree( (Vec_Vec_t *)vSupps ); - // remove variables - Llb_ImgQuantifyFirst( p->pAig, p->vDdMans, vQuant0, p->pPars->fVeryVerbose ); - // perform reachability - RetValue = Llb_CoreReachability_int( p, vQuant0, vQuant1 ); - Vec_VecFree( (Vec_Vec_t *)vQuant0 ); - Vec_VecFree( (Vec_Vec_t *)vQuant1 ); - return RetValue; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_CoreConstructAll( Aig_Man_t * p, Vec_Ptr_t * vResult, Vec_Int_t * vVarsNs, abctime TimeTarget ) -{ - DdManager * dd; - Vec_Ptr_t * vDdMans; - Vec_Ptr_t * vLower, * vUpper = NULL; - int i; - vDdMans = Vec_PtrStart( Vec_PtrSize(vResult) ); - Vec_PtrForEachEntryReverse( Vec_Ptr_t *, vResult, vLower, i ) - { - if ( i < Vec_PtrSize(vResult) - 1 ) - dd = Llb_ImgPartition( p, vLower, vUpper, TimeTarget ); - else - dd = Llb_DriverLastPartition( p, vVarsNs, TimeTarget ); - if ( dd == NULL ) - { - Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i ) - { - if ( dd == NULL ) - continue; - if ( dd->bFunc ) - Cudd_RecursiveDeref( dd, dd->bFunc ); - Extra_StopManager( dd ); - } - Vec_PtrFree( vDdMans ); - return NULL; - } - Vec_PtrWriteEntry( vDdMans, i, dd ); - vUpper = vLower; - } - return vDdMans; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_CoreSetVarMaps( Llb_Img_t * p ) -{ - Aig_Obj_t * pObj; - int i, iVarCs, iVarNs; - assert( p->vVarsCs != NULL ); - assert( p->vVarsNs != NULL ); - assert( p->vCs2Glo == NULL ); - assert( p->vNs2Glo == NULL ); - assert( p->vGlo2Cs == NULL ); - assert( p->vGlo2Ns == NULL ); - p->vCs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) ); - p->vNs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) ); - p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); - p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); - for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ ) - { - iVarCs = Vec_IntEntry( p->vVarsCs, i ); - iVarNs = Vec_IntEntry( p->vVarsNs, i ); - assert( iVarCs >= 0 && iVarCs < Aig_ManObjNumMax(p->pAig) ); - assert( iVarNs >= 0 && iVarNs < Aig_ManObjNumMax(p->pAig) ); - Vec_IntWriteEntry( p->vCs2Glo, iVarCs, i ); - Vec_IntWriteEntry( p->vNs2Glo, iVarNs, i ); - Vec_IntWriteEntry( p->vGlo2Cs, i, iVarCs ); - Vec_IntWriteEntry( p->vGlo2Ns, i, iVarNs ); - } - // add mapping of the PIs - Saig_ManForEachPi( p->pAig, pObj, i ) - Vec_IntWriteEntry( p->vCs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Img_t * Llb_CoreStart( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) -{ - Llb_Img_t * p; - p = ABC_CALLOC( Llb_Img_t, 1 ); - p->pInit = pInit; - p->pAig = pAig; - p->pPars = pPars; - p->dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - p->ddG = Cudd_Init( Aig_ManRegNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - p->ddR = Cudd_Init( Aig_ManCiNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); - Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT ); - Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT ); - p->vRings = Vec_PtrAlloc( 100 ); - p->vDriRefs = Llb_DriverCountRefs( pAig ); - p->vVarsCs = Llb_DriverCollectCs( pAig ); - p->vVarsNs = Llb_DriverCollectNs( pAig, p->vDriRefs ); - Llb_CoreSetVarMaps( p ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_CoreStop( Llb_Img_t * p ) -{ - DdManager * dd; - DdNode * bTemp; - int i; - if ( p->vDdMans ) - Vec_PtrForEachEntry( DdManager *, p->vDdMans, dd, i ) - { - if ( dd->bFunc ) - Cudd_RecursiveDeref( dd, dd->bFunc ); - if ( dd->bFunc2 ) - Cudd_RecursiveDeref( dd, dd->bFunc2 ); - Extra_StopManager( dd ); - } - Vec_PtrFreeP( &p->vDdMans ); - if ( p->ddR->bFunc ) - Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc ); - Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i ) - Cudd_RecursiveDeref( p->ddR, bTemp ); - Vec_PtrFree( p->vRings ); - Extra_StopManager( p->dd ); - Extra_StopManager( p->ddG ); - Extra_StopManager( p->ddR ); - Vec_IntFreeP( &p->vDriRefs ); - Vec_IntFreeP( &p->vVarsCs ); - Vec_IntFreeP( &p->vVarsNs ); - Vec_IntFreeP( &p->vCs2Glo ); - Vec_IntFreeP( &p->vNs2Glo ); - Vec_IntFreeP( &p->vGlo2Cs ); - Vec_IntFreeP( &p->vGlo2Ns ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_CoreExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, abctime TimeTarget ) -{ - int RetValue; - Llb_Img_t * p; -// printf( "\n" ); -// pPars->fVerbose = 1; - p = Llb_CoreStart( pInit, pAig, pPars ); - p->vDdMans = Llb_CoreConstructAll( pAig, vResult, p->vVarsNs, TimeTarget ); - if ( p->vDdMans == NULL ) - { - if ( !pPars->fSilent ) - printf( "Reached timeout (%d seconds) while deriving the partitions.\n", pPars->TimeLimit ); - Llb_CoreStop( p ); - return -1; - } - RetValue = Llb_CoreReachability( p ); - Llb_CoreStop( p ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Finds balanced cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManReachMinCut( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) -{ - extern Vec_Ptr_t * Llb_ManComputeCuts( Aig_Man_t * p, int Num, int fVerbose, int fVeryVerbose ); - Vec_Ptr_t * vResult; - Aig_Man_t * p; - int RetValue = -1; - abctime clk = Abc_Clock(); - - // compute time to stop - pPars->TimeTarget = pPars->TimeLimit ? pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0; - - p = Aig_ManDupFlopsOnly( pAig ); -//Aig_ManShow( p, 0, NULL ); - if ( pPars->fVerbose ) - Aig_ManPrintStats( pAig ); - if ( pPars->fVerbose ) - Aig_ManPrintStats( p ); - Aig_ManFanoutStart( p ); - - vResult = Llb_ManComputeCuts( p, pPars->nPartValue, pPars->fVerbose, pPars->fVeryVerbose ); - - if ( pPars->TimeLimit && Abc_Clock() > pPars->TimeTarget ) - { - if ( !pPars->fSilent ) - printf( "Reached timeout (%d seconds) after partitioning.\n", pPars->TimeLimit ); - - Vec_VecFree( (Vec_Vec_t *)vResult ); - Aig_ManFanoutStop( p ); - Aig_ManCleanMarkAB( p ); - Aig_ManStop( p ); - return RetValue; - } - - if ( !pPars->fSkipReach ) - RetValue = Llb_CoreExperiment( pAig, p, pPars, vResult, pPars->TimeTarget ); - - Vec_VecFree( (Vec_Vec_t *)vResult ); - Aig_ManFanoutStop( p ); - Aig_ManCleanMarkAB( p ); - Aig_ManStop( p ); - - if ( RetValue == -1 ) - Abc_PrintTime( 1, "Total runtime of the min-cut-based reachability engine", Abc_Clock() - clk ); - return RetValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/llb/llb2Driver.c b/src/proof/llb/llb2Driver.c deleted file mode 100644 index 1471f377..00000000 --- a/src/proof/llb/llb2Driver.c +++ /dev/null @@ -1,222 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb2Driver.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Procedures working with flop drivers.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb2Driver.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// driver issue:arises when creating -// - driver ref-counter array -// - Ns2Glo maps -// - final partition -// - change-phase cube - -// LI variable is used when -// - driver drives more than one LI -// - driver is a PI -// - driver is a constant - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns the array of times each flop driver is referenced.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_DriverCountRefs( Aig_Man_t * p ) -{ - Vec_Int_t * vCounts; - Aig_Obj_t * pObj; - int i; - vCounts = Vec_IntStart( Aig_ManObjNumMax(p) ); - Saig_ManForEachLi( p, pObj, i ) - Vec_IntAddToEntry( vCounts, Aig_ObjFaninId0(pObj), 1 ); - return vCounts; -} - -/**Function************************************************************* - - Synopsis [Returns array of NS variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_DriverCollectNs( Aig_Man_t * pAig, Vec_Int_t * vDriRefs ) -{ - Vec_Int_t * vVars; - Aig_Obj_t * pObj, * pDri; - int i; - vVars = Vec_IntAlloc( Aig_ManRegNum(pAig) ); - Saig_ManForEachLi( pAig, pObj, i ) - { - pDri = Aig_ObjFanin0(pObj); - if ( Vec_IntEntry( vDriRefs, Aig_ObjId(pDri) ) != 1 || Saig_ObjIsPi(pAig, pDri) || Aig_ObjIsConst1(pDri) ) - Vec_IntPush( vVars, Aig_ObjId(pObj) ); - else - Vec_IntPush( vVars, Aig_ObjId(pDri) ); - } - return vVars; -} - -/**Function************************************************************* - - Synopsis [Returns array of CS variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_DriverCollectCs( Aig_Man_t * pAig ) -{ - Vec_Int_t * vVars; - Aig_Obj_t * pObj; - int i; - vVars = Vec_IntAlloc( Aig_ManRegNum(pAig) ); - Saig_ManForEachLo( pAig, pObj, i ) - Vec_IntPush( vVars, Aig_ObjId(pObj) ); - return vVars; -} - -/**Function************************************************************* - - Synopsis [Create cube for phase swapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_DriverPhaseCube( Aig_Man_t * pAig, Vec_Int_t * vDriRefs, DdManager * dd ) -{ - DdNode * bCube, * bVar, * bTemp; - Aig_Obj_t * pObj; - int i; - abctime TimeStop; - TimeStop = dd->TimeStop; dd->TimeStop = 0; - bCube = Cudd_ReadOne( dd ); Cudd_Ref( bCube ); - Saig_ManForEachLi( pAig, pObj, i ) - { - assert( Vec_IntEntry( vDriRefs, Aig_ObjFaninId0(pObj) ) >= 1 ); - if ( Vec_IntEntry( vDriRefs, Aig_ObjFaninId0(pObj) ) != 1 ) - continue; - if ( !Aig_ObjFaninC0(pObj) ) - continue; - bVar = Cudd_bddIthVar( dd, Aig_ObjFaninId0(pObj) ); - bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bCube ); - dd->TimeStop = TimeStop; - return bCube; -} - -/**Function************************************************************* - - Synopsis [Compute the last partition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdManager * Llb_DriverLastPartition( Aig_Man_t * p, Vec_Int_t * vVarsNs, abctime TimeTarget ) -{ -// int fVerbose = 1; - DdManager * dd; - DdNode * bVar1, * bVar2, * bProd, * bRes, * bTemp; - Aig_Obj_t * pObj; - int i; - dd = Cudd_Init( Aig_ManObjNumMax(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - dd->TimeStop = TimeTarget; - bRes = Cudd_ReadOne(dd); Cudd_Ref( bRes ); - - // mark the duplicated flop inputs - Aig_ManForEachObjVec( vVarsNs, p, pObj, i ) - { - if ( !Saig_ObjIsLi(p, pObj) ) - continue; - bVar1 = Cudd_bddIthVar( dd, Aig_ObjId(pObj) ); - bVar2 = Cudd_bddIthVar( dd, Aig_ObjFaninId0(pObj) ); - if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) - bVar2 = Cudd_ReadOne(dd); - bVar2 = Cudd_NotCond( bVar2, Aig_ObjFaninC0(pObj) ); - bProd = Cudd_bddXnor( dd, bVar1, bVar2 ); Cudd_Ref( bProd ); -// bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); Cudd_Ref( bRes ); -// bRes = Extra_bddAndTime( dd, bTemp = bRes, bProd, TimeTarget ); - bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bProd ); - return NULL; - } - Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bProd ); - } - -/* - Saig_ManForEachLi( p, pObj, i ) - printf( "%d ", Aig_ObjId(pObj) ); - printf( "\n" ); - Saig_ManForEachLi( p, pObj, i ) - printf( "%c%d ", Aig_ObjFaninC0(pObj)? '-':'+', Aig_ObjFaninId0(pObj) ); - printf( "\n" ); -*/ - Cudd_AutodynDisable( dd ); -// Cudd_RecursiveDeref( dd, bRes ); -// Extra_StopManager( dd ); - dd->bFunc = bRes; - dd->TimeStop = 0; - return dd; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/llb/llb2Dump.c b/src/proof/llb/llb2Dump.c deleted file mode 100644 index 74f07922..00000000 --- a/src/proof/llb/llb2Dump.c +++ /dev/null @@ -1,104 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb2Dump.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Dumps the BDD of reached states into a file.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb2Dump.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns a dummy name.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Llb_ManGetDummyName( char * pPrefix, int Num, int nDigits ) -{ - static char Buffer[2000]; - sprintf( Buffer, "%s%0*d", pPrefix, nDigits, Num ); - return Buffer; -} - -/**Function************************************************************* - - Synopsis [Writes reached state BDD into a BLIF file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManDumpReached( DdManager * ddG, DdNode * bReached, char * pModel, char * pFileName ) -{ - FILE * pFile; - Vec_Ptr_t * vNamesIn, * vNamesOut; - char * pName; - int i, nDigits; - // reorder the BDD - Cudd_ReduceHeap( ddG, CUDD_REORDER_SYMM_SIFT, 1 ); - - // create input names - nDigits = Abc_Base10Log( Cudd_ReadSize(ddG) ); - vNamesIn = Vec_PtrAlloc( Cudd_ReadSize(ddG) ); - for ( i = 0; i < Cudd_ReadSize(ddG); i++ ) - { - pName = Llb_ManGetDummyName( "ff", i, nDigits ); - Vec_PtrPush( vNamesIn, Extra_UtilStrsav(pName) ); - } - // create output names - vNamesOut = Vec_PtrAlloc( 1 ); - Vec_PtrPush( vNamesOut, Extra_UtilStrsav("Reached") ); - - // write the file - pFile = fopen( pFileName, "wb" ); - Cudd_DumpBlif( ddG, 1, &bReached, (char **)Vec_PtrArray(vNamesIn), (char **)Vec_PtrArray(vNamesOut), pModel, pFile, 0 ); - fclose( pFile ); - - // cleanup - Vec_PtrForEachEntry( char *, vNamesIn, pName, i ) - ABC_FREE( pName ); - Vec_PtrForEachEntry( char *, vNamesOut, pName, i ) - ABC_FREE( pName ); - Vec_PtrFree( vNamesIn ); - Vec_PtrFree( vNamesOut ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/llb/llb2Flow.c b/src/proof/llb/llb2Flow.c deleted file mode 100644 index 64db32b3..00000000 --- a/src/proof/llb/llb2Flow.c +++ /dev/null @@ -1,1376 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb2Flow.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Flow computation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb2Flow.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline int Llb_ObjSetPath( Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { pObj->pData = (void *)pNext; return 1; } -static inline Aig_Obj_t * Llb_ObjGetPath( Aig_Obj_t * pObj ) { return (Aig_Obj_t *)pObj->pData; } -static inline Aig_Obj_t * Llb_ObjGetFanoutPath( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - Aig_Obj_t * pFanout; - int i, iFanout = -1; - assert( Llb_ObjGetPath(pObj) ); - Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) - if ( Llb_ObjGetPath(pFanout) == pObj ) - return pFanout; - return NULL; -} - -extern Vec_Ptr_t * Llb_ManCutSupp( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - - -/**Function************************************************************* - - Synopsis [For each cut, returns PIs that can be quantified.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManCutSupps( Aig_Man_t * p, Vec_Ptr_t * vResult ) -{ - Vec_Ptr_t * vSupps, * vOne, * vLower, * vUpper; - int i; - vSupps = Vec_PtrAlloc( 100 ); - Vec_PtrPush( vSupps, Vec_PtrAlloc(0) ); - vLower = (Vec_Ptr_t *)Vec_PtrEntry( vResult, 0 ); - Vec_PtrForEachEntryStart( Vec_Ptr_t *, vResult, vUpper, i, 1 ) - { - vOne = Llb_ManCutSupp( p, vLower, vUpper ); - Vec_PtrPush( vSupps, vOne ); - vLower = vUpper; - } - assert( Vec_PtrSize(vSupps) == Vec_PtrSize(vResult) ); - return vSupps; -} - -/**Function************************************************************* - - Synopsis [For each cut, returns PIs that can be quantified.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManCutMap( Aig_Man_t * p, Vec_Ptr_t * vResult, Vec_Ptr_t * vSupps ) -{ - int fShowMatrix = 1; - Vec_Ptr_t * vMaps, * vOne; - Vec_Int_t * vMap, * vPrev, * vNext; - Aig_Obj_t * pObj; - int * piFirst, * piLast; - int i, k, CounterPlus, CounterMinus, Counter; - - vMaps = Vec_PtrAlloc( 100 ); - Vec_PtrForEachEntry( Vec_Ptr_t *, vResult, vOne, i ) - { - vMap = Vec_IntStart( Aig_ManObjNumMax(p) ); - Vec_PtrForEachEntry( Aig_Obj_t *, vOne, pObj, k ) - { - if ( !Saig_ObjIsPi(p, pObj) ) - Vec_IntWriteEntry( vMap, pObj->Id, 1 ); -// else -//printf( "*" ); -//printf( "%d ", pObj->Id ); - } - Vec_PtrPush( vMaps, vMap ); -//printf( "\n" ); - } - Vec_PtrPush( vMaps, Vec_IntStart( Aig_ManObjNumMax(p) ) ); - assert( Vec_PtrSize(vMaps) == Vec_PtrSize(vResult)+1 ); - - // collect the first and last PIs - piFirst = ABC_ALLOC( int, Saig_ManPiNum(p) ); - piLast = ABC_ALLOC( int, Saig_ManPiNum(p) ); - Saig_ManForEachPi( p, pObj, i ) - piFirst[i] = piLast[i] = -1; - Vec_PtrForEachEntry( Vec_Ptr_t *, vSupps, vOne, i ) - { - Vec_PtrForEachEntry( Aig_Obj_t *, vOne, pObj, k ) - { - if ( !Saig_ObjIsPi(p, pObj) ) - continue; - if ( piFirst[Aig_ObjCioId(pObj)] == -1 ) - piFirst[Aig_ObjCioId(pObj)] = i; - piLast[Aig_ObjCioId(pObj)] = i; - } - } - // PIs feeding into the flops should be extended to the last frame - Saig_ManForEachLi( p, pObj, i ) - { - if ( !Saig_ObjIsPi(p, Aig_ObjFanin0(pObj)) ) - continue; - piLast[Aig_ObjCioId(Aig_ObjFanin0(pObj))] = Vec_PtrSize(vMaps)-1; - } - - // set the PI map - Saig_ManForEachPi( p, pObj, i ) - { - if ( piFirst[i] == -1 ) - continue; - if ( piFirst[i] == piLast[i] ) - { - vMap = (Vec_Int_t *)Vec_PtrEntry( vMaps, piFirst[i] ); - Vec_IntWriteEntry( vMap, pObj->Id, 2 ); - continue; - } - - // set support for all in between - for ( k = piFirst[i]; k <= piLast[i]; k++ ) - { - vMap = (Vec_Int_t *)Vec_PtrEntry( vMaps, k ); - Vec_IntWriteEntry( vMap, pObj->Id, 1 ); - } - } - ABC_FREE( piFirst ); - ABC_FREE( piLast ); - - - // find all that will appear here - Counter = Aig_ManRegNum(p); - printf( "%d ", Counter ); - Vec_PtrForEachEntryStart( Vec_Int_t *, vMaps, vMap, i, 1 ) - { - vPrev = (Vec_Int_t *)Vec_PtrEntry( vMaps, i-1 ); - vNext = (i == Vec_PtrSize(vMaps)-1)? NULL: (Vec_Int_t *)Vec_PtrEntry( vMaps, i+1 ); - - CounterPlus = CounterMinus = 0; - Aig_ManForEachObj( p, pObj, k ) - { - if ( Saig_ObjIsPi(p, pObj) ) - { - if ( Vec_IntEntry(vPrev, k) == 0 && Vec_IntEntry(vMap, k) == 1 ) - CounterPlus++; - if ( Vec_IntEntry(vMap, k) == 1 && (vNext == NULL || Vec_IntEntry(vNext, k) == 0) ) - CounterMinus++; - } - else - { - if ( Vec_IntEntry(vPrev, k) == 0 && Vec_IntEntry(vMap, k) == 1 ) - CounterPlus++; - if ( Vec_IntEntry(vPrev, k) == 1 && Vec_IntEntry(vMap, k) == 0 ) - CounterMinus++; - } - } - Counter = Counter + CounterPlus - CounterMinus; - printf( "%d=%d ", i, Counter ); - } - printf( "\n" ); - - if ( !fShowMatrix ) - return vMaps; - Aig_ManForEachObj( p, pObj, i ) - { - if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) ) - continue; - Vec_PtrForEachEntry( Vec_Int_t *, vMaps, vMap, k ) - if ( Vec_IntEntry(vMap, i) ) - break; - if ( k == Vec_PtrSize(vMaps) ) - continue; - printf( "Obj = %4d : ", i ); - if ( Saig_ObjIsPi(p,pObj) ) - printf( "pi " ); - else if ( Saig_ObjIsLo(p,pObj) ) - printf( "lo " ); - else if ( Aig_ObjIsNode(pObj) ) - printf( "and " ); - - Vec_PtrForEachEntry( Vec_Int_t *, vMaps, vMap, k ) - printf( "%d", Vec_IntEntry(vMap, i) ); - printf( "\n" ); - } - return vMaps; -} - -/**Function************************************************************* - - Synopsis [Counts the number of PIs in the cut] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManCutPiNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) -{ - Aig_Obj_t * pObj; - int i, Counter = 0; - Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) - if ( Saig_ObjIsPi(p,pObj) ) - Counter++; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts the number of LOs in the cut] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManCutLoNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) -{ - Aig_Obj_t * pObj; - int i, Counter = 0; - Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) - if ( Saig_ObjIsLo(p,pObj) ) - Counter++; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts the number of LIs in the cut] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManCutLiNum( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) -{ - Aig_Obj_t * pFanout; - Aig_Obj_t * pObj; - int i, k, iFanout = -1, Counter = 0; - Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) - { - if ( Aig_ObjIsCi(pObj) ) - continue; - Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, k ) - { - if ( Saig_ObjIsLi(p, pFanout) ) - { - Counter++; - break; - } - } - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Computes volume of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManCutVolume_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return 0; - Aig_ObjSetTravIdCurrent(p, pObj); - assert( Aig_ObjIsNode(pObj) ); - return 1 + Llb_ManCutVolume_rec(p, Aig_ObjFanin0(pObj)) + - Llb_ManCutVolume_rec(p, Aig_ObjFanin1(pObj)); -} - -/**Function************************************************************* - - Synopsis [Computes volume of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManCutVolume( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) -{ - Aig_Obj_t * pObj; - int i, Counter = 0; - // mark the lower cut with the traversal ID - Aig_ManIncrementTravId(p); - Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) - Aig_ObjSetTravIdCurrent( p, pObj ); - // count the upper cut - Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) - Counter += Llb_ManCutVolume_rec( p, pObj ); - return Counter; -} - - -/**Function************************************************************* - - Synopsis [Computes volume of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManCutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) -{ - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return; - Aig_ObjSetTravIdCurrent(p, pObj); - assert( Aig_ObjIsNode(pObj) ); - Llb_ManCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); - Llb_ManCutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes); - Vec_PtrPush( vNodes, pObj ); -} - -/**Function************************************************************* - - Synopsis [Computes volume of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i; - // mark the lower cut with the traversal ID - Aig_ManIncrementTravId(p); - Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) - Aig_ObjSetTravIdCurrent( p, pObj ); - // count the upper cut - vNodes = Vec_PtrAlloc( 100 ); - Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) - Llb_ManCutNodes_rec( p, pObj, vNodes ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Computes volume of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManCutSupp( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) -{ - Vec_Ptr_t * vNodes, * vSupp; - Aig_Obj_t * pObj; - int i; - vNodes = Llb_ManCutNodes( p, vLower, vUpper ); - // mark support of the nodes - Aig_ManIncrementTravId(p); - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - { - assert( Aig_ObjIsNode(pObj) ); - Aig_ObjSetTravIdCurrent( p, Aig_ObjFanin0(pObj) ); - Aig_ObjSetTravIdCurrent( p, Aig_ObjFanin1(pObj) ); - } - Vec_PtrFree( vNodes ); - // collect the support nodes - vSupp = Vec_PtrAlloc( 100 ); - Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - Vec_PtrPush( vSupp, pObj ); - return vSupp; - -} - -/**Function************************************************************* - - Synopsis [Computes volume of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManCutRange( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) -{ - Vec_Ptr_t * vRange; - Aig_Obj_t * pObj; - int i; - // mark the lower cut with the traversal ID - Aig_ManIncrementTravId(p); - Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) - Aig_ObjSetTravIdCurrent( p, pObj ); - // collect the upper ones that are not marked - vRange = Vec_PtrAlloc( 100 ); - Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) - if ( !Aig_ObjIsTravIdCurrent(p, pObj) ) - Vec_PtrPush( vRange, pObj ); - return vRange; -} - - - - -/**Function************************************************************* - - Synopsis [Prints the given cluster.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManCutPrint( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) -{ - Vec_Ptr_t * vSupp, * vRange; - int Pis, Ffs, And; - - Pis = Llb_ManCutPiNum(p, vLower); - Ffs = Llb_ManCutLoNum(p, vLower); - And = Vec_PtrSize(vLower) - Pis - Ffs; - printf( "Leaf: %3d=%3d+%3d+%3d ", Vec_PtrSize(vLower), Pis, Ffs, And ); - - Pis = Llb_ManCutPiNum(p, vUpper); - Ffs = Llb_ManCutLiNum(p, vUpper); - And = Vec_PtrSize(vUpper) - Pis - Ffs; - printf( "Root: %3d=%3d+%3d+%3d ", Vec_PtrSize(vUpper), Pis, Ffs, And ); - - vSupp = Llb_ManCutSupp( p, vLower, vUpper ); - Pis = Llb_ManCutPiNum(p, vSupp); - Ffs = Llb_ManCutLoNum(p, vSupp); - And = Vec_PtrSize(vSupp) - Pis - Ffs; - printf( "Supp: %3d=%3d+%3d+%3d ", Vec_PtrSize(vSupp), Pis, Ffs, And ); - - vRange = Llb_ManCutRange( p, vLower, vUpper ); - Pis = Llb_ManCutPiNum(p, vRange); - Ffs = Llb_ManCutLiNum(p, vRange); - And = Vec_PtrSize(vRange) - Pis - Ffs; - printf( "Range: %3d=%3d+%3d+%3d ", Vec_PtrSize(vRange), Pis, Ffs, And ); - - printf( "S =%3d. V =%3d.\n", - Vec_PtrSize(vSupp)+Vec_PtrSize(vRange), Llb_ManCutVolume(p, vLower, vUpper) ); - Vec_PtrFree( vSupp ); - Vec_PtrFree( vRange ); -/* - { - Aig_Obj_t * pObj; - int i; - printf( "Lower: " ); - Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) - printf( " %d", pObj->Id ); - printf( " " ); - printf( "Upper: " ); - Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) - printf( " %d", pObj->Id ); - printf( "\n" ); - } -*/ -} - -/**Function************************************************************* - - Synopsis [Prints the given cluster.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManResultPrint( Aig_Man_t * p, Vec_Ptr_t * vResult ) -{ - Vec_Ptr_t * vLower, * vUpper = NULL; - int i; - Vec_PtrForEachEntryReverse( Vec_Ptr_t *, vResult, vLower, i ) - { - if ( i < Vec_PtrSize(vResult) - 1 ) - Llb_ManCutPrint( p, vLower, vUpper ); - vUpper = vLower; - } -} - -/**Function************************************************************* - - Synopsis [Tries to find an augmenting path originating in this node.] - - Description [This procedure works for directed graphs only!] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManFlowBwdPath2_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - Aig_Obj_t * pFanout; - assert( Aig_ObjIsNode(pObj) || Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) ); - // skip visited nodes - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return 0; - Aig_ObjSetTravIdCurrent(p, pObj); - // process node without flow - if ( !Llb_ObjGetPath(pObj) ) - { - // start the path if we reached a terminal node - if ( pObj->fMarkA ) - return Llb_ObjSetPath( pObj, (Aig_Obj_t *)1 ); - // explore the fanins -// Abc_ObjForEachFanin( pObj, pFanin, i ) -// if ( Abc_NtkMaxFlowBwdPath2_rec(pFanin) ) -// return Abc_ObjSetPath( pObj, pFanin ); - if ( Aig_ObjIsNode(pObj) ) - { - if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ) ) - return Llb_ObjSetPath( pObj, Aig_ObjFanin0(pObj) ); - if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ) ) - return Llb_ObjSetPath( pObj, Aig_ObjFanin1(pObj) ); - } - return 0; - } - // pObj has flow - find the fanout with flow - pFanout = Llb_ObjGetFanoutPath( p, pObj ); - if ( pFanout == NULL ) - return 0; - // go through the fanins of the fanout with flow -// Abc_ObjForEachFanin( pFanout, pFanin, i ) -// if ( Abc_NtkMaxFlowBwdPath2_rec( pFanin ) ) -// return Abc_ObjSetPath( pFanout, pFanin ); - assert( Aig_ObjIsNode(pFanout) ); - if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pFanout) ) ) - return Llb_ObjSetPath( pFanout, Aig_ObjFanin0(pFanout) ); - if ( Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pFanout) ) ) - return Llb_ObjSetPath( pFanout, Aig_ObjFanin1(pFanout) ); - // try the fanout - if ( Llb_ManFlowBwdPath2_rec( p, pFanout ) ) - return Llb_ObjSetPath( pFanout, NULL ); - return 0; -} - - -/**Function************************************************************* - - Synopsis [Cleans markB.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManFlowLabelTfi_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return; - Aig_ObjSetTravIdCurrent(p, pObj); - if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) ) - return; - assert( Aig_ObjIsNode(pObj) ); - Llb_ManFlowLabelTfi_rec( p, Aig_ObjFanin0(pObj) ); - Llb_ManFlowLabelTfi_rec( p, Aig_ObjFanin1(pObj) ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManFlowUpdateCut( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) -{ - Aig_Obj_t * pObj; - int i; - // label the TFI of the cut nodes - Aig_ManIncrementTravId(p); - Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) - Llb_ManFlowLabelTfi_rec( p, pObj ); - // collect labeled fanins of non-labeled nodes - Vec_PtrClear( vMinCut ); - Aig_ManIncrementTravId(p); - Aig_ManForEachObj( p, pObj, i ) - { - if ( !Aig_ObjIsCo(pObj) && !Aig_ObjIsNode(pObj) ) - continue; - if ( Aig_ObjIsTravIdCurrent(p, pObj) || Aig_ObjIsTravIdPrevious(p, pObj) ) - continue; - if ( Aig_ObjIsTravIdPrevious(p, Aig_ObjFanin0(pObj)) ) - { - Aig_ObjSetTravIdCurrent(p, Aig_ObjFanin0(pObj)); - Vec_PtrPush( vMinCut, Aig_ObjFanin0(pObj) ); - } - if ( Aig_ObjIsNode(pObj) && Aig_ObjIsTravIdPrevious(p, Aig_ObjFanin1(pObj)) ) - { - Aig_ObjSetTravIdCurrent(p, Aig_ObjFanin1(pObj)); - Vec_PtrPush( vMinCut, Aig_ObjFanin1(pObj) ); - } - } -} - -/**Function************************************************************* - - Synopsis [Find minimum-volume minumum cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManFlowMinCut( Aig_Man_t * p ) -{ - Vec_Ptr_t * vMinCut; - Aig_Obj_t * pObj; - int i; - // collect the cut nodes - vMinCut = Vec_PtrAlloc( Aig_ManRegNum(p) ); - Aig_ManForEachObj( p, pObj, i ) - { - // node without flow is not a cut node - if ( !Llb_ObjGetPath(pObj) ) - continue; - // unvisited node is below the cut - if ( !Aig_ObjIsTravIdCurrent(p, pObj) ) - continue; - // add terminal with flow or node whose path is not visited - if ( pObj->fMarkA || !Aig_ObjIsTravIdCurrent( p, Llb_ObjGetPath(pObj) ) ) - Vec_PtrPush( vMinCut, pObj ); - } - return vMinCut; -} - -/**Function************************************************************* - - Synopsis [Verifies the min-cut is indeed a cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManFlowVerifyCut_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - // skip visited nodes - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return 1; - Aig_ObjSetTravIdCurrent(p, pObj); - // visit the node - if ( Aig_ObjIsConst1(pObj) ) - return 1; - if ( Aig_ObjIsCi(pObj) ) - return 0; - // explore the fanins - assert( Aig_ObjIsNode(pObj) ); - if ( !Llb_ManFlowVerifyCut_rec(p, Aig_ObjFanin0(pObj)) ) - return 0; - if ( !Llb_ManFlowVerifyCut_rec(p, Aig_ObjFanin1(pObj)) ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Verifies the min-cut is indeed a cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_ManFlowVerifyCut( Aig_Man_t * p, Vec_Ptr_t * vMinCut ) -{ - Aig_Obj_t * pObj; - int i; - // mark the cut with the current traversal ID - Aig_ManIncrementTravId(p); - Vec_PtrForEachEntry( Aig_Obj_t *, vMinCut, pObj, i ) - Aig_ObjSetTravIdCurrent( p, pObj ); - // search from the latches for a path to the COs/CIs - Saig_ManForEachLi( p, pObj, i ) - { - if ( !Llb_ManFlowVerifyCut_rec( p, Aig_ObjFanin0(pObj) ) ) - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Implementation of max-flow/min-cut computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManFlow( Aig_Man_t * p, Vec_Ptr_t * vSources, int * pnFlow ) -{ - Vec_Ptr_t * vMinCut; - Aig_Obj_t * pObj; - int Flow, FlowCur, RetValue, i; - // find the max-flow - Flow = 0; - Aig_ManCleanData( p ); - Aig_ManIncrementTravId(p); - Vec_PtrForEachEntry( Aig_Obj_t *, vSources, pObj, i ) - { - assert( !pObj->fMarkA && pObj->fMarkB ); - if ( !Aig_ObjFanin0(pObj)->fMarkB ) - { - FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ); - Flow += FlowCur; - if ( FlowCur ) - Aig_ManIncrementTravId(p); - } - if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB ) - { - FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ); - Flow += FlowCur; - if ( FlowCur ) - Aig_ManIncrementTravId(p); - } - } - if ( pnFlow ) - *pnFlow = Flow; - - // mark the nodes reachable from the latches - Aig_ManIncrementTravId(p); - Vec_PtrForEachEntry( Aig_Obj_t *, vSources, pObj, i ) - { - assert( !pObj->fMarkA && pObj->fMarkB ); - if ( !Aig_ObjFanin0(pObj)->fMarkB ) - { - RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ); - assert( RetValue == 0 ); - } - if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB ) - { - RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ); - assert( RetValue == 0 ); - } - } - - // find the min-cut with the smallest volume - vMinCut = Llb_ManFlowMinCut( p ); - assert( Vec_PtrSize(vMinCut) == Flow ); - // verify the cut - if ( !Llb_ManFlowVerifyCut(p, vMinCut) ) - printf( "Llb_ManFlow() error! The computed min-cut is not a cut!\n" ); -// Llb_ManFlowPrintCut( p, vMinCut ); - return vMinCut; -} - -/**Function************************************************************* - - Synopsis [Implementation of max-flow/min-cut computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManFlowCompute( Aig_Man_t * p ) -{ - Vec_Ptr_t * vMinCut; - Aig_Obj_t * pObj; - int Flow, FlowCur, RetValue, i; - // find the max-flow - Flow = 0; - Aig_ManCleanData( p ); - Aig_ManIncrementTravId(p); - Aig_ManForEachObj( p, pObj, i ) - { - if ( !pObj->fMarkB ) - continue; - assert( !pObj->fMarkA ); - if ( !Aig_ObjFanin0(pObj)->fMarkB ) - { -//printf( "%d ", Aig_ObjFanin0(pObj)->Id ); - FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ); - Flow += FlowCur; - if ( FlowCur ) - Aig_ManIncrementTravId(p); - } - if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB ) - { -//printf( "%d ", Aig_ObjFanin1(pObj)->Id ); - FlowCur = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ); - Flow += FlowCur; - if ( FlowCur ) - Aig_ManIncrementTravId(p); - } - } -//printf( "\n" ); - - // mark the nodes reachable from the latches - Aig_ManIncrementTravId(p); - Aig_ManForEachObj( p, pObj, i ) - { - if ( !pObj->fMarkB ) - continue; - assert( !pObj->fMarkA ); - if ( !Aig_ObjFanin0(pObj)->fMarkB ) - { - RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin0(pObj) ); - assert( RetValue == 0 ); - } - if ( Aig_ObjIsNode(pObj) && !Aig_ObjFanin1(pObj)->fMarkB ) - { - RetValue = Llb_ManFlowBwdPath2_rec( p, Aig_ObjFanin1(pObj) ); - assert( RetValue == 0 ); - } - } - // find the min-cut with the smallest volume - vMinCut = Llb_ManFlowMinCut( p ); - assert( Vec_PtrSize(vMinCut) == Flow ); -//printf( "%d ", Vec_PtrSize(vMinCut) ); - Llb_ManFlowUpdateCut( p, vMinCut ); -//printf( "%d ", Vec_PtrSize(vMinCut) ); - // verify the cut - if ( !Llb_ManFlowVerifyCut(p, vMinCut) ) - printf( "Llb_ManFlow() error! The computed min-cut is not a cut!\n" ); -// Llb_ManFlowPrintCut( p, vMinCut ); - return vMinCut; -} - - - - -/**Function************************************************************* - - Synopsis [Cleans markB.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManFlowCleanMarkB_rec( Aig_Obj_t * pObj ) -{ - if ( pObj->fMarkB == 0 ) - return; - pObj->fMarkB = 0; - assert( Aig_ObjIsNode(pObj) ); - Llb_ManFlowCleanMarkB_rec( Aig_ObjFanin0(pObj) ); - Llb_ManFlowCleanMarkB_rec( Aig_ObjFanin1(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Cleans markB.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManFlowSetMarkA_rec( Aig_Obj_t * pObj ) -{ - if ( pObj->fMarkA ) - return; - pObj->fMarkA = 1; - if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) ) - return; - assert( Aig_ObjIsNode(pObj) ); - Llb_ManFlowSetMarkA_rec( Aig_ObjFanin0(pObj) ); - Llb_ManFlowSetMarkA_rec( Aig_ObjFanin1(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Prepares flow computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManFlowPrepareCut( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) -{ - Aig_Obj_t * pObj; - int i; - // reset marks - Aig_ManForEachObj( p, pObj, i ) - { - pObj->fMarkA = 0; - pObj->fMarkB = 1; - } - // clean PIs and const - Aig_ManConst1(p)->fMarkB = 0; - Aig_ManForEachCi( p, pObj, i ) - pObj->fMarkB = 0; - // clean upper cut -//printf( "Upper: "); - Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) - { - Llb_ManFlowCleanMarkB_rec( pObj ); -//printf( "%d ", pObj->Id ); - } -//printf( "\n" ); - // set lower cut -//printf( "Lower: "); - Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) - { -//printf( "%d ", pObj->Id ); - assert( pObj->fMarkB == 0 ); - Llb_ManFlowSetMarkA_rec( pObj ); - } -//printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Prepares flow computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManFlowUnmarkCone( Aig_Man_t * p, Vec_Ptr_t * vCone ) -{ - Aig_Obj_t * pObj; - int i; - Vec_PtrForEachEntry( Aig_Obj_t *, vCone, pObj, i ) - { - assert( Aig_ObjIsNode(pObj) ); - assert( pObj->fMarkB == 1 ); - pObj->fMarkB = 0; - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManFlowCollectAndMarkCone_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vCone ) -{ - Aig_Obj_t * pFanout; - int i, iFanout = -1; - if ( Saig_ObjIsLi(p, pObj) ) - return; - if ( pObj->fMarkB ) - return; - if ( pObj->fMarkA == 0 ) - { - assert( Aig_ObjIsNode(pObj) ); - pObj->fMarkB = 1; - if ( Aig_ObjIsNode(pObj) ) - Vec_PtrPush( vCone, pObj ); - } - Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) - Llb_ManFlowCollectAndMarkCone_rec( p, pFanout, vCone ); -} - -/**Function************************************************************* - - Synopsis [Collects the cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManFlowCollectAndMarkCone( Aig_Man_t * p, Vec_Ptr_t * vStarts, Vec_Ptr_t * vCone ) -{ - Aig_Obj_t * pObj; - int i; - Vec_PtrClear( vCone ); - Vec_PtrForEachEntry( Aig_Obj_t *, vStarts, pObj, i ) - { - assert( pObj->fMarkA && !pObj->fMarkB ); - Llb_ManFlowCollectAndMarkCone_rec( p, pObj, vCone ); - } -} - - - - -/**Function************************************************************* - - Synopsis [Finds balanced cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManComputeCutLo( Aig_Man_t * p ) -{ - Vec_Ptr_t * vMinCut; - Aig_Obj_t * pObj; - int i; - vMinCut = Vec_PtrAlloc( 100 ); - Aig_ManForEachCi( p, pObj, i ) - Vec_PtrPush( vMinCut, pObj ); - return vMinCut; -} - -/**Function************************************************************* - - Synopsis [Finds balanced cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManComputeCutLi( Aig_Man_t * p ) -{ - Vec_Ptr_t * vMinCut; - Aig_Obj_t * pObj; - int i; - assert( Saig_ManPoNum(p) == 0 ); - vMinCut = Vec_PtrAlloc( 100 ); - Aig_ManIncrementTravId(p); - Saig_ManForEachLi( p, pObj, i ) - { - pObj = Aig_ObjFanin0(pObj); - if ( Aig_ObjIsConst1(pObj) ) - continue; - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - continue; - Aig_ObjSetTravIdCurrent(p, pObj); - Vec_PtrPush( vMinCut, pObj ); - } - return vMinCut; -} - - - -/**Function************************************************************* - - Synopsis [Finds balanced cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManFlowGetObjSet( Aig_Man_t * p, Vec_Ptr_t * vLower, int iStart, int nSize, Vec_Ptr_t * vSet ) -{ - Aig_Obj_t * pObj; - int i; - Vec_PtrClear( vSet ); - for ( i = 0; i < nSize; i++ ) - { - pObj = (Aig_Obj_t *)Vec_PtrEntry( vLower, (iStart + i) % Vec_PtrSize(vLower) ); - Vec_PtrPush( vSet, pObj ); - } -} - -/**Function************************************************************* - - Synopsis [Finds balanced cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManFlowFindBestCut( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, int Num ) -{ - int nVolMin = Aig_ManNodeNum(p) / Num / 2; - Vec_Ptr_t * vMinCut; - Vec_Ptr_t * vCone, * vSet; - Aig_Obj_t * pObj; - int i, s, Vol, VolLower, VolUpper, VolCmp; - int iBest = -1, iMinCut = ABC_INFINITY, iVolBest = 0; - - Vol = Llb_ManCutVolume( p, vLower, vUpper ); - assert( Vol > nVolMin ); - VolCmp = Abc_MinInt( nVolMin, Vol - nVolMin ); - vCone = Vec_PtrAlloc( 100 ); - vSet = Vec_PtrAlloc( 100 ); - Llb_ManFlowPrepareCut( p, vLower, vUpper ); - for ( s = 1; s < Aig_ManRegNum(p); s += 5 ) - { - Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) - { - Llb_ManFlowGetObjSet( p, vLower, i, s, vSet ); - Llb_ManFlowCollectAndMarkCone( p, vSet, vCone ); - if ( Vec_PtrSize(vCone) == 0 ) - continue; - vMinCut = Llb_ManFlowCompute( p ); - Llb_ManFlowUnmarkCone( p, vCone ); - - VolLower = Llb_ManCutVolume( p, vLower, vMinCut ); - VolUpper = Llb_ManCutVolume( p, vMinCut, vUpper ); - Vol = Abc_MinInt( VolLower, VolUpper ); - if ( Vol >= VolCmp && (iMinCut == -1 || - iMinCut > Vec_PtrSize(vMinCut) || - (iMinCut == Vec_PtrSize(vMinCut) && iVolBest < Vol)) ) - { - iBest = i; - iMinCut = Vec_PtrSize(vMinCut); - iVolBest = Vol; - } - Vec_PtrFree( vMinCut ); - } - if ( iBest >= 0 ) - break; - } - if ( iBest == -1 ) - { - // cleanup - Vec_PtrFree( vCone ); - Vec_PtrFree( vSet ); - return NULL; - } - // get the best cut - assert( iBest >= 0 ); - Llb_ManFlowGetObjSet( p, vLower, iBest, s, vSet ); - Llb_ManFlowCollectAndMarkCone( p, vSet, vCone ); - vMinCut = Llb_ManFlowCompute( p ); - Llb_ManFlowUnmarkCone( p, vCone ); - // cleanup - Vec_PtrFree( vCone ); - Vec_PtrFree( vSet ); - return vMinCut; -} - -/**Function************************************************************* - - Synopsis [Finds balanced cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ManComputeCuts( Aig_Man_t * p, int Num, int fVerbose, int fVeryVerbose ) -{ - int nVolMax = Aig_ManNodeNum(p) / Num; - Vec_Ptr_t * vResult, * vMinCut = NULL, * vLower, * vUpper; - int i, k, nVol; - abctime clk = Abc_Clock(); - vResult = Vec_PtrAlloc( 100 ); - Vec_PtrPush( vResult, Llb_ManComputeCutLo(p) ); - Vec_PtrPush( vResult, Llb_ManComputeCutLi(p) ); - while ( 1 ) - { - // find a place to insert new cut - vLower = (Vec_Ptr_t *)Vec_PtrEntry( vResult, 0 ); - Vec_PtrForEachEntryStart( Vec_Ptr_t *, vResult, vUpper, i, 1 ) - { - nVol = Llb_ManCutVolume( p, vLower, vUpper ); - if ( nVol <= nVolMax ) - { - vLower = vUpper; - continue; - } - - if ( fVeryVerbose ) - Llb_ManCutPrint( p, vLower, vUpper ); - vMinCut = Llb_ManFlowFindBestCut( p, vLower, vUpper, Num ); - if ( vMinCut == NULL ) - { - if ( fVeryVerbose ) - printf( "Could not break the cut.\n" ); - if ( fVeryVerbose ) - printf( "\n" ); - vLower = vUpper; - continue; - } - - if ( fVeryVerbose ) - Llb_ManCutPrint( p, vMinCut, vUpper ); - if ( fVeryVerbose ) - Llb_ManCutPrint( p, vLower, vMinCut ); - if ( fVeryVerbose ) - printf( "\n" ); - - break; - } - if ( i == Vec_PtrSize(vResult) ) - break; - // insert vMinCut before vUpper - Vec_PtrPush( vResult, NULL ); - for ( k = Vec_PtrSize(vResult) - 1; k > i; k-- ) - Vec_PtrWriteEntry( vResult, k, Vec_PtrEntry(vResult, k-1) ); - Vec_PtrWriteEntry( vResult, i, vMinCut ); - } - if ( fVerbose ) - { - printf( "Finished computing %d partitions. ", Vec_PtrSize(vResult) - 1 ); - Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); - Llb_ManResultPrint( p, vResult ); - } - return vResult; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_BddSetDefaultParams( Gia_ParLlb_t * p ) -{ - memset( p, 0, sizeof(Gia_ParLlb_t) ); - p->nBddMax = 1000000; - p->nIterMax = 10000000; - p->nClusterMax = 20; - p->nHintDepth = 0; - p->HintFirst = 0; - p->fUseFlow = 0; // use flow - p->nVolumeMax = 100; // max volume - p->nVolumeMin = 30; // min volume - p->fReorder = 1; - p->fIndConstr = 0; - p->fUsePivots = 0; - p->fCluster = 0; - p->fSchedule = 0; - p->fVerbose = 0; - p->fVeryVerbose = 0; - p->fSilent = 0; - p->TimeLimit = 0; -// p->TimeLimit = 0; - p->TimeLimitGlo = 0; - p->TimeTarget = 0; - p->iFrame = -1; -} - -/**Function************************************************************* - - Synopsis [Finds balanced cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ManMinCutTest( Aig_Man_t * pAig, int Num ) -{ - extern void Llb_BddConstructTest( Aig_Man_t * p, Vec_Ptr_t * vResult ); - extern void Llb_BddExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, Vec_Ptr_t * vMaps ); - - -// int fVerbose = 1; - Gia_ParLlb_t Pars, * pPars = &Pars; - Vec_Ptr_t * vResult;//, * vSupps, * vMaps; - Aig_Man_t * p; - - Llb_BddSetDefaultParams( pPars ); - - p = Aig_ManDupFlopsOnly( pAig ); -//Aig_ManShow( p, 0, NULL ); - Aig_ManPrintStats( pAig ); - Aig_ManPrintStats( p ); - Aig_ManFanoutStart( p ); - - vResult = Llb_ManComputeCuts( p, Num, 1, 0 ); -// vSupps = Llb_ManCutSupps( p, vResult ); -// vMaps = Llb_ManCutMap( p, vResult, vSupps ); - -// Llb_BddExperiment( pAig, p, pPars, vResult, vMaps ); - Llb_CoreExperiment( pAig, p, pPars, vResult, 0 ); - -// Vec_VecFree( (Vec_Vec_t *)vMaps ); -// Vec_VecFree( (Vec_Vec_t *)vSupps ); - Vec_VecFree( (Vec_Vec_t *)vResult ); - - Aig_ManFanoutStop( p ); - Aig_ManCleanMarkAB( p ); - Aig_ManStop( p ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/llb/llb2Image.c b/src/proof/llb/llb2Image.c deleted file mode 100644 index e245ba36..00000000 --- a/src/proof/llb/llb2Image.c +++ /dev/null @@ -1,482 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb2Image.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Computes image using partitioned structure.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb2Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern Vec_Ptr_t * Llb_ManCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ); -extern Vec_Ptr_t * Llb_ManCutRange( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes supports of the partitions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_ImgSupports( Aig_Man_t * p, Vec_Ptr_t * vDdMans, Vec_Int_t * vStart, Vec_Int_t * vStop, int fAddPis, int fVerbose ) -{ - Vec_Ptr_t * vSupps; - Vec_Int_t * vOne; - Aig_Obj_t * pObj; - DdManager * dd; - DdNode * bSupp, * bTemp; - int i, Entry, nSize; - nSize = Cudd_ReadSize( (DdManager *)Vec_PtrEntry( vDdMans, 0 ) ); - vSupps = Vec_PtrAlloc( 100 ); - // create initial - vOne = Vec_IntStart( nSize ); - Vec_IntForEachEntry( vStart, Entry, i ) - Vec_IntWriteEntry( vOne, Entry, 1 ); - Vec_PtrPush( vSupps, vOne ); - // create intermediate - Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i ) - { - vOne = Vec_IntStart( nSize ); - bSupp = Cudd_Support( dd, dd->bFunc ); Cudd_Ref( bSupp ); - for ( bTemp = bSupp; bTemp != Cudd_ReadOne(dd); bTemp = cuddT(bTemp) ) - Vec_IntWriteEntry( vOne, bTemp->index, 1 ); - Cudd_RecursiveDeref( dd, bSupp ); - Vec_PtrPush( vSupps, vOne ); - } - // create final - vOne = Vec_IntStart( nSize ); - Vec_IntForEachEntry( vStop, Entry, i ) - Vec_IntWriteEntry( vOne, Entry, 1 ); - if ( fAddPis ) - Saig_ManForEachPi( p, pObj, i ) - Vec_IntWriteEntry( vOne, Aig_ObjId(pObj), 1 ); - Vec_PtrPush( vSupps, vOne ); - - // print supports - assert( nSize == Aig_ManObjNumMax(p) ); - if ( !fVerbose ) - return vSupps; - Aig_ManForEachObj( p, pObj, i ) - { - int k, Counter = 0; - Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k ) - Counter += Vec_IntEntry(vOne, i); - if ( Counter == 0 ) - continue; - printf( "Obj = %4d : ", i ); - if ( Saig_ObjIsPi(p,pObj) ) - printf( "pi " ); - else if ( Saig_ObjIsLo(p,pObj) ) - printf( "lo " ); - else if ( Saig_ObjIsLi(p,pObj) ) - printf( "li " ); - else if ( Aig_ObjIsNode(pObj) ) - printf( "and " ); - Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k ) - printf( "%d", Vec_IntEntry(vOne, i) ); - printf( "\n" ); - } - return vSupps; -} - -/**Function************************************************************* - - Synopsis [Computes quantification schedule.] - - Description [Input array contains supports: 0=starting, ... intermediate... - N-1=final. Output arrays contain immediately quantifiable vars (vQuant0) - and vars that should be quantified after conjunction (vQuant1).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ImgSchedule( Vec_Ptr_t * vSupps, Vec_Ptr_t ** pvQuant0, Vec_Ptr_t ** pvQuant1, int fVerbose ) -{ - Vec_Int_t * vOne; - int nVarsAll, Counter, iSupp = -1, Entry, i, k; - // start quantification arrays - *pvQuant0 = Vec_PtrAlloc( Vec_PtrSize(vSupps) ); - *pvQuant1 = Vec_PtrAlloc( Vec_PtrSize(vSupps) ); - Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k ) - { - Vec_PtrPush( *pvQuant0, Vec_IntAlloc(16) ); - Vec_PtrPush( *pvQuant1, Vec_IntAlloc(16) ); - } - // count how many times each var appears - nVarsAll = Vec_IntSize( (Vec_Int_t *)Vec_PtrEntry(vSupps, 0) ); - for ( i = 0; i < nVarsAll; i++ ) - { - Counter = 0; - Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vOne, k ) - if ( Vec_IntEntry(vOne, i) ) - { - iSupp = k; - Counter++; - } - if ( Counter == 0 ) - continue; - if ( Counter == 1 ) - Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(*pvQuant0, iSupp), i ); - else // if ( Counter > 1 ) - Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(*pvQuant1, iSupp), i ); - } - - if ( fVerbose ) - for ( i = 0; i < Vec_PtrSize(vSupps); i++ ) - { - printf( "%2d : Quant0 = ", i ); - Vec_IntForEachEntry( (Vec_Int_t *)Vec_PtrEntry(*pvQuant0, i), Entry, k ) - printf( "%d ", Entry ); - printf( "\n" ); - } - - if ( fVerbose ) - for ( i = 0; i < Vec_PtrSize(vSupps); i++ ) - { - printf( "%2d : Quant1 = ", i ); - Vec_IntForEachEntry( (Vec_Int_t *)Vec_PtrEntry(*pvQuant1, i), Entry, k ) - printf( "%d ", Entry ); - printf( "\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Computes one partition in a separate BDD manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdManager * Llb_ImgPartition( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, abctime TimeTarget ) -{ - Vec_Ptr_t * vNodes, * vRange; - Aig_Obj_t * pObj; - DdManager * dd; - DdNode * bBdd0, * bBdd1, * bProd, * bRes, * bTemp; - int i; - - dd = Cudd_Init( Aig_ManObjNumMax(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - dd->TimeStop = TimeTarget; - - Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) - pObj->pData = Cudd_bddIthVar( dd, Aig_ObjId(pObj) ); - - vNodes = Llb_ManCutNodes( p, vLower, vUpper ); - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - { - bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); -// pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData ); -// pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeTarget ); - pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); - if ( pObj->pData == NULL ) - { - Cudd_Quit( dd ); - Vec_PtrFree( vNodes ); - return NULL; - } - Cudd_Ref( (DdNode *)pObj->pData ); - } - - vRange = Llb_ManCutRange( p, vLower, vUpper ); - bRes = Cudd_ReadOne(dd); Cudd_Ref( bRes ); - Vec_PtrForEachEntry( Aig_Obj_t *, vRange, pObj, i ) - { - assert( Aig_ObjIsNode(pObj) ); - bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), (DdNode *)pObj->pData ); Cudd_Ref( bProd ); -// bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); Cudd_Ref( bRes ); -// bRes = Extra_bddAndTime( dd, bTemp = bRes, bProd, TimeTarget ); - bRes = Cudd_bddAnd( dd, bTemp = bRes, bProd ); - if ( bRes == NULL ) - { - Cudd_Quit( dd ); - Vec_PtrFree( vRange ); - Vec_PtrFree( vNodes ); - return NULL; - } - Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bProd ); - } - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - - Vec_PtrFree( vRange ); - Vec_PtrFree( vNodes ); - Cudd_AutodynDisable( dd ); -// Cudd_RecursiveDeref( dd, bRes ); -// Extra_StopManager( dd ); - dd->bFunc = bRes; - dd->TimeStop = 0; - return dd; -} - -/**Function************************************************************* - - Synopsis [Derives positive cube composed of nodes IDs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ImgComputeCube( Aig_Man_t * pAig, Vec_Int_t * vNodeIds, DdManager * dd ) -{ - DdNode * bProd, * bTemp; - Aig_Obj_t * pObj; - int i; - abctime TimeStop; - TimeStop = dd->TimeStop; dd->TimeStop = 0; - bProd = Cudd_ReadOne(dd); Cudd_Ref( bProd ); - Aig_ManForEachObjVec( vNodeIds, pAig, pObj, i ) - { - bProd = Cudd_bddAnd( dd, bTemp = bProd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)) ); Cudd_Ref( bProd ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bProd ); - dd->TimeStop = TimeStop; - return bProd; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ImgQuantifyFirst( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, Vec_Ptr_t * vQuant0, int fVerbose ) -{ - DdManager * dd; - DdNode * bProd, * bRes, * bTemp; - int i; - abctime clk = Abc_Clock(); - Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i ) - { - // remember unquantified ones - assert( dd->bFunc2 == NULL ); - dd->bFunc2 = dd->bFunc; Cudd_Ref( dd->bFunc2 ); - - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - - bRes = dd->bFunc; - if ( fVerbose ) - Abc_Print( 1, "Part %2d : Init =%5d. ", i, Cudd_DagSize(bRes) ); - bProd = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, i+1), dd ); Cudd_Ref( bProd ); - bRes = Cudd_bddExistAbstract( dd, bTemp = bRes, bProd ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bProd ); - dd->bFunc = bRes; - - Cudd_AutodynDisable( dd ); - - if ( fVerbose ) - Abc_Print( 1, "Quant =%5d. ", Cudd_DagSize(bRes) ); - Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); - if ( fVerbose ) - Abc_Print( 1, "Reo = %5d. ", Cudd_DagSize(bRes) ); - Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); - if ( fVerbose ) - Abc_Print( 1, "Reo = %5d. ", Cudd_DagSize(bRes) ); - if ( fVerbose ) - Abc_Print( 1, "Supp = %3d. ", Cudd_SupportSize(dd, bRes) ); - if ( fVerbose ) - Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); - - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_ImgQuantifyReset( Vec_Ptr_t * vDdMans ) -{ - DdManager * dd; - int i; - Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i ) - { - assert( dd->bFunc2 != NULL ); - Cudd_RecursiveDeref( dd, dd->bFunc ); - dd->bFunc = dd->bFunc2; - dd->bFunc2 = NULL; - } -} - -/**Function************************************************************* - - Synopsis [Computes image of the initial set of states.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_ImgComputeImage( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, DdManager * dd, DdNode * bInit, - Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1, Vec_Int_t * vDriRefs, - abctime TimeTarget, int fBackward, int fReorder, int fVerbose ) -{ -// int fCheckSupport = 0; - DdManager * ddPart; - DdNode * bImage, * bGroup, * bCube, * bTemp; - int i; - abctime clk, clk0 = Abc_Clock(); - - bImage = bInit; Cudd_Ref( bImage ); - if ( fBackward ) - { - // change polarity - bCube = Llb_DriverPhaseCube( pAig, vDriRefs, dd ); Cudd_Ref( bCube ); - bImage = Extra_bddChangePolarity( dd, bTemp = bImage, bCube ); Cudd_Ref( bImage ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bCube ); - } - else - { - // quantify unique vriables - bCube = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, 0), dd ); Cudd_Ref( bCube ); - bImage = Cudd_bddExistAbstract( dd, bTemp = bImage, bCube ); - if ( bImage == NULL ) - { - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bCube ); - return NULL; - } - Cudd_Ref( bImage ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bCube ); - } - // perform image computation - Vec_PtrForEachEntry( DdManager *, vDdMans, ddPart, i ) - { - clk = Abc_Clock(); -if ( fVerbose ) -printf( " %2d : ", i ); - // transfer the BDD from the group manager to the main manager - bGroup = Cudd_bddTransfer( ddPart, dd, ddPart->bFunc ); - if ( bGroup == NULL ) - return NULL; - Cudd_Ref( bGroup ); -if ( fVerbose ) -printf( "Pt0 =%6d. Pt1 =%6d. ", Cudd_DagSize(ddPart->bFunc), Cudd_DagSize(bGroup) ); - // perform partial product - bCube = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant1, i+1), dd ); Cudd_Ref( bCube ); -// bImage = Cudd_bddAndAbstract( dd, bTemp = bImage, bGroup, bCube ); -// bImage = Extra_bddAndAbstractTime( dd, bTemp = bImage, bGroup, bCube, TimeTarget ); - bImage = Cudd_bddAndAbstract( dd, bTemp = bImage, bGroup, bCube ); - if ( bImage == NULL ) - { - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bCube ); - Cudd_RecursiveDeref( dd, bGroup ); - return NULL; - } - Cudd_Ref( bImage ); - -if ( fVerbose ) -printf( "Im0 =%6d. Im1 =%6d. ", Cudd_DagSize(bTemp), Cudd_DagSize(bImage) ); -//printf("\n"); Extra_bddPrintSupport(dd, bImage); printf("\n"); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bCube ); - Cudd_RecursiveDeref( dd, bGroup ); - -// Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); -// Abc_Print( 1, "Reo =%6d. ", Cudd_DagSize(bImage) ); - -if ( fVerbose ) -printf( "Supp =%3d. ", Cudd_SupportSize(dd, bImage) ); -if ( fVerbose ) -Abc_PrintTime( 1, "T", Abc_Clock() - clk ); - } - - if ( !fBackward ) - { - // change polarity - bCube = Llb_DriverPhaseCube( pAig, vDriRefs, dd ); Cudd_Ref( bCube ); - bImage = Extra_bddChangePolarity( dd, bTemp = bImage, bCube ); Cudd_Ref( bImage ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bCube ); - } - else - { - // quantify unique vriables - bCube = Llb_ImgComputeCube( pAig, (Vec_Int_t *)Vec_PtrEntry(vQuant0, 0), dd ); Cudd_Ref( bCube ); - bImage = Cudd_bddExistAbstract( dd, bTemp = bImage, bCube ); Cudd_Ref( bImage ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bCube ); - } - - if ( fReorder ) - { - if ( fVerbose ) - Abc_Print( 1, " Reordering... Before =%5d. ", Cudd_DagSize(bImage) ); - Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); - if ( fVerbose ) - Abc_Print( 1, "After =%5d. ", Cudd_DagSize(bImage) ); -// Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); -// Abc_Print( 1, "After =%5d. ", Cudd_DagSize(bImage) ); - if ( fVerbose ) - Abc_PrintTime( 1, "Time", Abc_Clock() - clk0 ); -// Abc_Print( 1, "\n" ); - } - - Cudd_Deref( bImage ); - return bImage; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/llb/llb3Image.c b/src/proof/llb/llb3Image.c deleted file mode 100644 index 72c6120a..00000000 --- a/src/proof/llb/llb3Image.c +++ /dev/null @@ -1,1095 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb3Image.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Computes image using partitioned structure.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb3Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Llb_Var_t_ Llb_Var_t; -struct Llb_Var_t_ -{ - int iVar; // variable number - int nScore; // variable score - Vec_Int_t * vParts; // partitions -}; - -typedef struct Llb_Prt_t_ Llb_Prt_t; -struct Llb_Prt_t_ -{ - int iPart; // partition number - int nSize; // the number of BDD nodes - DdNode * bFunc; // the partition - Vec_Int_t * vVars; // support -}; - -typedef struct Llb_Mgr_t_ Llb_Mgr_t; -struct Llb_Mgr_t_ -{ - Aig_Man_t * pAig; // AIG manager - Vec_Ptr_t * vLeaves; // leaves in the AIG manager - Vec_Ptr_t * vRoots; // roots in the AIG manager - DdManager * dd; // working BDD manager - int * pVars2Q; // variables to quantify - // internal - Llb_Prt_t ** pParts; // partitions - Llb_Var_t ** pVars; // variables - int iPartFree; // next free partition - int nVars; // the number of BDD variables - int nSuppMax; // maximum support size - // temporary - int * pSupp; // temporary support storage -}; - -static inline Llb_Var_t * Llb_MgrVar( Llb_Mgr_t * p, int i ) { return p->pVars[i]; } -static inline Llb_Prt_t * Llb_MgrPart( Llb_Mgr_t * p, int i ) { return p->pParts[i]; } - -// iterator over vars -#define Llb_MgrForEachVar( p, pVar, i ) \ - for ( i = 0; (i < p->nVars) && (((pVar) = Llb_MgrVar(p, i)), 1); i++ ) if ( pVar == NULL ) {} else -// iterator over parts -#define Llb_MgrForEachPart( p, pPart, i ) \ - for ( i = 0; (i < p->iPartFree) && (((pPart) = Llb_MgrPart(p, i)), 1); i++ ) if ( pPart == NULL ) {} else - -// iterator over vars of one partition -#define Llb_PartForEachVar( p, pPart, pVar, i ) \ - for ( i = 0; (i < Vec_IntSize(pPart->vVars)) && (((pVar) = Llb_MgrVar(p, Vec_IntEntry(pPart->vVars,i))), 1); i++ ) -// iterator over parts of one variable -#define Llb_VarForEachPart( p, pVar, pPart, i ) \ - for ( i = 0; (i < Vec_IntSize(pVar->vParts)) && (((pPart) = Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,i))), 1); i++ ) - -// statistics -abctime timeBuild, timeAndEx, timeOther; -int nSuppMax; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Removes one variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinRemoveVar( Llb_Mgr_t * p, Llb_Var_t * pVar ) -{ - assert( p->pVars[pVar->iVar] == pVar ); - p->pVars[pVar->iVar] = NULL; - Vec_IntFree( pVar->vParts ); - ABC_FREE( pVar ); -} - -/**Function************************************************************* - - Synopsis [Removes one partition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinRemovePart( Llb_Mgr_t * p, Llb_Prt_t * pPart ) -{ - assert( p->pParts[pPart->iPart] == pPart ); - p->pParts[pPart->iPart] = NULL; - Vec_IntFree( pPart->vVars ); - Cudd_RecursiveDeref( p->dd, pPart->bFunc ); - ABC_FREE( pPart ); -} - -/**Function************************************************************* - - Synopsis [Create cube with singleton variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_NonlinCreateCube1( Llb_Mgr_t * p, Llb_Prt_t * pPart ) -{ - DdNode * bCube, * bTemp; - Llb_Var_t * pVar; - int i; - abctime TimeStop; - TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; - bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube ); - Llb_PartForEachVar( p, pPart, pVar, i ) - { - assert( Vec_IntSize(pVar->vParts) > 0 ); - if ( Vec_IntSize(pVar->vParts) != 1 ) - continue; - assert( Vec_IntEntry(pVar->vParts, 0) == pPart->iPart ); - bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - Cudd_Deref( bCube ); - p->dd->TimeStop = TimeStop; - return bCube; -} - -/**Function************************************************************* - - Synopsis [Create cube of variables appearing only in two partitions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_NonlinCreateCube2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 ) -{ - DdNode * bCube, * bTemp; - Llb_Var_t * pVar; - int i; - abctime TimeStop; - TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; - bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube ); - Llb_PartForEachVar( p, pPart1, pVar, i ) - { - assert( Vec_IntSize(pVar->vParts) > 0 ); - if ( Vec_IntSize(pVar->vParts) != 2 ) - continue; - if ( (Vec_IntEntry(pVar->vParts, 0) == pPart1->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart2->iPart) || - (Vec_IntEntry(pVar->vParts, 0) == pPart2->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart1->iPart) ) - { - bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - } - Cudd_Deref( bCube ); - p->dd->TimeStop = TimeStop; - return bCube; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if partition has singleton variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_NonlinHasSingletonVars( Llb_Mgr_t * p, Llb_Prt_t * pPart ) -{ - Llb_Var_t * pVar; - int i; - Llb_PartForEachVar( p, pPart, pVar, i ) - if ( Vec_IntSize(pVar->vParts) == 1 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if partition has singleton variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinPrint( Llb_Mgr_t * p ) -{ - Llb_Prt_t * pPart; - Llb_Var_t * pVar; - int i, k; - printf( "\n" ); - Llb_MgrForEachVar( p, pVar, i ) - { - printf( "Var %3d : ", i ); - Llb_VarForEachPart( p, pVar, pPart, k ) - printf( "%d ", pPart->iPart ); - printf( "\n" ); - } - Llb_MgrForEachPart( p, pPart, i ) - { - printf( "Part %3d : ", i ); - Llb_PartForEachVar( p, pPart, pVar, k ) - printf( "%d ", pVar->iVar ); - printf( "\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Quantifies singles belonging to one partition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_NonlinQuantify1( Llb_Mgr_t * p, Llb_Prt_t * pPart, int fSubset ) -{ - Llb_Var_t * pVar; - Llb_Prt_t * pTemp; - Vec_Ptr_t * vSingles; - DdNode * bCube, * bTemp; - int i, RetValue, nSizeNew; - if ( fSubset ) - { - int Length; -// int nSuppSize = Cudd_SupportSize( p->dd, pPart->bFunc ); -// pPart->bFunc = Cudd_SubsetHeavyBranch( p->dd, bTemp = pPart->bFunc, nSuppSize, 3*pPart->nSize/4 ); Cudd_Ref( pPart->bFunc ); - pPart->bFunc = Cudd_LargestCube( p->dd, bTemp = pPart->bFunc, &Length ); Cudd_Ref( pPart->bFunc ); - - printf( "Subsetting %3d : ", pPart->iPart ); - printf( "(Supp =%3d Node =%5d) -> ", Cudd_SupportSize(p->dd, bTemp), Cudd_DagSize(bTemp) ); - printf( "(Supp =%3d Node =%5d)\n", Cudd_SupportSize(p->dd, pPart->bFunc), Cudd_DagSize(pPart->bFunc) ); - - RetValue = (Cudd_DagSize(bTemp) == Cudd_DagSize(pPart->bFunc)); - - Cudd_RecursiveDeref( p->dd, bTemp ); - - if ( RetValue ) - return 1; - } - else - { - // create cube to be quantified - bCube = Llb_NonlinCreateCube1( p, pPart ); Cudd_Ref( bCube ); -// assert( !Cudd_IsConstant(bCube) ); - // derive new function - pPart->bFunc = Cudd_bddExistAbstract( p->dd, bTemp = pPart->bFunc, bCube ); Cudd_Ref( pPart->bFunc ); - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bCube ); - } - // get support - vSingles = Vec_PtrAlloc( 0 ); - nSizeNew = Cudd_DagSize(pPart->bFunc); - Extra_SupportArray( p->dd, pPart->bFunc, p->pSupp ); - Llb_PartForEachVar( p, pPart, pVar, i ) - if ( p->pSupp[pVar->iVar] ) - { - assert( Vec_IntSize(pVar->vParts) > 1 ); - pVar->nScore -= pPart->nSize - nSizeNew; - } - else - { - RetValue = Vec_IntRemove( pVar->vParts, pPart->iPart ); - assert( RetValue ); - pVar->nScore -= pPart->nSize; - if ( Vec_IntSize(pVar->vParts) == 0 ) - Llb_NonlinRemoveVar( p, pVar ); - else if ( Vec_IntSize(pVar->vParts) == 1 ) - Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); - } - - // update partition - pPart->nSize = nSizeNew; - Vec_IntClear( pPart->vVars ); - for ( i = 0; i < p->nVars; i++ ) - if ( p->pSupp[i] && p->pVars2Q[i] ) - Vec_IntPush( pPart->vVars, i ); - // remove other variables - Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i ) - Llb_NonlinQuantify1( p, pTemp, 0 ); - Vec_PtrFree( vSingles ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Quantifies singles belonging to one partition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_NonlinQuantify2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 ) -{ - int fVerbose = 0; - Llb_Var_t * pVar; - Llb_Prt_t * pTemp; - Vec_Ptr_t * vSingles; - DdNode * bCube, * bFunc; - int i, RetValue, nSuppSize; -// int iPart1 = pPart1->iPart; -// int iPart2 = pPart2->iPart; - - // create cube to be quantified - bCube = Llb_NonlinCreateCube2( p, pPart1, pPart2 ); Cudd_Ref( bCube ); -if ( fVerbose ) -{ -printf( "\n" ); -printf( "\n" ); -Llb_NonlinPrint( p ); -printf( "Conjoining partitions %d and %d.\n", pPart1->iPart, pPart2->iPart ); -Extra_bddPrintSupport( p->dd, bCube ); printf( "\n" ); -} - - // derive new function -// bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube ); Cudd_Ref( bFunc ); -/* - bFunc = Cudd_bddAndAbstractLimit( p->dd, pPart1->bFunc, pPart2->bFunc, bCube, Limit ); - if ( bFunc == NULL ) - { - int RetValue; - Cudd_RecursiveDeref( p->dd, bCube ); - if ( pPart1->nSize < pPart2->nSize ) - RetValue = Llb_NonlinQuantify1( p, pPart1, 1 ); - else - RetValue = Llb_NonlinQuantify1( p, pPart2, 1 ); - if ( RetValue ) - Limit = Limit + 1000; - Llb_NonlinQuantify2( p, pPart1, pPart2 ); - return 0; - } - Cudd_Ref( bFunc ); -*/ - -// bFunc = Extra_bddAndAbstractTime( p->dd, pPart1->bFunc, pPart2->bFunc, bCube, TimeOut ); - bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube ); - if ( bFunc == NULL ) - { - Cudd_RecursiveDeref( p->dd, bCube ); - return 0; - } - Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( p->dd, bCube ); - - // create new partition - pTemp = p->pParts[p->iPartFree] = ABC_CALLOC( Llb_Prt_t, 1 ); - pTemp->iPart = p->iPartFree++; - pTemp->nSize = Cudd_DagSize(bFunc); - pTemp->bFunc = bFunc; - pTemp->vVars = Vec_IntAlloc( 8 ); - // update variables - Llb_PartForEachVar( p, pPart1, pVar, i ) - { - RetValue = Vec_IntRemove( pVar->vParts, pPart1->iPart ); - assert( RetValue ); - pVar->nScore -= pPart1->nSize; - } - // update variables - Llb_PartForEachVar( p, pPart2, pVar, i ) - { - RetValue = Vec_IntRemove( pVar->vParts, pPart2->iPart ); - assert( RetValue ); - pVar->nScore -= pPart2->nSize; - } - // add variables to the new partition - nSuppSize = 0; - Extra_SupportArray( p->dd, bFunc, p->pSupp ); - for ( i = 0; i < p->nVars; i++ ) - { - nSuppSize += p->pSupp[i]; - if ( p->pSupp[i] && p->pVars2Q[i] ) - { - pVar = Llb_MgrVar( p, i ); - pVar->nScore += pTemp->nSize; - Vec_IntPush( pVar->vParts, pTemp->iPart ); - Vec_IntPush( pTemp->vVars, i ); - } - } - p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize ); - // remove variables and collect partitions with singleton variables - vSingles = Vec_PtrAlloc( 0 ); - Llb_PartForEachVar( p, pPart1, pVar, i ) - { - if ( Vec_IntSize(pVar->vParts) == 0 ) - Llb_NonlinRemoveVar( p, pVar ); - else if ( Vec_IntSize(pVar->vParts) == 1 ) - { - if ( fVerbose ) - printf( "Adding partition %d because of var %d.\n", - Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar ); - Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); - } - } - Llb_PartForEachVar( p, pPart2, pVar, i ) - { - if ( pVar == NULL ) - continue; - if ( Vec_IntSize(pVar->vParts) == 0 ) - Llb_NonlinRemoveVar( p, pVar ); - else if ( Vec_IntSize(pVar->vParts) == 1 ) - { - if ( fVerbose ) - printf( "Adding partition %d because of var %d.\n", - Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar ); - Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); - } - } - // remove partitions - Llb_NonlinRemovePart( p, pPart1 ); - Llb_NonlinRemovePart( p, pPart2 ); - // remove other variables -if ( fVerbose ) -Llb_NonlinPrint( p ); - Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i ) - { -if ( fVerbose ) -printf( "Updating partitiong %d with singlton vars.\n", pTemp->iPart ); - Llb_NonlinQuantify1( p, pTemp, 0 ); - } -if ( fVerbose ) -Llb_NonlinPrint( p ); - Vec_PtrFree( vSingles ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes volume of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinCutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) -{ - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return; - Aig_ObjSetTravIdCurrent(p, pObj); - if ( Saig_ObjIsLi(p, pObj) ) - { - Llb_NonlinCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); - return; - } - if ( Aig_ObjIsConst1(pObj) ) - return; - assert( Aig_ObjIsNode(pObj) ); - Llb_NonlinCutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); - Llb_NonlinCutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes); - Vec_PtrPush( vNodes, pObj ); -} - -/**Function************************************************************* - - Synopsis [Computes volume of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_NonlinCutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i; - // mark the lower cut with the traversal ID - Aig_ManIncrementTravId(p); - Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) - Aig_ObjSetTravIdCurrent( p, pObj ); - // count the upper cut - vNodes = Vec_PtrAlloc( 100 ); - Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) - Llb_NonlinCutNodes_rec( p, pObj, vNodes ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Returns array of BDDs for the roots in terms of the leaves.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_NonlinBuildBdds( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, DdManager * dd ) -{ - Vec_Ptr_t * vNodes, * vResult; - Aig_Obj_t * pObj; - DdNode * bBdd0, * bBdd1, * bProd; - int i, k; - - Aig_ManConst1(p)->pData = Cudd_ReadOne( dd ); - Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) - pObj->pData = Cudd_bddIthVar( dd, Aig_ObjId(pObj) ); - - vNodes = Llb_NonlinCutNodes( p, vLower, vUpper ); - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - { - bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); -// pObj->pData = Extra_bddAndTime( dd, bBdd0, bBdd1, TimeOut ); - pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); - if ( pObj->pData == NULL ) - { - Vec_PtrForEachEntryStop( Aig_Obj_t *, vNodes, pObj, k, i ) - if ( pObj->pData ) - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - Vec_PtrFree( vNodes ); - return NULL; - } - Cudd_Ref( (DdNode *)pObj->pData ); - } - - vResult = Vec_PtrAlloc( 100 ); - Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) - { - if ( Aig_ObjIsNode(pObj) ) - { - bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), (DdNode *)pObj->pData ); Cudd_Ref( bProd ); - } - else - { - assert( Saig_ObjIsLi(p, pObj) ); - bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bProd = Cudd_bddXnor( dd, Cudd_bddIthVar(dd, Aig_ObjId(pObj)), bBdd0 ); Cudd_Ref( bProd ); - } - Vec_PtrPush( vResult, bProd ); - } - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - - Vec_PtrFree( vNodes ); - return vResult; -} - -/**Function************************************************************* - - Synopsis [Starts non-linear quantification scheduling.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinAddPair( Llb_Mgr_t * p, DdNode * bFunc, int iPart, int iVar ) -{ - if ( p->pVars[iVar] == NULL ) - { - p->pVars[iVar] = ABC_CALLOC( Llb_Var_t, 1 ); - p->pVars[iVar]->iVar = iVar; - p->pVars[iVar]->nScore = 0; - p->pVars[iVar]->vParts = Vec_IntAlloc( 8 ); - } - Vec_IntPush( p->pVars[iVar]->vParts, iPart ); - Vec_IntPush( p->pParts[iPart]->vVars, iVar ); -} - -/**Function************************************************************* - - Synopsis [Starts non-linear quantification scheduling.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinAddPartition( Llb_Mgr_t * p, int i, DdNode * bFunc ) -{ - int k, nSuppSize; - assert( !Cudd_IsConstant(bFunc) ); - // create partition - p->pParts[i] = ABC_CALLOC( Llb_Prt_t, 1 ); - p->pParts[i]->iPart = i; - p->pParts[i]->bFunc = bFunc; - p->pParts[i]->vVars = Vec_IntAlloc( 8 ); - // add support dependencies - nSuppSize = 0; - Extra_SupportArray( p->dd, bFunc, p->pSupp ); - for ( k = 0; k < p->nVars; k++ ) - { - nSuppSize += p->pSupp[k]; - if ( p->pSupp[k] && p->pVars2Q[k] ) - Llb_NonlinAddPair( p, bFunc, i, k ); - } - p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize ); -} - -/**Function************************************************************* - - Synopsis [Starts non-linear quantification scheduling.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_NonlinStart( Llb_Mgr_t * p ) -{ - Vec_Ptr_t * vRootBdds; - DdNode * bFunc; - int i; - // create and collect BDDs - vRootBdds = Llb_NonlinBuildBdds( p->pAig, p->vLeaves, p->vRoots, p->dd ); // come referenced - if ( vRootBdds == NULL ) - return 0; - // add pairs (refs are consumed inside) - Vec_PtrForEachEntry( DdNode *, vRootBdds, bFunc, i ) - Llb_NonlinAddPartition( p, i, bFunc ); - Vec_PtrFree( vRootBdds ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Checks that each var appears in at least one partition.] - - Description [] - - SideEffects [] - - SeeAlso [] -**********************************************************************/ -void Llb_NonlinCheckVars( Llb_Mgr_t * p ) -{ - Llb_Var_t * pVar; - int i; - Llb_MgrForEachVar( p, pVar, i ) - assert( Vec_IntSize(pVar->vParts) > 1 ); -} - -/**Function************************************************************* - - Synopsis [Find next partition to quantify] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_NonlinNextPartitions( Llb_Mgr_t * p, Llb_Prt_t ** ppPart1, Llb_Prt_t ** ppPart2 ) -{ - Llb_Var_t * pVar, * pVarBest = NULL; - Llb_Prt_t * pPart, * pPart1Best = NULL, * pPart2Best = NULL; - int i; - Llb_NonlinCheckVars( p ); - // find variable with minimum score - Llb_MgrForEachVar( p, pVar, i ) - if ( pVarBest == NULL || pVarBest->nScore > pVar->nScore ) - pVarBest = pVar; - if ( pVarBest == NULL ) - return 0; - // find two partitions with minimum size - Llb_VarForEachPart( p, pVarBest, pPart, i ) - { - if ( pPart1Best == NULL ) - pPart1Best = pPart; - else if ( pPart2Best == NULL ) - pPart2Best = pPart; - else if ( pPart1Best->nSize > pPart->nSize || pPart2Best->nSize > pPart->nSize ) - { - if ( pPart1Best->nSize > pPart2Best->nSize ) - pPart1Best = pPart; - else - pPart2Best = pPart; - } - } - *ppPart1 = pPart1Best; - *ppPart2 = pPart2Best; - return 1; -} - -/**Function************************************************************* - - Synopsis [Reorders BDDs in the working manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinReorder( DdManager * dd, int fTwice, int fVerbose ) -{ - abctime clk = Abc_Clock(); - if ( fVerbose ) - Abc_Print( 1, "Reordering... Before =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); - Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); - if ( fVerbose ) - Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); - if ( fTwice ) - { - Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); - if ( fVerbose ) - Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); - } - if ( fVerbose ) - Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); -} - -/**Function************************************************************* - - Synopsis [Recomputes scores after variable reordering.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinRecomputeScores( Llb_Mgr_t * p ) -{ - Llb_Prt_t * pPart; - Llb_Var_t * pVar; - int i, k; - Llb_MgrForEachPart( p, pPart, i ) - pPart->nSize = Cudd_DagSize(pPart->bFunc); - Llb_MgrForEachVar( p, pVar, i ) - { - pVar->nScore = 0; - Llb_VarForEachPart( p, pVar, pPart, k ) - pVar->nScore += pPart->nSize; - } -} - -/**Function************************************************************* - - Synopsis [Recomputes scores after variable reordering.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinVerifyScores( Llb_Mgr_t * p ) -{ - Llb_Prt_t * pPart; - Llb_Var_t * pVar; - int i, k, nScore; - Llb_MgrForEachPart( p, pPart, i ) - assert( pPart->nSize == Cudd_DagSize(pPart->bFunc) ); - Llb_MgrForEachVar( p, pVar, i ) - { - nScore = 0; - Llb_VarForEachPart( p, pVar, pPart, k ) - nScore += pPart->nSize; - assert( nScore == pVar->nScore ); - } -} - -/**Function************************************************************* - - Synopsis [Starts non-linear quantification scheduling.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Mgr_t * Llb_NonlinAlloc( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, DdManager * dd ) -{ - Llb_Mgr_t * p; - p = ABC_CALLOC( Llb_Mgr_t, 1 ); - p->pAig = pAig; - p->vLeaves = vLeaves; - p->vRoots = vRoots; - p->dd = dd; - p->pVars2Q = pVars2Q; - p->nVars = Cudd_ReadSize(dd); - p->iPartFree = Vec_PtrSize(vRoots); - p->pVars = ABC_CALLOC( Llb_Var_t *, p->nVars ); - p->pParts = ABC_CALLOC( Llb_Prt_t *, 2 * p->iPartFree + 2 ); - p->pSupp = ABC_ALLOC( int, Cudd_ReadSize(dd) ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops non-linear quantification scheduling.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinFree( Llb_Mgr_t * p ) -{ - Llb_Prt_t * pPart; - Llb_Var_t * pVar; - int i; - Llb_MgrForEachVar( p, pVar, i ) - Llb_NonlinRemoveVar( p, pVar ); - Llb_MgrForEachPart( p, pPart, i ) - Llb_NonlinRemovePart( p, pPart ); - ABC_FREE( p->pVars ); - ABC_FREE( p->pParts ); - ABC_FREE( p->pSupp ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Performs image computation.] - - Description [Computes image of BDDs (vFuncs).] - - SideEffects [BDDs in vFuncs are derefed inside. The result is refed.] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_NonlinImage( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, - DdManager * dd, DdNode * bCurrent, int fReorder, int fVerbose, int * pOrder ) -{ - Llb_Prt_t * pPart, * pPart1, * pPart2; - Llb_Mgr_t * p; - DdNode * bFunc, * bTemp; - int i, nReorders, timeInside; - abctime clk = Abc_Clock(), clk2; - // start the manager - clk2 = Abc_Clock(); - p = Llb_NonlinAlloc( pAig, vLeaves, vRoots, pVars2Q, dd ); - if ( !Llb_NonlinStart( p ) ) - { - Llb_NonlinFree( p ); - return NULL; - } - // add partition - Llb_NonlinAddPartition( p, p->iPartFree++, bCurrent ); - // remove singles - Llb_MgrForEachPart( p, pPart, i ) - if ( Llb_NonlinHasSingletonVars(p, pPart) ) - Llb_NonlinQuantify1( p, pPart, 0 ); - timeBuild += Abc_Clock() - clk2; - timeInside = Abc_Clock() - clk2; - // compute scores - Llb_NonlinRecomputeScores( p ); - // save permutation - if ( pOrder ) - memcpy( pOrder, dd->invperm, sizeof(int) * dd->size ); - // iteratively quantify variables - while ( Llb_NonlinNextPartitions(p, &pPart1, &pPart2) ) - { - clk2 = Abc_Clock(); - nReorders = Cudd_ReadReorderings(dd); - if ( !Llb_NonlinQuantify2( p, pPart1, pPart2 ) ) - { - Llb_NonlinFree( p ); - return NULL; - } - timeAndEx += Abc_Clock() - clk2; - timeInside += Abc_Clock() - clk2; - if ( nReorders < Cudd_ReadReorderings(dd) ) - Llb_NonlinRecomputeScores( p ); -// else -// Llb_NonlinVerifyScores( p ); - } - // load partitions - bFunc = Cudd_ReadOne(p->dd); Cudd_Ref( bFunc ); - Llb_MgrForEachPart( p, pPart, i ) - { - bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - nSuppMax = p->nSuppMax; - Llb_NonlinFree( p ); - // reorder variables - if ( fReorder ) - Llb_NonlinReorder( dd, 0, fVerbose ); - timeOther += Abc_Clock() - clk - timeInside; - // return - Cudd_Deref( bFunc ); - return bFunc; -} - - - -static Llb_Mgr_t * p = NULL; - -/**Function************************************************************* - - Synopsis [Starts image computation manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdManager * Llb_NonlinImageStart( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, int * pOrder, int fFirst, abctime TimeTarget ) -{ - DdManager * dd; - abctime clk = Abc_Clock(); - assert( p == NULL ); - // start a new manager (disable reordering) - dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - dd->TimeStop = TimeTarget; - Cudd_ShuffleHeap( dd, pOrder ); -// if ( fFirst ) - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - // start the manager - p = Llb_NonlinAlloc( pAig, vLeaves, vRoots, pVars2Q, dd ); - if ( !Llb_NonlinStart( p ) ) - { - Llb_NonlinFree( p ); - p = NULL; - return NULL; - } - timeBuild += Abc_Clock() - clk; -// if ( !fFirst ) -// Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - return dd; -} - -/**Function************************************************************* - - Synopsis [Performs image computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_NonlinImageCompute( DdNode * bCurrent, int fReorder, int fDrop, int fVerbose, int * pOrder ) -{ - Llb_Prt_t * pPart, * pPart1, * pPart2; - DdNode * bFunc, * bTemp; - int i, nReorders, timeInside = 0; - abctime clk = Abc_Clock(), clk2; - - // add partition - Llb_NonlinAddPartition( p, p->iPartFree++, bCurrent ); - // remove singles - Llb_MgrForEachPart( p, pPart, i ) - if ( Llb_NonlinHasSingletonVars(p, pPart) ) - Llb_NonlinQuantify1( p, pPart, 0 ); - // reorder - if ( fReorder ) - Llb_NonlinReorder( p->dd, 0, 0 ); - // save permutation - memcpy( pOrder, p->dd->invperm, sizeof(int) * p->dd->size ); - - // compute scores - Llb_NonlinRecomputeScores( p ); - // iteratively quantify variables - while ( Llb_NonlinNextPartitions(p, &pPart1, &pPart2) ) - { - clk2 = Abc_Clock(); - nReorders = Cudd_ReadReorderings(p->dd); - if ( !Llb_NonlinQuantify2( p, pPart1, pPart2 ) ) - { - Llb_NonlinFree( p ); - return NULL; - } - timeAndEx += Abc_Clock() - clk2; - timeInside += Abc_Clock() - clk2; - if ( nReorders < Cudd_ReadReorderings(p->dd) ) - Llb_NonlinRecomputeScores( p ); -// else -// Llb_NonlinVerifyScores( p ); - } - // load partitions - bFunc = Cudd_ReadOne(p->dd); Cudd_Ref( bFunc ); - Llb_MgrForEachPart( p, pPart, i ) - { - bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc ); - if ( bFunc == NULL ) - { - Cudd_RecursiveDeref( p->dd, bTemp ); - Llb_NonlinFree( p ); - return NULL; - } - Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - nSuppMax = p->nSuppMax; - // reorder variables -// if ( fReorder ) -// Llb_NonlinReorder( p->dd, 0, fVerbose ); - // save permutation -// memcpy( pOrder, p->dd->invperm, sizeof(int) * Cudd_ReadSize(p->dd) ); - - timeOther += Abc_Clock() - clk - timeInside; - // return - Cudd_Deref( bFunc ); - return bFunc; -} - -/**Function************************************************************* - - Synopsis [Quits image computation manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinImageQuit() -{ - DdManager * dd; - if ( p == NULL ) - return; - dd = p->dd; - Llb_NonlinFree( p ); - if ( dd->bFunc ) - Cudd_RecursiveDeref( dd, dd->bFunc ); - Extra_StopManager( dd ); -// Cudd_Quit ( dd ); - p = NULL; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/llb/llb3Nonlin.c b/src/proof/llb/llb3Nonlin.c deleted file mode 100644 index 94a48bbf..00000000 --- a/src/proof/llb/llb3Nonlin.c +++ /dev/null @@ -1,872 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb2Nonlin.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Non-linear quantification scheduling.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb2Nonlin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Llb_Mnn_t_ Llb_Mnn_t; -struct Llb_Mnn_t_ -{ - Aig_Man_t * pInit; // AIG manager - Aig_Man_t * pAig; // AIG manager - Gia_ParLlb_t * pPars; // parameters - - DdManager * dd; // BDD manager - DdManager * ddG; // BDD manager - DdManager * ddR; // BDD manager - Vec_Ptr_t * vRings; // onion rings in ddR - - Vec_Ptr_t * vLeaves; - Vec_Ptr_t * vRoots; - int * pVars2Q; - int * pOrderL; - int * pOrderL2; - int * pOrderG; - - Vec_Int_t * vCs2Glo; // cur state variables into global variables - Vec_Int_t * vNs2Glo; // next state variables into global variables - Vec_Int_t * vGlo2Cs; // global variables into cur state variables - Vec_Int_t * vGlo2Ns; // global variables into next state variables - - int ddLocReos; - int ddLocGrbs; - - abctime timeImage; - abctime timeTran1; - abctime timeTran2; - abctime timeGloba; - abctime timeOther; - abctime timeTotal; - abctime timeReo; - abctime timeReoG; - -}; - -extern abctime timeBuild, timeAndEx, timeOther; -extern int nSuppMax; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Finds variable whose 0-cofactor is the smallest.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_NonlinFindBestVar( DdManager * dd, DdNode * bFunc, Aig_Man_t * pAig ) -{ - int fVerbose = 0; - Aig_Obj_t * pObj; - DdNode * bCof, * bVar; - int i, iVar, iVarBest = -1, iValue, iValueBest = ABC_INFINITY, Size0Best = -1; - int Size, Size0, Size1; - abctime clk = Abc_Clock(); - Size = Cudd_DagSize(bFunc); -// printf( "Original = %6d. SuppSize = %3d. Vars = %3d.\n", -// Size = Cudd_DagSize(bFunc), Cudd_SupportSize(dd, bFunc), Aig_ManRegNum(pAig) ); - Saig_ManForEachLo( pAig, pObj, i ) - { - iVar = Aig_ObjId(pObj); - -if ( fVerbose ) -printf( "Var =%3d : ", iVar ); - bVar = Cudd_bddIthVar(dd, iVar); - - bCof = Cudd_bddAnd( dd, bFunc, Cudd_Not(bVar) ); Cudd_Ref( bCof ); - Size0 = Cudd_DagSize(bCof); -if ( fVerbose ) -printf( "Supp0 =%3d ", Cudd_SupportSize(dd, bCof) ); -if ( fVerbose ) -printf( "Size0 =%6d ", Size0 ); - Cudd_RecursiveDeref( dd, bCof ); - - bCof = Cudd_bddAnd( dd, bFunc, bVar ); Cudd_Ref( bCof ); - Size1 = Cudd_DagSize(bCof); -if ( fVerbose ) -printf( "Supp1 =%3d ", Cudd_SupportSize(dd, bCof) ); -if ( fVerbose ) -printf( "Size1 =%6d ", Size1 ); - Cudd_RecursiveDeref( dd, bCof ); - - iValue = Abc_MaxInt(Size0, Size1) - Abc_MinInt(Size0, Size1) + Size0 + Size1 - Size; -if ( fVerbose ) -printf( "D =%6d ", Size0 + Size1 - Size ); -if ( fVerbose ) -printf( "B =%6d ", Abc_MaxInt(Size0, Size1) - Abc_MinInt(Size0, Size1) ); -if ( fVerbose ) -printf( "S =%6d\n", iValue ); - if ( Size0 > 1 && Size1 > 1 && iValueBest > iValue ) - { - iValueBest = iValue; - iVarBest = i; - Size0Best = Size0; - } - } - printf( "BestVar = %4d/%4d. Value =%6d. Orig =%6d. Size0 =%6d. ", - iVarBest, Aig_ObjId(Saig_ManLo(pAig,iVarBest)), iValueBest, Size, Size0Best ); - Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); - return iVarBest; -} - - -/**Function************************************************************* - - Synopsis [Finds variable whose 0-cofactor is the smallest.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinTrySubsetting( DdManager * dd, DdNode * bFunc ) -{ - DdNode * bNew; - printf( "Original = %6d. SuppSize = %3d. ", - Cudd_DagSize(bFunc), Cudd_SupportSize(dd, bFunc) ); - bNew = Cudd_SubsetHeavyBranch( dd, bFunc, Cudd_SupportSize(dd, bFunc), 1000 ); Cudd_Ref( bNew ); - printf( "Result = %6d. SuppSize = %3d.\n", - Cudd_DagSize(bNew), Cudd_SupportSize(dd, bNew) ); - Cudd_RecursiveDeref( dd, bNew ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinPrepareVarMap( Llb_Mnn_t * p ) -{ - Aig_Obj_t * pObjLi, * pObjLo, * pObj; - int i, iVarLi, iVarLo; - p->vCs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) ); - p->vNs2Glo = Vec_IntStartFull( Aig_ManObjNumMax(p->pAig) ); - p->vGlo2Cs = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); - p->vGlo2Ns = Vec_IntStartFull( Aig_ManRegNum(p->pAig) ); - Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) - { - iVarLi = Aig_ObjId(pObjLi); - iVarLo = Aig_ObjId(pObjLo); - assert( iVarLi >= 0 && iVarLi < Aig_ManObjNumMax(p->pAig) ); - assert( iVarLo >= 0 && iVarLo < Aig_ManObjNumMax(p->pAig) ); - Vec_IntWriteEntry( p->vCs2Glo, iVarLo, i ); - Vec_IntWriteEntry( p->vNs2Glo, iVarLi, i ); - Vec_IntWriteEntry( p->vGlo2Cs, i, iVarLo ); - Vec_IntWriteEntry( p->vGlo2Ns, i, iVarLi ); - } - // add mapping of the PIs - Saig_ManForEachPi( p->pAig, pObj, i ) - { - Vec_IntWriteEntry( p->vCs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i ); - Vec_IntWriteEntry( p->vNs2Glo, Aig_ObjId(pObj), Aig_ManRegNum(p->pAig)+i ); - } -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_NonlinComputeInitState( Aig_Man_t * pAig, DdManager * dd ) -{ - Aig_Obj_t * pObj; - DdNode * bRes, * bVar, * bTemp; - int i, iVar; - abctime TimeStop; - TimeStop = dd->TimeStop; dd->TimeStop = 0; - bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); - Saig_ManForEachLo( pAig, pObj, i ) - { - iVar = (Cudd_ReadSize(dd) == Aig_ManRegNum(pAig)) ? i : Aig_ObjId(pObj); - bVar = Cudd_bddIthVar( dd, iVar ); - bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bRes ); - dd->TimeStop = TimeStop; - return bRes; -} - - -/**Function************************************************************* - - Synopsis [Derives counter-example by backward reachability.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Cex_t * Llb_NonlinDeriveCex( Llb_Mnn_t * p ) -{ - Abc_Cex_t * pCex; - Aig_Obj_t * pObj; - Vec_Int_t * vVarsNs; - DdNode * bState = NULL, * bImage, * bOneCube, * bTemp, * bRing; - int i, v, RetValue, nPiOffset; - char * pValues = ABC_ALLOC( char, Cudd_ReadSize(p->ddR) ); - assert( Vec_PtrSize(p->vRings) > 0 ); - - p->dd->TimeStop = 0; - p->ddR->TimeStop = 0; - - // update quantifiable vars - memset( p->pVars2Q, 0, sizeof(int) * Cudd_ReadSize(p->dd) ); - vVarsNs = Vec_IntAlloc( Aig_ManRegNum(p->pAig) ); - Saig_ManForEachLi( p->pAig, pObj, i ) - { - p->pVars2Q[Aig_ObjId(pObj)] = 1; - Vec_IntPush( vVarsNs, Aig_ObjId(pObj) ); - } -/* - Saig_ManForEachLo( p->pAig, pObj, i ) - printf( "%d ", pObj->Id ); - printf( "\n" ); - Saig_ManForEachLi( p->pAig, pObj, i ) - printf( "%d(%d) ", pObj->Id, Aig_ObjFaninId0(pObj) ); - printf( "\n" ); -*/ - // allocate room for the counter-example - pCex = Abc_CexAlloc( Saig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Vec_PtrSize(p->vRings) ); - pCex->iFrame = Vec_PtrSize(p->vRings) - 1; - pCex->iPo = -1; - - // get the last cube - bOneCube = Cudd_bddIntersect( p->ddR, (DdNode *)Vec_PtrEntryLast(p->vRings), p->ddR->bFunc ); Cudd_Ref( bOneCube ); - RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); - Cudd_RecursiveDeref( p->ddR, bOneCube ); - assert( RetValue ); - - // write PIs of counter-example - nPiOffset = Saig_ManRegNum(p->pAig) + Saig_ManPiNum(p->pAig) * (Vec_PtrSize(p->vRings) - 1); - Saig_ManForEachPi( p->pAig, pObj, i ) - if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) - Abc_InfoSetBit( pCex->pData, nPiOffset + i ); - - // write state in terms of NS variables - if ( Vec_PtrSize(p->vRings) > 1 ) - { - bState = Llb_CoreComputeCube( p->dd, vVarsNs, 1, pValues ); Cudd_Ref( bState ); - } - // perform backward analysis - Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v ) - { - if ( v == Vec_PtrSize(p->vRings) - 1 ) - continue; -//Extra_bddPrintSupport( p->dd, bState ); printf( "\n" ); -//Extra_bddPrintSupport( p->dd, bRing ); printf( "\n" ); - // compute the next states - bImage = Llb_NonlinImage( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->dd, bState, - p->pPars->fReorder, p->pPars->fVeryVerbose, NULL ); // consumed reference - assert( bImage != NULL ); - Cudd_Ref( bImage ); -//Extra_bddPrintSupport( p->dd, bImage ); printf( "\n" ); - - // move reached states into ring manager - bImage = Extra_TransferPermute( p->dd, p->ddR, bTemp = bImage, Vec_IntArray(p->vCs2Glo) ); Cudd_Ref( bImage ); - Cudd_RecursiveDeref( p->dd, bTemp ); - - // intersect with the previous set - bOneCube = Cudd_bddIntersect( p->ddR, bImage, bRing ); Cudd_Ref( bOneCube ); - Cudd_RecursiveDeref( p->ddR, bImage ); - - // find any assignment of the BDD - RetValue = Cudd_bddPickOneCube( p->ddR, bOneCube, pValues ); - Cudd_RecursiveDeref( p->ddR, bOneCube ); - assert( RetValue ); - - // write PIs of counter-example - nPiOffset -= Saig_ManPiNum(p->pAig); - Saig_ManForEachPi( p->pAig, pObj, i ) - if ( pValues[Saig_ManRegNum(p->pAig)+i] == 1 ) - Abc_InfoSetBit( pCex->pData, nPiOffset + i ); - - // check that we get the init state - if ( v == 0 ) - { - Saig_ManForEachLo( p->pAig, pObj, i ) - assert( pValues[i] == 0 ); - break; - } - - // write state in terms of NS variables - bState = Llb_CoreComputeCube( p->dd, vVarsNs, 1, pValues ); Cudd_Ref( bState ); - } - assert( nPiOffset == Saig_ManRegNum(p->pAig) ); - // update the output number -//Abc_CexPrint( pCex ); - RetValue = Saig_ManFindFailedPoCex( p->pInit, pCex ); - assert( RetValue >= 0 && RetValue < Saig_ManPoNum(p->pInit) ); // invalid CEX!!! - pCex->iPo = RetValue; - // cleanup - ABC_FREE( pValues ); - Vec_IntFree( vVarsNs ); - return pCex; -} - - -/**Function************************************************************* - - Synopsis [Perform reachability with hints.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_NonlinReoHook( DdManager * dd, char * Type, void * Method ) -{ - Aig_Man_t * pAig = (Aig_Man_t *)dd->bFunc; - Aig_Obj_t * pObj; - int i; - printf( "Order: " ); - for ( i = 0; i < Cudd_ReadSize(dd); i++ ) - { - pObj = Aig_ManObj( pAig, i ); - if ( pObj == NULL ) - continue; - if ( Saig_ObjIsPi(pAig, pObj) ) - printf( "pi" ); - else if ( Saig_ObjIsLo(pAig, pObj) ) - printf( "lo" ); - else if ( Saig_ObjIsPo(pAig, pObj) ) - printf( "po" ); - else if ( Saig_ObjIsLi(pAig, pObj) ) - printf( "li" ); - else continue; - printf( "%d=%d ", i, dd->perm[i] ); - } - printf( "\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Perform reachability with hints.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_NonlinCompPerms( DdManager * dd, int * pVar2Lev ) -{ - DdSubtable * pSubt; - int i, Sum = 0, Entry; - for ( i = 0; i < dd->size; i++ ) - { - pSubt = &(dd->subtables[dd->perm[i]]); - if ( pSubt->keys == pSubt->dead + 1 ) - continue; - Entry = Abc_MaxInt(dd->perm[i], pVar2Lev[i]) - Abc_MinInt(dd->perm[i], pVar2Lev[i]); - Sum += Entry; -//printf( "%d-%d(%d) ", dd->perm[i], pV2L[i], Entry ); - } - return Sum; -} - -/**Function************************************************************* - - Synopsis [Perform reachability with hints.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_NonlinReachability( Llb_Mnn_t * p ) -{ - DdNode * bTemp, * bNext; - int nIters, nBddSize0, nBddSize = -1, NumCmp;//, Limit = p->pPars->nBddMax; - abctime clk2, clk3, clk = Abc_Clock(); - assert( Aig_ManRegNum(p->pAig) > 0 ); - - // compute time to stop - p->pPars->TimeTarget = p->pPars->TimeLimit ? p->pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0; - - // set the stop time parameter - p->dd->TimeStop = p->pPars->TimeTarget; - p->ddG->TimeStop = p->pPars->TimeTarget; - p->ddR->TimeStop = p->pPars->TimeTarget; - - // set reordering hooks - assert( p->dd->bFunc == NULL ); -// p->dd->bFunc = (DdNode *)p->pAig; -// Cudd_AddHook( p->dd, Llb_NonlinReoHook, CUDD_POST_REORDERING_HOOK ); - - // create bad state in the ring manager - p->ddR->bFunc = Llb_BddComputeBad( p->pInit, p->ddR, p->pPars->TimeTarget ); - if ( p->ddR->bFunc == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = -1; - return -1; - } - Cudd_Ref( p->ddR->bFunc ); - // compute the starting set of states - Cudd_Quit( p->dd ); - p->dd = Llb_NonlinImageStart( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->pOrderL, 1, p->pPars->TimeTarget ); - if ( p->dd == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = -1; - return -1; - } - p->dd->bFunc = Llb_NonlinComputeInitState( p->pAig, p->dd ); Cudd_Ref( p->dd->bFunc ); // current - p->ddG->bFunc = Llb_NonlinComputeInitState( p->pAig, p->ddG ); Cudd_Ref( p->ddG->bFunc ); // reached - p->ddG->bFunc2 = Llb_NonlinComputeInitState( p->pAig, p->ddG ); Cudd_Ref( p->ddG->bFunc2 ); // frontier - for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ ) - { - // check the runtime limit - clk2 = Abc_Clock(); - if ( p->pPars->TimeLimit && Abc_Clock() > p->pPars->TimeTarget ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Llb_NonlinImageQuit(); - return -1; - } - - // save the onion ring - bTemp = Extra_TransferPermute( p->dd, p->ddR, p->dd->bFunc, Vec_IntArray(p->vCs2Glo) ); - if ( bTemp == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during ring transfer.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Llb_NonlinImageQuit(); - return -1; - } - Cudd_Ref( bTemp ); - Vec_PtrPush( p->vRings, bTemp ); - - // check it for bad states - if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->ddR, bTemp, Cudd_Not(p->ddR->bFunc) ) ) - { - assert( p->pInit->pSeqModel == NULL ); - if ( !p->pPars->fBackward ) - p->pInit->pSeqModel = Llb_NonlinDeriveCex( p ); - if ( !p->pPars->fSilent ) - { - if ( !p->pPars->fBackward ) - Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", p->pInit->pSeqModel->iPo, nIters ); - else - Abc_Print( 1, "Output ??? was asserted in frame %d (counter-example is not produced). ", nIters ); - Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); - } - p->pPars->iFrame = nIters - 1; - Llb_NonlinImageQuit(); - return 0; - } - - // compute the next states - clk3 = Abc_Clock(); - nBddSize0 = Cudd_DagSize( p->dd->bFunc ); - bNext = Llb_NonlinImageCompute( p->dd->bFunc, p->pPars->fReorder, 0, 1, p->pOrderL ); // consumes ref -// bNext = Llb_NonlinImage( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->dd, bCurrent, -// p->pPars->fReorder, p->pPars->fVeryVerbose, NULL, ABC_INFINITY, p->pPars->TimeTarget ); - if ( bNext == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation in quantification.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Llb_NonlinImageQuit(); - return -1; - } - Cudd_Ref( bNext ); - nBddSize = Cudd_DagSize( bNext ); - p->timeImage += Abc_Clock() - clk3; - - - // transfer to the state manager - clk3 = Abc_Clock(); - Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc2 ); - p->ddG->bFunc2 = Extra_TransferPermute( p->dd, p->ddG, bNext, Vec_IntArray(p->vNs2Glo) ); -// p->ddG->bFunc2 = Extra_bddAndPermute( p->ddG, Cudd_Not(p->ddG->bFunc), p->dd, bNext, Vec_IntArray(p->vNs2Glo) ); - if ( p->ddG->bFunc2 == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->dd, bNext ); - Llb_NonlinImageQuit(); - return -1; - } - Cudd_Ref( p->ddG->bFunc2 ); - Cudd_RecursiveDeref( p->dd, bNext ); - p->timeTran1 += Abc_Clock() - clk3; - - // save permutation - NumCmp = Llb_NonlinCompPerms( p->dd, p->pOrderL2 ); - // save order before image computation - memcpy( p->pOrderL2, p->dd->perm, sizeof(int) * p->dd->size ); - // update the image computation manager - p->timeReo += Cudd_ReadReorderingTime(p->dd); - p->ddLocReos += Cudd_ReadReorderings(p->dd); - p->ddLocGrbs += Cudd_ReadGarbageCollections(p->dd); - Llb_NonlinImageQuit(); - p->dd = Llb_NonlinImageStart( p->pAig, p->vLeaves, p->vRoots, p->pVars2Q, p->pOrderL, 0, p->pPars->TimeTarget ); - if ( p->dd == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - return -1; - } - //Extra_TestAndPerm( p->ddG, Cudd_Not(p->ddG->bFunc), p->ddG->bFunc2 ); - - // derive new states - clk3 = Abc_Clock(); - p->ddG->bFunc2 = Cudd_bddAnd( p->ddG, bTemp = p->ddG->bFunc2, Cudd_Not(p->ddG->bFunc) ); - if ( p->ddG->bFunc2 == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->ddG, bTemp ); - Llb_NonlinImageQuit(); - return -1; - } - Cudd_Ref( p->ddG->bFunc2 ); - Cudd_RecursiveDeref( p->ddG, bTemp ); - p->timeGloba += Abc_Clock() - clk3; - - if ( Cudd_IsConstant(p->ddG->bFunc2) ) - break; - // add to the reached set - clk3 = Abc_Clock(); - p->ddG->bFunc = Cudd_bddOr( p->ddG, bTemp = p->ddG->bFunc, p->ddG->bFunc2 ); - if ( p->ddG->bFunc == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->ddG, bTemp ); - Llb_NonlinImageQuit(); - return -1; - } - Cudd_Ref( p->ddG->bFunc ); - Cudd_RecursiveDeref( p->ddG, bTemp ); - p->timeGloba += Abc_Clock() - clk3; - - // reset permutation -// RetValue = Cudd_CheckZeroRef( dd ); -// assert( RetValue == 0 ); -// Cudd_ShuffleHeap( dd, pOrderG ); - - // move new states to the working manager - clk3 = Abc_Clock(); - p->dd->bFunc = Extra_TransferPermute( p->ddG, p->dd, p->ddG->bFunc2, Vec_IntArray(p->vGlo2Cs) ); - if ( p->dd->bFunc == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation in transfer 2.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Llb_NonlinImageQuit(); - return -1; - } - Cudd_Ref( p->dd->bFunc ); - p->timeTran2 += Abc_Clock() - clk3; - - // report the results - if ( p->pPars->fVerbose ) - { - printf( "I =%3d : ", nIters ); - printf( "Fr =%7d ", nBddSize0 ); - printf( "Im =%7d ", nBddSize ); - printf( "(%4d %4d) ", p->ddLocReos, p->ddLocGrbs ); - printf( "Rea =%6d ", Cudd_DagSize(p->ddG->bFunc) ); - printf( "(%4d %4d) ", Cudd_ReadReorderings(p->ddG), Cudd_ReadGarbageCollections(p->ddG) ); - printf( "S =%4d ", nSuppMax ); - printf( "cL =%5d ", NumCmp ); - printf( "cG =%5d ", Llb_NonlinCompPerms( p->ddG, p->pOrderG ) ); - Abc_PrintTime( 1, "T", Abc_Clock() - clk2 ); - memcpy( p->pOrderG, p->ddG->perm, sizeof(int) * p->ddG->size ); - } -/* - if ( pPars->fVerbose ) - { - double nMints = Cudd_CountMinterm(ddG, bReached, Saig_ManRegNum(pAig) ); -// Extra_bddPrint( ddG, bReached );printf( "\n" ); - printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(pAig)) ); - fflush( stdout ); - } -*/ - if ( nIters == p->pPars->nIterMax - 1 ) - { - if ( !p->pPars->fSilent ) - printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nIterMax ); - p->pPars->iFrame = nIters; - Llb_NonlinImageQuit(); - return -1; - } - } - Llb_NonlinImageQuit(); - - // report the stats - if ( p->pPars->fVerbose ) - { - double nMints = Cudd_CountMinterm(p->ddG, p->ddG->bFunc, Saig_ManRegNum(p->pAig) ); - if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) - printf( "Reachability analysis is stopped after %d frames.\n", nIters ); - else - printf( "Reachability analysis completed after %d frames.\n", nIters ); - printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); - fflush( stdout ); - } - if ( nIters >= p->pPars->nIterMax || nBddSize > p->pPars->nBddMax ) - { - if ( !p->pPars->fSilent ) - printf( "Verified only for states reachable in %d frames. ", nIters ); - p->pPars->iFrame = p->pPars->nIterMax; - return -1; // undecided - } - // report - if ( !p->pPars->fSilent ) - printf( "The miter is proved unreachable after %d iterations. ", nIters ); - p->pPars->iFrame = nIters - 1; - Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); - return 1; // unreachable -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Mnn_t * Llb_MnnStart( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) -{ - Llb_Mnn_t * p; - Aig_Obj_t * pObj; - int i; - p = ABC_CALLOC( Llb_Mnn_t, 1 ); - p->pInit = pInit; - p->pAig = pAig; - p->pPars = pPars; - p->dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - p->ddG = Cudd_Init( Aig_ManRegNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - p->ddR = Cudd_Init( Aig_ManCiNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); - Cudd_AutodynEnable( p->ddG, CUDD_REORDER_SYMM_SIFT ); - Cudd_AutodynEnable( p->ddR, CUDD_REORDER_SYMM_SIFT ); - p->vRings = Vec_PtrAlloc( 100 ); - // create leaves - p->vLeaves = Vec_PtrAlloc( Aig_ManCiNum(pAig) ); - Aig_ManForEachCi( pAig, pObj, i ) - Vec_PtrPush( p->vLeaves, pObj ); - // create roots - p->vRoots = Vec_PtrAlloc( Aig_ManCoNum(pAig) ); - Saig_ManForEachLi( pAig, pObj, i ) - Vec_PtrPush( p->vRoots, pObj ); - // variables to quantify - p->pOrderL = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); - p->pOrderL2= ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); - p->pOrderG = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); - p->pVars2Q = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) ); - Aig_ManForEachCi( pAig, pObj, i ) - p->pVars2Q[Aig_ObjId(pObj)] = 1; - for ( i = 0; i < Aig_ManObjNumMax(pAig); i++ ) - p->pOrderL[i] = p->pOrderL2[i] = p->pOrderG[i] = i; - Llb_NonlinPrepareVarMap( p ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MnnStop( Llb_Mnn_t * p ) -{ - DdNode * bTemp; - int i; - if ( p->pPars->fVerbose ) - { - p->timeOther = p->timeTotal - p->timeImage - p->timeTran1 - p->timeTran2 - p->timeGloba; - p->timeReoG = Cudd_ReadReorderingTime(p->ddG); - ABC_PRTP( "Image ", p->timeImage, p->timeTotal ); - ABC_PRTP( " build ", timeBuild, p->timeTotal ); - ABC_PRTP( " and-ex ", timeAndEx, p->timeTotal ); - ABC_PRTP( " other ", timeOther, p->timeTotal ); - ABC_PRTP( "Transfer1", p->timeTran1, p->timeTotal ); - ABC_PRTP( "Transfer2", p->timeTran2, p->timeTotal ); - ABC_PRTP( "Global ", p->timeGloba, p->timeTotal ); - ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); - ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); - ABC_PRTP( " reo ", p->timeReo, p->timeTotal ); - ABC_PRTP( " reoG ", p->timeReoG, p->timeTotal ); - } - if ( p->ddR->bFunc ) - Cudd_RecursiveDeref( p->ddR, p->ddR->bFunc ); - Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i ) - Cudd_RecursiveDeref( p->ddR, bTemp ); - Vec_PtrFree( p->vRings ); - if ( p->ddG->bFunc ) - Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc ); - if ( p->ddG->bFunc2 ) - Cudd_RecursiveDeref( p->ddG, p->ddG->bFunc2 ); -// printf( "manager1\n" ); -// Extra_StopManager( p->dd ); -// printf( "manager2\n" ); - Extra_StopManager( p->ddG ); -// printf( "manager3\n" ); - Extra_StopManager( p->ddR ); - Vec_IntFreeP( &p->vCs2Glo ); - Vec_IntFreeP( &p->vNs2Glo ); - Vec_IntFreeP( &p->vGlo2Cs ); - Vec_IntFreeP( &p->vGlo2Ns ); - Vec_PtrFree( p->vLeaves ); - Vec_PtrFree( p->vRoots ); - ABC_FREE( p->pVars2Q ); - ABC_FREE( p->pOrderL ); - ABC_FREE( p->pOrderL2 ); - ABC_FREE( p->pOrderG ); - ABC_FREE( p ); -} - - -/**Function************************************************************* - - Synopsis [Finds balanced cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_NonlinExperiment( Aig_Man_t * pAig, int Num ) -{ - Llb_Mnn_t * pMnn; - Gia_ParLlb_t Pars, * pPars = &Pars; - Aig_Man_t * p; - abctime clk = Abc_Clock(); - - Llb_ManSetDefaultParams( pPars ); - pPars->fVerbose = 1; - - p = Aig_ManDupFlopsOnly( pAig ); -//Aig_ManShow( p, 0, NULL ); - Aig_ManPrintStats( pAig ); - Aig_ManPrintStats( p ); - - pMnn = Llb_MnnStart( pAig, p, pPars ); - Llb_NonlinReachability( pMnn ); - pMnn->timeTotal = Abc_Clock() - clk; - Llb_MnnStop( pMnn ); - - Aig_ManStop( p ); -} - -/**Function************************************************************* - - Synopsis [Finds balanced cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_NonlinCoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) -{ - Llb_Mnn_t * pMnn; - Aig_Man_t * p; - int RetValue = -1; - - p = Aig_ManDupFlopsOnly( pAig ); -//Aig_ManShow( p, 0, NULL ); - if ( pPars->fVerbose ) - Aig_ManPrintStats( pAig ); - if ( pPars->fVerbose ) - Aig_ManPrintStats( p ); - - if ( !pPars->fSkipReach ) - { - abctime clk = Abc_Clock(); - pMnn = Llb_MnnStart( pAig, p, pPars ); - RetValue = Llb_NonlinReachability( pMnn ); - pMnn->timeTotal = Abc_Clock() - clk; - Llb_MnnStop( pMnn ); - } - - Aig_ManStop( p ); - return RetValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/llb/llb4Cex.c b/src/proof/llb/llb4Cex.c deleted file mode 100644 index 18aeaf04..00000000 --- a/src/proof/llb/llb4Cex.c +++ /dev/null @@ -1,320 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb2Cex.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Non-linear quantification scheduling.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb2Cex.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" -#include "sat/cnf/cnf.h" -#include "sat/bsat/satSolver.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Translates a sequence of states into a counter-example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Cex_t * Llb4_Nonlin4TransformCex( Aig_Man_t * pAig, Vec_Ptr_t * vStates, int iCexPo, int fVerbose ) -{ - Abc_Cex_t * pCex; - Cnf_Dat_t * pCnf; - Vec_Int_t * vAssumps; - sat_solver * pSat; - Aig_Obj_t * pObj; - unsigned * pNext, * pThis; - int i, k, iBit, status, nRegs;//, clk = Abc_Clock(); -/* - Vec_PtrForEachEntry( unsigned *, vStates, pNext, i ) - { - printf( "%4d : ", i ); - Extra_PrintBinary( stdout, pNext, Aig_ManRegNum(pAig) ); - printf( "\n" ); - } -*/ - // derive SAT solver - nRegs = Aig_ManRegNum(pAig); pAig->nRegs = 0; - pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) ); - pAig->nRegs = nRegs; -// Cnf_DataTranformPolarity( pCnf, 0 ); - // convert into SAT solver - pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); - if ( pSat == NULL ) - { - printf( "Llb4_Nonlin4TransformCex(): Counter-example generation has failed.\n" ); - Cnf_DataFree( pCnf ); - return NULL; - } - // simplify the problem - status = sat_solver_simplify(pSat); - if ( status == 0 ) - { - printf( "Llb4_Nonlin4TransformCex(): SAT solver is invalid.\n" ); - sat_solver_delete( pSat ); - Cnf_DataFree( pCnf ); - return NULL; - } - // start the counter-example - pCex = Abc_CexAlloc( Saig_ManRegNum(pAig), Saig_ManPiNum(pAig), Vec_PtrSize(vStates) ); - pCex->iFrame = Vec_PtrSize(vStates)-1; - pCex->iPo = -1; - - // solve each time frame - iBit = Saig_ManRegNum(pAig); - pThis = (unsigned *)Vec_PtrEntry( vStates, 0 ); - vAssumps = Vec_IntAlloc( 2 * Aig_ManRegNum(pAig) ); - Vec_PtrForEachEntryStart( unsigned *, vStates, pNext, i, 1 ) - { - // create assumptions - Vec_IntClear( vAssumps ); - Saig_ManForEachLo( pAig, pObj, k ) - Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Abc_InfoHasBit(pThis,k) ) ); - Saig_ManForEachLi( pAig, pObj, k ) - Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Abc_InfoHasBit(pNext,k) ) ); - // solve SAT problem - status = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), - (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); - // if the problem is SAT, get the counterexample - if ( status != l_True ) - { - printf( "Llb4_Nonlin4TransformCex(): There is no transition between state %d and %d.\n", i-1, i ); - Vec_IntFree( vAssumps ); - sat_solver_delete( pSat ); - Cnf_DataFree( pCnf ); - ABC_FREE( pCex ); - return NULL; - } - // get the assignment of PIs - Saig_ManForEachPi( pAig, pObj, k ) - if ( sat_solver_var_value(pSat, pCnf->pVarNums[Aig_ObjId(pObj)]) ) - Abc_InfoSetBit( pCex->pData, iBit + k ); - // update the counter - iBit += Saig_ManPiNum(pAig); - pThis = pNext; - } - - // add the last frame when the property fails - Vec_IntClear( vAssumps ); - if ( iCexPo >= 0 ) - { - Saig_ManForEachPo( pAig, pObj, k ) - if ( k == iCexPo ) - Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 ) ); - } - else - { - Saig_ManForEachPo( pAig, pObj, k ) - Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 ) ); - } - - // add clause - status = sat_solver_addclause( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps) ); - if ( status == 0 ) - { - printf( "Llb4_Nonlin4TransformCex(): The SAT solver is unsat after adding last clause.\n" ); - Vec_IntFree( vAssumps ); - sat_solver_delete( pSat ); - Cnf_DataFree( pCnf ); - ABC_FREE( pCex ); - return NULL; - } - // create assumptions - Vec_IntClear( vAssumps ); - Saig_ManForEachLo( pAig, pObj, k ) - Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !Abc_InfoHasBit(pThis,k) ) ); - // solve the last frame - status = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), - (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); - if ( status != l_True ) - { - printf( "Llb4_Nonlin4TransformCex(): There is no last transition that makes the property fail.\n" ); - Vec_IntFree( vAssumps ); - sat_solver_delete( pSat ); - Cnf_DataFree( pCnf ); - ABC_FREE( pCex ); - return NULL; - } - // get the assignment of PIs - Saig_ManForEachPi( pAig, pObj, k ) - if ( sat_solver_var_value(pSat, pCnf->pVarNums[Aig_ObjId(pObj)]) ) - Abc_InfoSetBit( pCex->pData, iBit + k ); - iBit += Saig_ManPiNum(pAig); - assert( iBit == pCex->nBits ); - - // free the sat_solver - Vec_IntFree( vAssumps ); - sat_solver_delete( pSat ); - Cnf_DataFree( pCnf ); - - // verify counter-example - status = Saig_ManFindFailedPoCex( pAig, pCex ); - if ( status >= 0 && status < Saig_ManPoNum(pAig) ) - pCex->iPo = status; - else - { - printf( "Llb4_Nonlin4TransformCex(): Counter-example verification has FAILED.\n" ); - ABC_FREE( pCex ); - return NULL; - } - // report the results -// if ( fVerbose ) -// Abc_PrintTime( 1, "SAT-based cex generation time", Abc_Clock() - clk ); - return pCex; -} - - -/**Function************************************************************* - - Synopsis [Resimulates the counter-example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb4_Nonlin4VerifyCex( Aig_Man_t * pAig, Abc_Cex_t * p ) -{ - Vec_Ptr_t * vStates; - Aig_Obj_t * pObj, * pObjRi, * pObjRo; - int i, k, iBit = 0; - // create storage for states - vStates = Vec_PtrAllocSimInfo( p->iFrame+1, Abc_BitWordNum(Aig_ManRegNum(pAig)) ); - Vec_PtrCleanSimInfo( vStates, 0, Abc_BitWordNum(Aig_ManRegNum(pAig)) ); - // verify counter-example - Aig_ManCleanMarkB(pAig); - Aig_ManConst1(pAig)->fMarkB = 1; - Saig_ManForEachLo( pAig, pObj, i ) - pObj->fMarkB = 0; //Abc_InfoHasBit(p->pData, iBit++); - // do not require equal flop count in the AIG and in the CEX - iBit = p->nRegs; - for ( i = 0; i <= p->iFrame; i++ ) - { - // save current state - Saig_ManForEachLo( pAig, pObj, k ) - if ( pObj->fMarkB ) - Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(vStates, i), k ); - // compute new state - Saig_ManForEachPi( pAig, pObj, k ) - pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++); - Aig_ManForEachNode( pAig, pObj, k ) - pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & - (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj)); - Aig_ManForEachCo( pAig, pObj, k ) - pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj); - if ( i == p->iFrame ) - break; - Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, k ) - pObjRo->fMarkB = pObjRi->fMarkB; - } -/* - { - unsigned * pNext; - Vec_PtrForEachEntry( unsigned *, vStates, pNext, i ) - { - printf( "%4d : ", i ); - Extra_PrintBinary( stdout, pNext, Aig_ManRegNum(pAig) ); - printf( "\n" ); - } - } -*/ - assert( iBit == p->nBits ); -// if ( Aig_ManCo(pAig, p->iPo)->fMarkB == 0 ) -// Vec_PtrFreeP( &vStates ); - for ( i = Saig_ManPoNum(pAig) - 1; i >= 0; i-- ) - { - if ( Aig_ManCo(pAig, i)->fMarkB ) - { - p->iPo = i; - break; - } - } - if ( i == -1 ) - Vec_PtrFreeP( &vStates ); - Aig_ManCleanMarkB(pAig); - return vStates; -} - -/**Function************************************************************* - - Synopsis [Translates a sequence of states into a counter-example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Cex_t * Llb4_Nonlin4NormalizeCex( Aig_Man_t * pAigOrg, Aig_Man_t * pAigRpm, Abc_Cex_t * pCexRpm ) -{ - Abc_Cex_t * pCexOrg; - Vec_Ptr_t * vStates; - // check parameters of the AIG - if ( Saig_ManRegNum(pAigOrg) != Saig_ManRegNum(pAigRpm) ) - { - printf( "Llb4_Nonlin4NormalizeCex(): The number of flops in the original and reparametrized AIGs do not agree.\n" ); - return NULL; - } -/* - if ( Saig_ManRegNum(pAigRpm) != pCexRpm->nRegs ) - { - printf( "Llb4_Nonlin4NormalizeCex(): The number of flops in the reparametrized AIG and in the CEX do not agree.\n" ); - return NULL; - } -*/ - if ( Saig_ManPiNum(pAigRpm) != pCexRpm->nPis ) - { - printf( "Llb4_Nonlin4NormalizeCex(): The number of PIs in the reparametrized AIG and in the CEX do not agree.\n" ); - return NULL; - } - // get the sequence of states - vStates = Llb4_Nonlin4VerifyCex( pAigRpm, pCexRpm ); - if ( vStates == NULL ) - { - Abc_Print( 1, "Llb4_Nonlin4NormalizeCex(): The given CEX does not fail outputs of pAigRpm.\n" ); - return NULL; - } - // derive updated counter-example - pCexOrg = Llb4_Nonlin4TransformCex( pAigOrg, vStates, pCexRpm->iPo, 0 ); - Vec_PtrFree( vStates ); - return pCexOrg; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/llb/llb4Cluster.c b/src/proof/llb/llb4Cluster.c deleted file mode 100644 index 7e325597..00000000 --- a/src/proof/llb/llb4Cluster.c +++ /dev/null @@ -1,452 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb2Cluster.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Non-linear quantification scheduling.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb2Cluster.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Find good static variable ordering.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4FindOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter ) -{ - Aig_Obj_t * pFanin0, * pFanin1; - if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) - return; - Aig_ObjSetTravIdCurrent( pAig, pObj ); - assert( Llb_ObjBddVar(vOrder, pObj) < 0 ); - if ( Aig_ObjIsCi(pObj) ) - { - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); - return; - } - // try fanins with higher level first - pFanin0 = Aig_ObjFanin0(pObj); - pFanin1 = Aig_ObjFanin1(pObj); -// if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) ) - if ( pFanin0->Level > pFanin1->Level ) - { - Llb_Nonlin4FindOrder_rec( pAig, pFanin0, vOrder, pCounter ); - Llb_Nonlin4FindOrder_rec( pAig, pFanin1, vOrder, pCounter ); - } - else - { - Llb_Nonlin4FindOrder_rec( pAig, pFanin1, vOrder, pCounter ); - Llb_Nonlin4FindOrder_rec( pAig, pFanin0, vOrder, pCounter ); - } - if ( pObj->fMarkA ) - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); -} - -/**Function************************************************************* - - Synopsis [Find good static variable ordering.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_Nonlin4FindOrder( Aig_Man_t * pAig, int * pCounter ) -{ - Vec_Int_t * vNodes = NULL; - Vec_Int_t * vOrder; - Aig_Obj_t * pObj; - int i, Counter = 0; - // mark nodes to exclude: AND with low level and CO drivers - Aig_ManCleanMarkA( pAig ); - Aig_ManForEachNode( pAig, pObj, i ) - if ( Aig_ObjLevel(pObj) > 3 ) - pObj->fMarkA = 1; - Aig_ManForEachCo( pAig, pObj, i ) - Aig_ObjFanin0(pObj)->fMarkA = 0; - - // collect nodes in the order - vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) ); - Aig_ManIncrementTravId( pAig ); - Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); -// Aig_ManForEachCo( pAig, pObj, i ) - Saig_ManForEachLi( pAig, pObj, i ) - { - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); - Llb_Nonlin4FindOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter ); - } - Aig_ManForEachCi( pAig, pObj, i ) - if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); - Aig_ManCleanMarkA( pAig ); - Vec_IntFreeP( &vNodes ); -// assert( Counter == Aig_ManObjNum(pAig) - 1 ); - -/* - Saig_ManForEachPi( pAig, pObj, i ) - printf( "pi%d ", Llb_ObjBddVar(vOrder, pObj) ); - printf( "\n" ); - Saig_ManForEachLo( pAig, pObj, i ) - printf( "lo%d ", Llb_ObjBddVar(vOrder, pObj) ); - printf( "\n" ); - Saig_ManForEachPo( pAig, pObj, i ) - printf( "po%d ", Llb_ObjBddVar(vOrder, pObj) ); - printf( "\n" ); - Saig_ManForEachLi( pAig, pObj, i ) - printf( "li%d ", Llb_ObjBddVar(vOrder, pObj) ); - printf( "\n" ); - Aig_ManForEachNode( pAig, pObj, i ) - printf( "n%d ", Llb_ObjBddVar(vOrder, pObj) ); - printf( "\n" ); -*/ - if ( pCounter ) - *pCounter = Counter; - return vOrder; -} - -/**Function************************************************************* - - Synopsis [Derives BDDs for the partitions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_Nonlin4FindPartitions_rec( DdManager * dd, Aig_Obj_t * pObj, Vec_Int_t * vOrder, Vec_Ptr_t * vRoots ) -{ - DdNode * bBdd, * bBdd0, * bBdd1, * bPart, * vVar; - if ( Aig_ObjIsConst1(pObj) ) - return Cudd_ReadOne(dd); - if ( Aig_ObjIsCi(pObj) ) - return Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); - if ( pObj->pData ) - return (DdNode *)pObj->pData; - if ( Aig_ObjIsCo(pObj) ) - { - bBdd0 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) ); - bPart = Cudd_bddXnor( dd, Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ), bBdd0 ); Cudd_Ref( bPart ); - Vec_PtrPush( vRoots, bPart ); - return NULL; - } - bBdd0 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) ); - bBdd1 = Cudd_NotCond( Llb_Nonlin4FindPartitions_rec(dd, Aig_ObjFanin1(pObj), vOrder, vRoots), Aig_ObjFaninC1(pObj) ); - bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bBdd ); - if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) - { - vVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); - bPart = Cudd_bddXnor( dd, vVar, bBdd ); Cudd_Ref( bPart ); - Vec_PtrPush( vRoots, bPart ); - Cudd_RecursiveDeref( dd, bBdd ); - bBdd = vVar; Cudd_Ref( vVar ); - } - pObj->pData = bBdd; - return bBdd; -} - -/**Function************************************************************* - - Synopsis [Derives BDDs for the partitions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_Nonlin4FindPartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fOutputs ) -{ - Vec_Ptr_t * vRoots; - Aig_Obj_t * pObj; - int i; - Aig_ManCleanData( pAig ); - vRoots = Vec_PtrAlloc( 100 ); - if ( fOutputs ) - { - Saig_ManForEachPo( pAig, pObj, i ) - Llb_Nonlin4FindPartitions_rec( dd, pObj, vOrder, vRoots ); - } - else - { - Saig_ManForEachLi( pAig, pObj, i ) - Llb_Nonlin4FindPartitions_rec( dd, pObj, vOrder, vRoots ); - } - Aig_ManForEachNode( pAig, pObj, i ) - if ( pObj->pData ) - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - return vRoots; -} - -/**Function************************************************************* - - Synopsis [Creates quantifiable variables for both types of traversal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_Nonlin4FindVars2Q( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder ) -{ - Vec_Int_t * vVars2Q; - Aig_Obj_t * pObj; - int i; - vVars2Q = Vec_IntAlloc( 0 ); - Vec_IntFill( vVars2Q, Cudd_ReadSize(dd), 1 ); - Saig_ManForEachLo( pAig, pObj, i ) - Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 ); -// Aig_ManForEachCo( pAig, pObj, i ) - Saig_ManForEachLi( pAig, pObj, i ) - Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 ); - return vVars2Q; -} - -/**Function************************************************************* - - Synopsis [Creates quantifiable variables for both types of traversal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_Nonlin4CountTerms( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, DdNode * bFunc, int fCo, int fFlop ) -{ - DdNode * bSupp; - Aig_Obj_t * pObj; - int i, Counter = 0; - bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); - if ( !fCo && !fFlop ) - { - Saig_ManForEachPi( pAig, pObj, i ) - if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) - Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) ); - } - else if ( fCo && !fFlop ) - { - Saig_ManForEachPo( pAig, pObj, i ) - if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) - Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) ); - } - else if ( !fCo && fFlop ) - { - Saig_ManForEachLo( pAig, pObj, i ) - if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) - Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) ); - } - else if ( fCo && fFlop ) - { - Saig_ManForEachLi( pAig, pObj, i ) - if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) - Counter += Cudd_bddLeq( dd, bSupp, Cudd_bddIthVar(dd, Llb_ObjBddVar(vOrder, pObj)) ); - } - Cudd_RecursiveDeref( dd, bSupp ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Creates quantifiable variables for both types of traversal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4PrintGroups( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups ) -{ - DdNode * bTemp; - int i, nSuppAll, nSuppPi, nSuppPo, nSuppLi, nSuppLo, nSuppAnd; - Vec_PtrForEachEntry( DdNode *, vGroups, bTemp, i ) - { -//Extra_bddPrintSupport(dd, bTemp); printf("\n" ); - nSuppAll = Cudd_SupportSize(dd,bTemp); - nSuppPi = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 0, 0); - nSuppPo = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 1, 0); - nSuppLi = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 0, 1); - nSuppLo = Llb_Nonlin4CountTerms(dd, pAig, vOrder, bTemp, 1, 1); - nSuppAnd = nSuppAll - (nSuppPi+nSuppPo+nSuppLi+nSuppLo); - - if ( Cudd_DagSize(bTemp) <= 10 ) - continue; - - printf( "%4d : bdd =%6d supp =%3d ", i, Cudd_DagSize(bTemp), nSuppAll ); - printf( "pi =%3d ", nSuppPi ); - printf( "po =%3d ", nSuppPo ); - printf( "lo =%3d ", nSuppLo ); - printf( "li =%3d ", nSuppLi ); - printf( "and =%3d", nSuppAnd ); - printf( "\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Creates quantifiable variables for both types of traversal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4PrintSuppProfile( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups ) -{ - Aig_Obj_t * pObj; - int i, * pSupp; - int nSuppAll = 0, nSuppPi = 0, nSuppPo = 0, nSuppLi = 0, nSuppLo = 0, nSuppAnd = 0; - - pSupp = ABC_CALLOC( int, Cudd_ReadSize(dd) ); - Extra_VectorSupportArray( dd, (DdNode **)Vec_PtrArray(vGroups), Vec_PtrSize(vGroups), pSupp ); - - Aig_ManForEachObj( pAig, pObj, i ) - { - if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) - continue; - // remove variables that do not participate - if ( pSupp[Llb_ObjBddVar(vOrder, pObj)] == 0 ) - { - if ( Aig_ObjIsNode(pObj) ) - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), -1 ); - continue; - } - nSuppAll++; - if ( Saig_ObjIsPi(pAig, pObj) ) - nSuppPi++; - else if ( Saig_ObjIsLo(pAig, pObj) ) - nSuppLo++; - else if ( Saig_ObjIsPo(pAig, pObj) ) - nSuppPo++; - else if ( Saig_ObjIsLi(pAig, pObj) ) - nSuppLi++; - else - nSuppAnd++; - } - ABC_FREE( pSupp ); - - printf( "Groups =%3d ", Vec_PtrSize(vGroups) ); - printf( "Variables: all =%4d ", nSuppAll ); - printf( "pi =%4d ", nSuppPi ); - printf( "po =%4d ", nSuppPo ); - printf( "lo =%4d ", nSuppLo ); - printf( "li =%4d ", nSuppLi ); - printf( "and =%4d", nSuppAnd ); - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4Cluster( Aig_Man_t * pAig, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int nBddMax, int fVerbose ) -{ - DdManager * dd; - Vec_Int_t * vOrder, * vVars2Q; - Vec_Ptr_t * vParts, * vGroups; - DdNode * bTemp; - int i, nVarNum; - - // create the BDD manager - vOrder = Llb_Nonlin4FindOrder( pAig, &nVarNum ); - dd = Cudd_Init( nVarNum, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); -// Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - - vVars2Q = Llb_Nonlin4FindVars2Q( dd, pAig, vOrder ); - vParts = Llb_Nonlin4FindPartitions( dd, pAig, vOrder, 0 ); - - vGroups = Llb_Nonlin4Group( dd, vParts, vVars2Q, nBddMax ); - Vec_IntFree( vVars2Q ); - - Vec_PtrForEachEntry( DdNode *, vParts, bTemp, i ) - Cudd_RecursiveDeref( dd, bTemp ); - Vec_PtrFree( vParts ); - - -// if ( fVerbose ) - Llb_Nonlin4PrintSuppProfile( dd, pAig, vOrder, vGroups ); - if ( fVerbose ) - printf( "Before reordering\n" ); - if ( fVerbose ) - Llb_Nonlin4PrintGroups( dd, pAig, vOrder, vGroups ); - -// Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); -// printf( "After reordering\n" ); -// Llb_Nonlin4PrintGroups( dd, pAig, vOrder, vGroups ); - - if ( pvOrder ) - *pvOrder = vOrder; - else - Vec_IntFree( vOrder ); - - if ( pvGroups ) - *pvGroups = vGroups; - else - { - Vec_PtrForEachEntry( DdNode *, vGroups, bTemp, i ) - Cudd_RecursiveDeref( dd, bTemp ); - Vec_PtrFree( vGroups ); - } - - if ( pdd ) - *pdd = dd; - else - Extra_StopManager( dd ); -// Cudd_Quit( dd ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/llb/llb4Image.c b/src/proof/llb/llb4Image.c deleted file mode 100644 index 2ba4fcfd..00000000 --- a/src/proof/llb/llb4Image.c +++ /dev/null @@ -1,863 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb3Image.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Computes image using partitioned structure.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb3Image.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Llb_Var_t_ Llb_Var_t; -struct Llb_Var_t_ -{ - int iVar; // variable number - int nScore; // variable score - Vec_Int_t * vParts; // partitions -}; - -typedef struct Llb_Prt_t_ Llb_Prt_t; -struct Llb_Prt_t_ -{ - int iPart; // partition number - int nSize; // the number of BDD nodes - DdNode * bFunc; // the partition - Vec_Int_t * vVars; // support -}; - -typedef struct Llb_Mgr_t_ Llb_Mgr_t; -struct Llb_Mgr_t_ -{ - DdManager * dd; // working BDD manager - Vec_Int_t * vVars2Q; // variables to quantify - int nSizeMax; // maximum size of the cluster - // internal - Llb_Prt_t ** pParts; // partitions - Llb_Var_t ** pVars; // variables - int iPartFree; // next free partition - int nVars; // the number of BDD variables - int nSuppMax; // maximum support size - // temporary - int * pSupp; // temporary support storage -}; - -static inline Llb_Var_t * Llb_MgrVar( Llb_Mgr_t * p, int i ) { return p->pVars[i]; } -static inline Llb_Prt_t * Llb_MgrPart( Llb_Mgr_t * p, int i ) { return p->pParts[i]; } - -// iterator over vars -#define Llb_MgrForEachVar( p, pVar, i ) \ - for ( i = 0; (i < p->nVars) && (((pVar) = Llb_MgrVar(p, i)), 1); i++ ) if ( pVar == NULL ) {} else -// iterator over parts -#define Llb_MgrForEachPart( p, pPart, i ) \ - for ( i = 0; (i < p->iPartFree) && (((pPart) = Llb_MgrPart(p, i)), 1); i++ ) if ( pPart == NULL ) {} else - -// iterator over vars of one partition -#define Llb_PartForEachVar( p, pPart, pVar, i ) \ - for ( i = 0; (i < Vec_IntSize(pPart->vVars)) && (((pVar) = Llb_MgrVar(p, Vec_IntEntry(pPart->vVars,i))), 1); i++ ) -// iterator over parts of one variable -#define Llb_VarForEachPart( p, pVar, pPart, i ) \ - for ( i = 0; (i < Vec_IntSize(pVar->vParts)) && (((pPart) = Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,i))), 1); i++ ) - -// statistics -//abctime timeBuild, timeAndEx, timeOther; -//int nSuppMax; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Removes one variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4RemoveVar( Llb_Mgr_t * p, Llb_Var_t * pVar ) -{ - assert( p->pVars[pVar->iVar] == pVar ); - p->pVars[pVar->iVar] = NULL; - Vec_IntFree( pVar->vParts ); - ABC_FREE( pVar ); -} - -/**Function************************************************************* - - Synopsis [Removes one partition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4RemovePart( Llb_Mgr_t * p, Llb_Prt_t * pPart ) -{ -//printf( "Removing %d\n", pPart->iPart ); - assert( p->pParts[pPart->iPart] == pPart ); - p->pParts[pPart->iPart] = NULL; - Vec_IntFree( pPart->vVars ); - Cudd_RecursiveDeref( p->dd, pPart->bFunc ); - ABC_FREE( pPart ); -} - -/**Function************************************************************* - - Synopsis [Create cube with singleton variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_Nonlin4CreateCube1( Llb_Mgr_t * p, Llb_Prt_t * pPart ) -{ - DdNode * bCube, * bTemp; - Llb_Var_t * pVar; - int i; - abctime TimeStop; - TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; - bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube ); - Llb_PartForEachVar( p, pPart, pVar, i ) - { - assert( Vec_IntSize(pVar->vParts) > 0 ); - if ( Vec_IntSize(pVar->vParts) != 1 ) - continue; - assert( Vec_IntEntry(pVar->vParts, 0) == pPart->iPart ); - bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - Cudd_Deref( bCube ); - p->dd->TimeStop = TimeStop; - return bCube; -} - -/**Function************************************************************* - - Synopsis [Create cube of variables appearing only in two partitions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_Nonlin4CreateCube2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 ) -{ - DdNode * bCube, * bTemp; - Llb_Var_t * pVar; - int i; - abctime TimeStop; - TimeStop = p->dd->TimeStop; p->dd->TimeStop = 0; - bCube = Cudd_ReadOne(p->dd); Cudd_Ref( bCube ); - Llb_PartForEachVar( p, pPart1, pVar, i ) - { - assert( Vec_IntSize(pVar->vParts) > 0 ); - if ( Vec_IntSize(pVar->vParts) != 2 ) - continue; - if ( (Vec_IntEntry(pVar->vParts, 0) == pPart1->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart2->iPart) || - (Vec_IntEntry(pVar->vParts, 0) == pPart2->iPart && Vec_IntEntry(pVar->vParts, 1) == pPart1->iPart) ) - { - bCube = Cudd_bddAnd( p->dd, bTemp = bCube, Cudd_bddIthVar(p->dd, pVar->iVar) ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - } - Cudd_Deref( bCube ); - p->dd->TimeStop = TimeStop; - return bCube; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if partition has singleton variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_Nonlin4HasSingletonVars( Llb_Mgr_t * p, Llb_Prt_t * pPart ) -{ - Llb_Var_t * pVar; - int i; - Llb_PartForEachVar( p, pPart, pVar, i ) - if ( Vec_IntSize(pVar->vParts) == 1 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if partition has singleton variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4Print( Llb_Mgr_t * p ) -{ - Llb_Prt_t * pPart; - Llb_Var_t * pVar; - int i, k; - printf( "\n" ); - Llb_MgrForEachVar( p, pVar, i ) - { - printf( "Var %3d : ", i ); - Llb_VarForEachPart( p, pVar, pPart, k ) - printf( "%d ", pPart->iPart ); - printf( "\n" ); - } - Llb_MgrForEachPart( p, pPart, i ) - { - printf( "Part %3d : ", i ); - Llb_PartForEachVar( p, pPart, pVar, k ) - printf( "%d ", pVar->iVar ); - printf( "\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Quantifies singles belonging to one partition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_Nonlin4Quantify1( Llb_Mgr_t * p, Llb_Prt_t * pPart ) -{ - Llb_Var_t * pVar; - Llb_Prt_t * pTemp; - Vec_Ptr_t * vSingles; - DdNode * bCube, * bTemp; - int i, RetValue, nSizeNew; - // create cube to be quantified - bCube = Llb_Nonlin4CreateCube1( p, pPart ); Cudd_Ref( bCube ); -// assert( !Cudd_IsConstant(bCube) ); - // derive new function - pPart->bFunc = Cudd_bddExistAbstract( p->dd, bTemp = pPart->bFunc, bCube ); Cudd_Ref( pPart->bFunc ); - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bCube ); - // get support - vSingles = Vec_PtrAlloc( 0 ); - nSizeNew = Cudd_DagSize(pPart->bFunc); - Extra_SupportArray( p->dd, pPart->bFunc, p->pSupp ); - Llb_PartForEachVar( p, pPart, pVar, i ) - if ( p->pSupp[pVar->iVar] ) - { - assert( Vec_IntSize(pVar->vParts) > 1 ); - pVar->nScore -= pPart->nSize - nSizeNew; - } - else - { - RetValue = Vec_IntRemove( pVar->vParts, pPart->iPart ); - assert( RetValue ); - pVar->nScore -= pPart->nSize; - if ( Vec_IntSize(pVar->vParts) == 0 ) - Llb_Nonlin4RemoveVar( p, pVar ); - else if ( Vec_IntSize(pVar->vParts) == 1 ) - Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); - } - - // update partition - pPart->nSize = nSizeNew; - Vec_IntClear( pPart->vVars ); - for ( i = 0; i < p->nVars; i++ ) - if ( p->pSupp[i] && Vec_IntEntry(p->vVars2Q, i) ) - Vec_IntPush( pPart->vVars, i ); - // remove other variables - Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i ) - Llb_Nonlin4Quantify1( p, pTemp ); - Vec_PtrFree( vSingles ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Quantifies singles belonging to one partition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_Nonlin4Quantify2( Llb_Mgr_t * p, Llb_Prt_t * pPart1, Llb_Prt_t * pPart2 ) -{ - int fVerbose = 0; - Llb_Var_t * pVar; - Llb_Prt_t * pTemp; - Vec_Ptr_t * vSingles; - DdNode * bCube, * bFunc; - int i, RetValue, nSuppSize; -// int iPart1 = pPart1->iPart; -// int iPart2 = pPart2->iPart; - int liveBeg, liveEnd; - - // create cube to be quantified - bCube = Llb_Nonlin4CreateCube2( p, pPart1, pPart2 ); Cudd_Ref( bCube ); - -//printf( "Quantifying " ); Extra_bddPrintSupport( p->dd, bCube ); printf( "\n" ); - -if ( fVerbose ) -{ -printf( "\n" ); -printf( "\n" ); -Llb_Nonlin4Print( p ); -printf( "Conjoining partitions %d and %d.\n", pPart1->iPart, pPart2->iPart ); -Extra_bddPrintSupport( p->dd, bCube ); printf( "\n" ); -} -liveBeg = p->dd->keys - p->dd->dead; - bFunc = Cudd_bddAndAbstract( p->dd, pPart1->bFunc, pPart2->bFunc, bCube ); -liveEnd = p->dd->keys - p->dd->dead; -//printf( "%d ", liveEnd-liveBeg ); - - if ( bFunc == NULL ) - { - Cudd_RecursiveDeref( p->dd, bCube ); - return 0; - } - Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( p->dd, bCube ); - -//printf( "Creating part %d ", p->iPartFree ); Extra_bddPrintSupport( p->dd, bFunc ); printf( "\n" ); - -//printf( "Creating %d\n", p->iPartFree ); - - // create new partition - pTemp = p->pParts[p->iPartFree] = ABC_CALLOC( Llb_Prt_t, 1 ); - pTemp->iPart = p->iPartFree++; - pTemp->nSize = Cudd_DagSize(bFunc); - pTemp->bFunc = bFunc; - pTemp->vVars = Vec_IntAlloc( 8 ); - // update variables - Llb_PartForEachVar( p, pPart1, pVar, i ) - { - RetValue = Vec_IntRemove( pVar->vParts, pPart1->iPart ); - assert( RetValue ); - pVar->nScore -= pPart1->nSize; - } - // update variables - Llb_PartForEachVar( p, pPart2, pVar, i ) - { - RetValue = Vec_IntRemove( pVar->vParts, pPart2->iPart ); - assert( RetValue ); - pVar->nScore -= pPart2->nSize; - } - // add variables to the new partition - nSuppSize = 0; - Extra_SupportArray( p->dd, bFunc, p->pSupp ); - for ( i = 0; i < p->nVars; i++ ) - { - nSuppSize += p->pSupp[i]; - if ( p->pSupp[i] && Vec_IntEntry(p->vVars2Q, i) ) - { - pVar = Llb_MgrVar( p, i ); - pVar->nScore += pTemp->nSize; - Vec_IntPush( pVar->vParts, pTemp->iPart ); - Vec_IntPush( pTemp->vVars, i ); - } - } - p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize ); - // remove variables and collect partitions with singleton variables - vSingles = Vec_PtrAlloc( 0 ); - Llb_PartForEachVar( p, pPart1, pVar, i ) - { - if ( Vec_IntSize(pVar->vParts) == 0 ) - Llb_Nonlin4RemoveVar( p, pVar ); - else if ( Vec_IntSize(pVar->vParts) == 1 ) - { - if ( fVerbose ) - printf( "Adding partition %d because of var %d.\n", - Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar ); - Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); - } - } - Llb_PartForEachVar( p, pPart2, pVar, i ) - { - if ( pVar == NULL ) - continue; - if ( Vec_IntSize(pVar->vParts) == 0 ) - Llb_Nonlin4RemoveVar( p, pVar ); - else if ( Vec_IntSize(pVar->vParts) == 1 ) - { - if ( fVerbose ) - printf( "Adding partition %d because of var %d.\n", - Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0))->iPart, pVar->iVar ); - Vec_PtrPushUnique( vSingles, Llb_MgrPart(p, Vec_IntEntry(pVar->vParts,0)) ); - } - } - // remove partitions - Llb_Nonlin4RemovePart( p, pPart1 ); - Llb_Nonlin4RemovePart( p, pPart2 ); - // remove other variables -if ( fVerbose ) -Llb_Nonlin4Print( p ); - Vec_PtrForEachEntry( Llb_Prt_t *, vSingles, pTemp, i ) - { -if ( fVerbose ) -printf( "Updating partitiong %d with singlton vars.\n", pTemp->iPart ); - Llb_Nonlin4Quantify1( p, pTemp ); - } -if ( fVerbose ) -Llb_Nonlin4Print( p ); - Vec_PtrFree( vSingles ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes volume of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4CutNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) -{ - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return; - Aig_ObjSetTravIdCurrent(p, pObj); - if ( Saig_ObjIsLi(p, pObj) ) - { - Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); - return; - } - if ( Aig_ObjIsConst1(pObj) ) - return; - assert( Aig_ObjIsNode(pObj) ); - Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin0(pObj), vNodes); - Llb_Nonlin4CutNodes_rec(p, Aig_ObjFanin1(pObj), vNodes); - Vec_PtrPush( vNodes, pObj ); -} - -/**Function************************************************************* - - Synopsis [Computes volume of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_Nonlin4CutNodes( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i; - // mark the lower cut with the traversal ID - Aig_ManIncrementTravId(p); - Vec_PtrForEachEntry( Aig_Obj_t *, vLower, pObj, i ) - Aig_ObjSetTravIdCurrent( p, pObj ); - // count the upper cut - vNodes = Vec_PtrAlloc( 100 ); - Vec_PtrForEachEntry( Aig_Obj_t *, vUpper, pObj, i ) - Llb_Nonlin4CutNodes_rec( p, pObj, vNodes ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Starts non-linear quantification scheduling.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4AddPair( Llb_Mgr_t * p, int iPart, int iVar ) -{ - if ( p->pVars[iVar] == NULL ) - { - p->pVars[iVar] = ABC_CALLOC( Llb_Var_t, 1 ); - p->pVars[iVar]->iVar = iVar; - p->pVars[iVar]->nScore = 0; - p->pVars[iVar]->vParts = Vec_IntAlloc( 8 ); - } - Vec_IntPush( p->pVars[iVar]->vParts, iPart ); - Vec_IntPush( p->pParts[iPart]->vVars, iVar ); -} - -/**Function************************************************************* - - Synopsis [Starts non-linear quantification scheduling.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4AddPartition( Llb_Mgr_t * p, int i, DdNode * bFunc ) -{ - int k, nSuppSize; - assert( !Cudd_IsConstant(bFunc) ); -//printf( "Creating init %d\n", i ); - // create partition - p->pParts[i] = ABC_CALLOC( Llb_Prt_t, 1 ); - p->pParts[i]->iPart = i; - p->pParts[i]->bFunc = bFunc; Cudd_Ref( bFunc ); - p->pParts[i]->vVars = Vec_IntAlloc( 8 ); - // add support dependencies - nSuppSize = 0; - Extra_SupportArray( p->dd, bFunc, p->pSupp ); - for ( k = 0; k < p->nVars; k++ ) - { - nSuppSize += p->pSupp[k]; - if ( p->pSupp[k] && Vec_IntEntry(p->vVars2Q, k) ) - Llb_Nonlin4AddPair( p, i, k ); - } - p->nSuppMax = Abc_MaxInt( p->nSuppMax, nSuppSize ); -} - -/**Function************************************************************* - - Synopsis [Checks that each var appears in at least one partition.] - - Description [] - - SideEffects [] - - SeeAlso [] -**********************************************************************/ -void Llb_Nonlin4CheckVars( Llb_Mgr_t * p ) -{ - Llb_Var_t * pVar; - int i; - Llb_MgrForEachVar( p, pVar, i ) - assert( Vec_IntSize(pVar->vParts) > 1 ); -} - -/**Function************************************************************* - - Synopsis [Find next partition to quantify] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_Nonlin4NextPartitions( Llb_Mgr_t * p, Llb_Prt_t ** ppPart1, Llb_Prt_t ** ppPart2 ) -{ - Llb_Var_t * pVar, * pVarBest = NULL; - Llb_Prt_t * pPart, * pPart1Best = NULL, * pPart2Best = NULL; - int i; - Llb_Nonlin4CheckVars( p ); - // find variable with minimum score - Llb_MgrForEachVar( p, pVar, i ) - { - if ( p->nSizeMax && pVar->nScore > p->nSizeMax ) - continue; -// if ( pVarBest == NULL || Vec_IntSize(pVarBest->vParts) * pVarBest->nScore > Vec_IntSize(pVar->vParts) * pVar->nScore ) - if ( pVarBest == NULL || pVarBest->nScore > pVar->nScore ) - pVarBest = pVar; -// printf( "%d ", pVar->nScore ); - } -//printf( "\n" ); - if ( pVarBest == NULL ) - return 0; - // find two partitions with minimum size - Llb_VarForEachPart( p, pVarBest, pPart, i ) - { - if ( pPart1Best == NULL ) - pPart1Best = pPart; - else if ( pPart2Best == NULL ) - pPart2Best = pPart; - else if ( pPart1Best->nSize > pPart->nSize || pPart2Best->nSize > pPart->nSize ) - { - if ( pPart1Best->nSize > pPart2Best->nSize ) - pPart1Best = pPart; - else - pPart2Best = pPart; - } - } -//printf( "Selecting %d and parts %d and %d\n", pVarBest->iVar, pPart1Best->nSize, pPart2Best->nSize ); -//Extra_bddPrintSupport( p->dd, pPart1Best->bFunc ); printf( "\n" ); -//Extra_bddPrintSupport( p->dd, pPart2Best->bFunc ); printf( "\n" ); - - *ppPart1 = pPart1Best; - *ppPart2 = pPart2Best; - return 1; -} - -/**Function************************************************************* - - Synopsis [Recomputes scores after variable reordering.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4RecomputeScores( Llb_Mgr_t * p ) -{ - Llb_Prt_t * pPart; - Llb_Var_t * pVar; - int i, k; - Llb_MgrForEachPart( p, pPart, i ) - pPart->nSize = Cudd_DagSize(pPart->bFunc); - Llb_MgrForEachVar( p, pVar, i ) - { - pVar->nScore = 0; - Llb_VarForEachPart( p, pVar, pPart, k ) - pVar->nScore += pPart->nSize; - } -} - -/**Function************************************************************* - - Synopsis [Recomputes scores after variable reordering.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4VerifyScores( Llb_Mgr_t * p ) -{ - Llb_Prt_t * pPart; - Llb_Var_t * pVar; - int i, k, nScore; - Llb_MgrForEachPart( p, pPart, i ) - assert( pPart->nSize == Cudd_DagSize(pPart->bFunc) ); - Llb_MgrForEachVar( p, pVar, i ) - { - nScore = 0; - Llb_VarForEachPart( p, pVar, pPart, k ) - nScore += pPart->nSize; - assert( nScore == pVar->nScore ); - } -} - -/**Function************************************************************* - - Synopsis [Starts non-linear quantification scheduling.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Mgr_t * Llb_Nonlin4Alloc( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q, int nSizeMax ) -{ - Llb_Mgr_t * p; - DdNode * bFunc; - int i; - p = ABC_CALLOC( Llb_Mgr_t, 1 ); - p->dd = dd; - p->nSizeMax = nSizeMax; - p->vVars2Q = vVars2Q; - p->nVars = Cudd_ReadSize(dd); - p->iPartFree = Vec_PtrSize(vParts); - p->pVars = ABC_CALLOC( Llb_Var_t *, p->nVars ); - p->pParts = ABC_CALLOC( Llb_Prt_t *, 2 * p->iPartFree + 2 ); - p->pSupp = ABC_ALLOC( int, Cudd_ReadSize(dd) ); - // add pairs (refs are consumed inside) - Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i ) - Llb_Nonlin4AddPartition( p, i, bFunc ); - // add partition - if ( bCurrent ) - Llb_Nonlin4AddPartition( p, p->iPartFree++, bCurrent ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops non-linear quantification scheduling.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4Free( Llb_Mgr_t * p ) -{ - Llb_Prt_t * pPart; - Llb_Var_t * pVar; - int i; - Llb_MgrForEachVar( p, pVar, i ) - Llb_Nonlin4RemoveVar( p, pVar ); - Llb_MgrForEachPart( p, pPart, i ) - Llb_Nonlin4RemovePart( p, pPart ); - ABC_FREE( p->pVars ); - ABC_FREE( p->pParts ); - ABC_FREE( p->pSupp ); - ABC_FREE( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_Nonlin4Image( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q ) -{ - Llb_Prt_t * pPart, * pPart1, * pPart2; - Llb_Mgr_t * p; - DdNode * bFunc, * bTemp; - int i, nReorders; - // start the manager - p = Llb_Nonlin4Alloc( dd, vParts, bCurrent, vVars2Q, 0 ); - // remove singles - Llb_MgrForEachPart( p, pPart, i ) - if ( Llb_Nonlin4HasSingletonVars(p, pPart) ) - Llb_Nonlin4Quantify1( p, pPart ); - // compute scores - Llb_Nonlin4RecomputeScores( p ); - // iteratively quantify variables - while ( Llb_Nonlin4NextPartitions(p, &pPart1, &pPart2) ) - { - nReorders = Cudd_ReadReorderings(dd); - if ( !Llb_Nonlin4Quantify2( p, pPart1, pPart2 ) ) - { - Llb_Nonlin4Free( p ); - return NULL; - } - if ( nReorders < Cudd_ReadReorderings(dd) ) - Llb_Nonlin4RecomputeScores( p ); -// else -// Llb_Nonlin4VerifyScores( p ); - } - // load partitions - bFunc = Cudd_ReadOne(p->dd); Cudd_Ref( bFunc ); - Llb_MgrForEachPart( p, pPart, i ) - { - bFunc = Cudd_bddAnd( p->dd, bTemp = bFunc, pPart->bFunc ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } -// nSuppMax = p->nSuppMax; - Llb_Nonlin4Free( p ); -//printf( "\n" ); - // return - Cudd_Deref( bFunc ); - return bFunc; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_Nonlin4Group( DdManager * dd, Vec_Ptr_t * vParts, Vec_Int_t * vVars2Q, int nSizeMax ) -{ - Vec_Ptr_t * vGroups; - Llb_Prt_t * pPart, * pPart1, * pPart2; - Llb_Mgr_t * p; - int i, nReorders;//, clk = Abc_Clock(); - // start the manager - p = Llb_Nonlin4Alloc( dd, vParts, NULL, vVars2Q, nSizeMax ); - // remove singles - Llb_MgrForEachPart( p, pPart, i ) - if ( Llb_Nonlin4HasSingletonVars(p, pPart) ) - Llb_Nonlin4Quantify1( p, pPart ); - // compute scores - Llb_Nonlin4RecomputeScores( p ); - // iteratively quantify variables - while ( Llb_Nonlin4NextPartitions(p, &pPart1, &pPart2) ) - { - nReorders = Cudd_ReadReorderings(dd); - if ( !Llb_Nonlin4Quantify2( p, pPart1, pPart2 ) ) - { - Llb_Nonlin4Free( p ); - return NULL; - } - if ( nReorders < Cudd_ReadReorderings(dd) ) - Llb_Nonlin4RecomputeScores( p ); -// else -// Llb_Nonlin4VerifyScores( p ); - } - // load partitions - vGroups = Vec_PtrAlloc( 1000 ); - Llb_MgrForEachPart( p, pPart, i ) - { -//printf( "Iteration %d ", pPart->iPart ); - if ( Cudd_IsConstant(pPart->bFunc) ) - { -//printf( "Constant\n" ); - assert( !Cudd_IsComplement(pPart->bFunc) ); - continue; - } -//printf( "\n" ); - Vec_PtrPush( vGroups, pPart->bFunc ); - Cudd_Ref( pPart->bFunc ); -//printf( "Part %d ", pPart->iPart ); -//Extra_bddPrintSupport( p->dd, pPart->bFunc ); printf( "\n" ); - } - Llb_Nonlin4Free( p ); -//Abc_PrintTime( 1, "Reparametrization time", Abc_Clock() - clk ); - return vGroups; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/llb/llb4Map.c b/src/proof/llb/llb4Map.c deleted file mode 100644 index 4487ce25..00000000 --- a/src/proof/llb/llb4Map.c +++ /dev/null @@ -1,123 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb2Map.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Non-linear quantification scheduling.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb2Map.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" -#include "base/abc/abc.h" -#include "map/if/if.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns internal nodes used in the mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_AigMap( Aig_Man_t * pAig, int nLutSize, int nLutMin ) -{ - extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); - extern If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); - extern void Gia_ManSetIfParsDefault( void * pPars ); - If_Par_t Pars, * pPars = &Pars; - If_Man_t * pIfMan; - If_Obj_t * pAnd; - Abc_Ntk_t * pNtk; - Abc_Obj_t * pNode; - Vec_Int_t * vNodes; - Aig_Obj_t * pObj; - int i; - - // create ABC network - pNtk = Abc_NtkFromAigPhase( pAig ); - assert( Abc_NtkIsStrash(pNtk) ); - - // derive mapping parameters - Gia_ManSetIfParsDefault( pPars ); - pPars->nLutSize = nLutSize; - - // get timing information - pPars->pTimesArr = Abc_NtkGetCiArrivalFloats(pNtk); - pPars->pTimesReq = Abc_NtkGetCoRequiredFloats(pNtk); - - // perform LUT mapping - pIfMan = Abc_NtkToIf( pNtk, pPars ); - if ( pIfMan == NULL ) - { - Abc_NtkDelete( pNtk ); - return NULL; - } - if ( !If_ManPerformMapping( pIfMan ) ) - { - Abc_NtkDelete( pNtk ); - If_ManStop( pIfMan ); - return NULL; - } - - // mark nodes in the AIG used in the mapping - Aig_ManCleanMarkA( pAig ); - Aig_ManForEachNode( pAig, pObj, i ) - { - pNode = (Abc_Obj_t *)pObj->pData; - if ( pNode == NULL ) - continue; - pAnd = (If_Obj_t *)pNode->pCopy; - if ( pAnd == NULL ) - continue; - if ( pAnd->nRefs > 0 && (int)If_ObjCutBest(pAnd)->nLeaves >= nLutMin ) - pObj->fMarkA = 1; - } - Abc_NtkDelete( pNtk ); - If_ManStop( pIfMan ); - - // unmark flop drivers - Saig_ManForEachLi( pAig, pObj, i ) - Aig_ObjFanin0(pObj)->fMarkA = 0; - - // collect mapping - vNodes = Vec_IntAlloc( 100 ); - Aig_ManForEachNode( pAig, pObj, i ) - if ( pObj->fMarkA ) - Vec_IntPush( vNodes, Aig_ObjId(pObj) ); - Aig_ManCleanMarkA( pAig ); - return vNodes; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/llb/llb4Nonlin.c b/src/proof/llb/llb4Nonlin.c deleted file mode 100644 index a9421358..00000000 --- a/src/proof/llb/llb4Nonlin.c +++ /dev/null @@ -1,1185 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb2Nonlin.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Non-linear quantification scheduling.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb2Nonlin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" -#include "base/abc/abc.h" -#include "aig/gia/giaAig.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Llb_Mnx_t_ Llb_Mnx_t; -struct Llb_Mnx_t_ -{ - // user info - Aig_Man_t * pAig; // AIG manager - Gia_ParLlb_t * pPars; // parameters - - // intermediate BDDs - DdManager * dd; // BDD manager - DdNode * bBad; // bad states in terms of CIs - DdNode * bReached; // reached states - DdNode * bCurrent; // from states - DdNode * bNext; // to states - Vec_Ptr_t * vRings; // onion rings in ddR - Vec_Ptr_t * vRoots; // BDDs for partitions - - // structural info - Vec_Int_t * vOrder; // for each object ID, its BDD variable number or -1 - Vec_Int_t * vVars2Q; // 1 if variable is quantifiable; 0 othervise - - abctime timeImage; - abctime timeRemap; - abctime timeReo; - abctime timeOther; - abctime timeTotal; -}; - -//extern int timeBuild, timeAndEx, timeOther; -//extern int nSuppMax; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes bad in working manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_Nonlin4ComputeBad( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder ) -{ - Vec_Ptr_t * vNodes; - DdNode * bBdd, * bBdd0, * bBdd1, * bTemp, * bResult, * bCube; - Aig_Obj_t * pObj; - int i; - Aig_ManCleanData( pAig ); - // assign elementary variables - Aig_ManConst1(pAig)->pData = Cudd_ReadOne(dd); - Aig_ManForEachCi( pAig, pObj, i ) - pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); - // compute internal nodes - vNodes = Aig_ManDfsNodes( pAig, (Aig_Obj_t **)Vec_PtrArray(pAig->vCos), Saig_ManPoNum(pAig) ); - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - { - if ( !Aig_ObjIsNode(pObj) ) - continue; - bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); - bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); - if ( bBdd == NULL ) - { - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - if ( Aig_ObjIsNode(pObj) && pObj->pData != NULL ) - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - Vec_PtrFree( vNodes ); - return NULL; - } - Cudd_Ref( bBdd ); - pObj->pData = bBdd; - } - // quantify PIs of each PO - bResult = Cudd_ReadLogicZero( dd ); Cudd_Ref( bResult ); - Saig_ManForEachPo( pAig, pObj, i ) - { - bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bResult = Cudd_bddOr( dd, bTemp = bResult, bBdd0 ); - if ( bResult == NULL ) - { - Cudd_RecursiveDeref( dd, bTemp ); - break; - } - Cudd_Ref( bResult ); - Cudd_RecursiveDeref( dd, bTemp ); - } - // deref - Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) - if ( Aig_ObjIsNode(pObj) && pObj->pData != NULL ) - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - Vec_PtrFree( vNodes ); - if ( bResult ) - { - bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube ); - Saig_ManForEachPi( pAig, pObj, i ) - { - bCube = Cudd_bddAnd( dd, bTemp = bCube, (DdNode *)pObj->pData ); - if ( bCube == NULL ) - { - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bResult ); - bResult = NULL; - break; - } - Cudd_Ref( bCube ); - Cudd_RecursiveDeref( dd, bTemp ); - } - if ( bResult != NULL ) - { - bResult = Cudd_bddExistAbstract( dd, bTemp = bResult, bCube ); Cudd_Ref( bResult ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bCube ); - Cudd_Deref( bResult ); - } - } -//if ( bResult ) -//printf( "Bad state = %d.\n", Cudd_DagSize(bResult) ); - return bResult; -} - -/**Function************************************************************* - - Synopsis [Derives BDDs for the partitions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_Nonlin4DerivePartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder ) -{ - Vec_Ptr_t * vRoots; - Aig_Obj_t * pObj; - DdNode * bBdd, * bBdd0, * bBdd1, * bPart; - int i; - Aig_ManCleanData( pAig ); - // assign elementary variables - Aig_ManConst1(pAig)->pData = Cudd_ReadOne(dd); - Aig_ManForEachCi( pAig, pObj, i ) - pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); - Aig_ManForEachNode( pAig, pObj, i ) - if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) - { - pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); - Cudd_Ref( (DdNode *)pObj->pData ); - } - Saig_ManForEachLi( pAig, pObj, i ) - pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); - // compute intermediate BDDs - vRoots = Vec_PtrAlloc( 100 ); - Aig_ManForEachNode( pAig, pObj, i ) - { - bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bBdd1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); - bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); - if ( bBdd == NULL ) - goto finish; - Cudd_Ref( bBdd ); - if ( pObj->pData == NULL ) - { - pObj->pData = bBdd; - continue; - } - // create new partition - bPart = Cudd_bddXnor( dd, (DdNode *)pObj->pData, bBdd ); - if ( bPart == NULL ) - goto finish; - Cudd_Ref( bPart ); - Cudd_RecursiveDeref( dd, bBdd ); - Vec_PtrPush( vRoots, bPart ); -//printf( "%d ", Cudd_DagSize(bPart) ); - } - // compute register output BDDs - Saig_ManForEachLi( pAig, pObj, i ) - { - bBdd0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bPart = Cudd_bddXnor( dd, (DdNode *)pObj->pData, bBdd0 ); - if ( bPart == NULL ) - goto finish; - Cudd_Ref( bPart ); - Vec_PtrPush( vRoots, bPart ); -//printf( "%d ", Cudd_DagSize(bPart) ); - } -//printf( "\n" ); - Aig_ManForEachNode( pAig, pObj, i ) - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - return vRoots; - // early termination -finish: - Aig_ManForEachNode( pAig, pObj, i ) - if ( pObj->pData ) - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - Vec_PtrForEachEntry( DdNode *, vRoots, bPart, i ) - Cudd_RecursiveDeref( dd, bPart ); - Vec_PtrFree( vRoots ); - return NULL; -} - -/**Function************************************************************* - - Synopsis [Find simple variable ordering.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_Nonlin4CreateOrderSimple( Aig_Man_t * pAig ) -{ - Vec_Int_t * vOrder; - Aig_Obj_t * pObj; - int i, Counter = 0; - vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) ); - Aig_ManForEachCi( pAig, pObj, i ) - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); - Saig_ManForEachLi( pAig, pObj, i ) - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); - return vOrder; -} - -/**Function************************************************************* - - Synopsis [Find good static variable ordering.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4CreateOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter ) -{ - Aig_Obj_t * pFanin0, * pFanin1; - if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) - return; - Aig_ObjSetTravIdCurrent( pAig, pObj ); - assert( Llb_ObjBddVar(vOrder, pObj) < 0 ); - if ( Aig_ObjIsCi(pObj) ) - { -// if ( Saig_ObjIsLo(pAig, pObj) ) -// Vec_IntWriteEntry( vOrder, Aig_ObjId(Saig_ObjLoToLi(pAig, pObj)), (*pCounter)++ ); - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); - return; - } - // try fanins with higher level first - pFanin0 = Aig_ObjFanin0(pObj); - pFanin1 = Aig_ObjFanin1(pObj); -// if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) ) - if ( pFanin0->Level > pFanin1->Level ) - { - Llb_Nonlin4CreateOrder_rec( pAig, pFanin0, vOrder, pCounter ); - Llb_Nonlin4CreateOrder_rec( pAig, pFanin1, vOrder, pCounter ); - } - else - { - Llb_Nonlin4CreateOrder_rec( pAig, pFanin1, vOrder, pCounter ); - Llb_Nonlin4CreateOrder_rec( pAig, pFanin0, vOrder, pCounter ); - } - if ( pObj->fMarkA ) - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); -} - -/**Function************************************************************* - - Synopsis [Collect nodes with the given fanout count.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_Nonlin4CollectHighRefNodes( Aig_Man_t * pAig, int nFans ) -{ - Vec_Int_t * vNodes; - Aig_Obj_t * pObj; - int i; - Aig_ManCleanMarkA( pAig ); - Aig_ManForEachNode( pAig, pObj, i ) - if ( Aig_ObjRefs(pObj) >= nFans ) - pObj->fMarkA = 1; - // unmark flop drivers - Saig_ManForEachLi( pAig, pObj, i ) - Aig_ObjFanin0(pObj)->fMarkA = 0; - // collect mapping - vNodes = Vec_IntAlloc( 100 ); - Aig_ManForEachNode( pAig, pObj, i ) - if ( pObj->fMarkA ) - Vec_IntPush( vNodes, Aig_ObjId(pObj) ); - Aig_ManCleanMarkA( pAig ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Find good static variable ordering.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_Nonlin4CreateOrder( Aig_Man_t * pAig ) -{ - Vec_Int_t * vNodes = NULL; - Vec_Int_t * vOrder; - Aig_Obj_t * pObj; - int i, Counter = 0; -/* - // mark internal nodes to be used - Aig_ManCleanMarkA( pAig ); - vNodes = Llb_Nonlin4CollectHighRefNodes( pAig, 4 ); - Aig_ManForEachObjVec( vNodes, pAig, pObj, i ) - pObj->fMarkA = 1; -printf( "Techmapping added %d pivots.\n", Vec_IntSize(vNodes) ); -*/ - // collect nodes in the order - vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) ); - Aig_ManIncrementTravId( pAig ); - Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); - Saig_ManForEachLi( pAig, pObj, i ) - { - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); - Llb_Nonlin4CreateOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter ); - } - Aig_ManForEachCi( pAig, pObj, i ) - if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) - { -// if ( Saig_ObjIsLo(pAig, pObj) ) -// Vec_IntWriteEntry( vOrder, Aig_ObjId(Saig_ObjLoToLi(pAig, pObj)), Counter++ ); - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); - } - assert( Counter <= Aig_ManCiNum(pAig) + Aig_ManRegNum(pAig) + (vNodes?Vec_IntSize(vNodes):0) ); - Aig_ManCleanMarkA( pAig ); - Vec_IntFreeP( &vNodes ); - return vOrder; -} - - -/**Function************************************************************* - - Synopsis [Creates quantifiable varaibles for both types of traversal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_Nonlin4CreateVars2Q( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fBackward ) -{ - Vec_Int_t * vVars2Q; - Aig_Obj_t * pObjLi, * pObjLo; - int i; - vVars2Q = Vec_IntAlloc( 0 ); - Vec_IntFill( vVars2Q, Cudd_ReadSize(dd), 1 ); - Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) - Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, fBackward ? pObjLo : pObjLi), 0 ); - return vVars2Q; -} - -/**Function************************************************************* - - Synopsis [Compute initial state in terms of current state variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4SetupVarMap( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder ) -{ - DdNode ** pVarsX, ** pVarsY; - Aig_Obj_t * pObjLo, * pObjLi; - int i; - pVarsX = ABC_ALLOC( DdNode *, Cudd_ReadSize(dd) ); - pVarsY = ABC_ALLOC( DdNode *, Cudd_ReadSize(dd) ); - Saig_ManForEachLiLo( pAig, pObjLo, pObjLi, i ) - { - assert( Llb_ObjBddVar(vOrder, pObjLo) >= 0 ); - assert( Llb_ObjBddVar(vOrder, pObjLi) >= 0 ); - pVarsX[i] = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLo) ); - pVarsY[i] = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLi) ); - } - Cudd_SetVarMap( dd, pVarsX, pVarsY, Aig_ManRegNum(pAig) ); - ABC_FREE( pVarsX ); - ABC_FREE( pVarsY ); -} - -/**Function************************************************************* - - Synopsis [Compute initial state in terms of current state variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_Nonlin4ComputeInitState( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fBackward ) -{ - Aig_Obj_t * pObjLi, * pObjLo; - DdNode * bRes, * bVar, * bTemp; - int i; - abctime TimeStop; - TimeStop = dd->TimeStop; dd->TimeStop = 0; - bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); - Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) - { - bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, fBackward? pObjLi : pObjLo) ); - bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bRes ); - dd->TimeStop = TimeStop; - return bRes; -} - -/**Function************************************************************* - - Synopsis [Compute initial state in terms of current state variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_Nonlin4ComputeCube( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, char * pValues, int Flag ) -{ - Aig_Obj_t * pObjLo, * pObjLi, * pObjTemp; - DdNode * bRes, * bVar, * bTemp; - int i; - abctime TimeStop; - TimeStop = dd->TimeStop; dd->TimeStop = 0; - bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); - Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) - { - if ( Flag ) - pObjTemp = pObjLo, pObjLo = pObjLi, pObjLi = pObjTemp; - // get the correspoding flop input variable - bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObjLi) ); - if ( pValues[Llb_ObjBddVar(vOrder, pObjLo)] != 1 ) - bVar = Cudd_Not(bVar); - // create cube - bRes = Cudd_bddAnd( dd, bTemp = bRes, bVar ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bRes ); - dd->TimeStop = TimeStop; - return bRes; -} - -/**Function************************************************************* - - Synopsis [Compute initial state in terms of current state variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4RecordState( Aig_Man_t * pAig, Vec_Int_t * vOrder, unsigned * pState, char * pValues, int fBackward ) -{ - Aig_Obj_t * pObjLo, * pObjLi; - int i; - Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) - if ( pValues[Llb_ObjBddVar(vOrder, fBackward? pObjLi : pObjLo)] == 1 ) - Abc_InfoSetBit( pState, i ); -} - -/**Function************************************************************* - - Synopsis [Multiply every partition by the cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_Nonlin4Multiply( DdManager * dd, DdNode * bCube, Vec_Ptr_t * vParts ) -{ - Vec_Ptr_t * vNew; - DdNode * bTemp, * bFunc; - int i; - vNew = Vec_PtrAlloc( Vec_PtrSize(vParts) ); - Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i ) - { - bTemp = Cudd_bddAnd( dd, bFunc, bCube ); Cudd_Ref( bTemp ); - Vec_PtrPush( vNew, bTemp ); - } - return vNew; -} - -/**Function************************************************************* - - Synopsis [Multiply every partition by the cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4Deref( DdManager * dd, Vec_Ptr_t * vParts ) -{ - DdNode * bFunc; - int i; - Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i ) - Cudd_RecursiveDeref( dd, bFunc ); - Vec_PtrFree( vParts ); -} - -/**Function************************************************************* - - Synopsis [Derives counter-example by backward reachability.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_Nonlin4DeriveCex( Llb_Mnx_t * p, int fBackward, int fVerbose ) -{ - Vec_Int_t * vVars2Q; - Vec_Ptr_t * vStates, * vRootsNew; - Aig_Obj_t * pObj; - DdNode * bState = NULL, * bImage, * bOneCube, * bRing; - int i, v, RetValue;//, clk = Abc_Clock(); - char * pValues; - assert( Vec_PtrSize(p->vRings) > 0 ); - // disable the timeout - p->dd->TimeStop = 0; - - // start the state set - vStates = Vec_PtrAllocSimInfo( Vec_PtrSize(p->vRings), Abc_BitWordNum(Aig_ManRegNum(p->pAig)) ); - Vec_PtrCleanSimInfo( vStates, 0, Abc_BitWordNum(Aig_ManRegNum(p->pAig)) ); - if ( fBackward ) - Vec_PtrReverseOrder( vStates ); - - // get the last cube - pValues = ABC_ALLOC( char, Cudd_ReadSize(p->dd) ); - bOneCube = Cudd_bddIntersect( p->dd, (DdNode *)Vec_PtrEntryLast(p->vRings), p->bBad ); Cudd_Ref( bOneCube ); - RetValue = Cudd_bddPickOneCube( p->dd, bOneCube, pValues ); - Cudd_RecursiveDeref( p->dd, bOneCube ); - assert( RetValue ); - - // record the cube - Llb_Nonlin4RecordState( p->pAig, p->vOrder, (unsigned *)Vec_PtrEntryLast(vStates), pValues, fBackward ); - - // write state in terms of NS variables - if ( Vec_PtrSize(p->vRings) > 1 ) - { - bState = Llb_Nonlin4ComputeCube( p->dd, p->pAig, p->vOrder, pValues, fBackward ); Cudd_Ref( bState ); - } - // perform backward analysis - vVars2Q = Llb_Nonlin4CreateVars2Q( p->dd, p->pAig, p->vOrder, !fBackward ); - Vec_PtrForEachEntryReverse( DdNode *, p->vRings, bRing, v ) - { - if ( v == Vec_PtrSize(p->vRings) - 1 ) - continue; - - // preprocess partitions - vRootsNew = Llb_Nonlin4Multiply( p->dd, bState, p->vRoots ); - Cudd_RecursiveDeref( p->dd, bState ); - - // compute the next states - bImage = Llb_Nonlin4Image( p->dd, vRootsNew, NULL, vVars2Q ); Cudd_Ref( bImage ); - Llb_Nonlin4Deref( p->dd, vRootsNew ); - - // intersect with the previous set - bOneCube = Cudd_bddIntersect( p->dd, bImage, bRing ); Cudd_Ref( bOneCube ); - Cudd_RecursiveDeref( p->dd, bImage ); - - // find any assignment of the BDD - RetValue = Cudd_bddPickOneCube( p->dd, bOneCube, pValues ); - Cudd_RecursiveDeref( p->dd, bOneCube ); - assert( RetValue ); - - // record the cube - Llb_Nonlin4RecordState( p->pAig, p->vOrder, (unsigned *)Vec_PtrEntry(vStates, v), pValues, fBackward ); - - // check that we get the init state - if ( v == 0 ) - { - Saig_ManForEachLo( p->pAig, pObj, i ) - assert( fBackward || pValues[Llb_ObjBddVar(p->vOrder, pObj)] == 0 ); - break; - } - - // write state in terms of NS variables - bState = Llb_Nonlin4ComputeCube( p->dd, p->pAig, p->vOrder, pValues, fBackward ); Cudd_Ref( bState ); - } - Vec_IntFree( vVars2Q ); - ABC_FREE( pValues ); - if ( fBackward ) - Vec_PtrReverseOrder( vStates ); -// if ( fVerbose ) -// Abc_PrintTime( 1, "BDD-based cex generation time", Abc_Clock() - clk ); - return vStates; -} - - -/**Function************************************************************* - - Synopsis [Perform reachability with hints.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_Nonlin4Reachability( Llb_Mnx_t * p ) -{ - DdNode * bAux; - int nIters, nBddSizeFr = 0, nBddSizeTo = 0, nBddSizeTo2 = 0; - abctime clkTemp, clkIter, clk = Abc_Clock(); - assert( Aig_ManRegNum(p->pAig) > 0 ); - - if ( p->pPars->fBackward ) - { - // create bad state in the ring manager - if ( !p->pPars->fSkipOutCheck ) - { - p->bBad = Llb_Nonlin4ComputeInitState( p->dd, p->pAig, p->vOrder, p->pPars->fBackward ); Cudd_Ref( p->bBad ); - } - // create init state - if ( p->pPars->fCluster ) - p->bCurrent = p->dd->bFunc, p->dd->bFunc = NULL; - else - { - p->bCurrent = Llb_Nonlin4ComputeBad( p->dd, p->pAig, p->vOrder ); - if ( p->bCurrent == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = -1; - return -1; - } - Cudd_Ref( p->bCurrent ); - } - // remap into the next states - p->bCurrent = Cudd_bddVarMap( p->dd, bAux = p->bCurrent ); - if ( p->bCurrent == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during remapping bad states.\n", p->pPars->TimeLimit ); - Cudd_RecursiveDeref( p->dd, bAux ); - p->pPars->iFrame = -1; - return -1; - } - Cudd_Ref( p->bCurrent ); - Cudd_RecursiveDeref( p->dd, bAux ); - } - else - { - // create bad state in the ring manager - if ( !p->pPars->fSkipOutCheck ) - { - if ( p->pPars->fCluster ) - p->bBad = p->dd->bFunc, p->dd->bFunc = NULL; - else - { - p->bBad = Llb_Nonlin4ComputeBad( p->dd, p->pAig, p->vOrder ); - if ( p->bBad == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during constructing the bad states.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = -1; - return -1; - } - Cudd_Ref( p->bBad ); - } - } - else if ( p->dd->bFunc ) - Cudd_RecursiveDeref( p->dd, p->dd->bFunc ), p->dd->bFunc = NULL; - // compute the starting set of states - p->bCurrent = Llb_Nonlin4ComputeInitState( p->dd, p->pAig, p->vOrder, p->pPars->fBackward ); Cudd_Ref( p->bCurrent ); - } - // perform iterations - p->bReached = p->bCurrent; Cudd_Ref( p->bReached ); - for ( nIters = 0; nIters < p->pPars->nIterMax; nIters++ ) - { - clkIter = Abc_Clock(); - // check the runtime limit - if ( p->pPars->TimeLimit && Abc_Clock() > p->pPars->TimeTarget ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - return -1; - } - - // save the onion ring - Vec_PtrPush( p->vRings, p->bCurrent ); Cudd_Ref( p->bCurrent ); - - // check it for bad states - if ( !p->pPars->fSkipOutCheck && !Cudd_bddLeq( p->dd, p->bCurrent, Cudd_Not(p->bBad) ) ) - { - Vec_Ptr_t * vStates; - assert( p->pAig->pSeqModel == NULL ); - vStates = Llb_Nonlin4DeriveCex( p, p->pPars->fBackward, p->pPars->fVerbose ); - p->pAig->pSeqModel = Llb4_Nonlin4TransformCex( p->pAig, vStates, -1, p->pPars->fVerbose ); - Vec_PtrFreeP( &vStates ); - if ( !p->pPars->fSilent ) - { - Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", p->pAig->pSeqModel->iPo, p->pAig->pName, nIters ); - Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); - } - p->pPars->iFrame = nIters - 1; - return 0; - } - - // compute the next states - clkTemp = Abc_Clock(); - p->bNext = Llb_Nonlin4Image( p->dd, p->vRoots, p->bCurrent, p->vVars2Q ); - if ( p->bNext == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation in quantification.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - return -1; - } - Cudd_Ref( p->bNext ); - p->timeImage += Abc_Clock() - clkTemp; - - // remap into current states - clkTemp = Abc_Clock(); - p->bNext = Cudd_bddVarMap( p->dd, bAux = p->bNext ); - if ( p->bNext == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during remapping next states.\n", p->pPars->TimeLimit ); - Cudd_RecursiveDeref( p->dd, bAux ); - p->pPars->iFrame = nIters - 1; - return -1; - } - Cudd_Ref( p->bNext ); - Cudd_RecursiveDeref( p->dd, bAux ); - p->timeRemap += Abc_Clock() - clkTemp; - - // collect statistics - if ( p->pPars->fVerbose ) - { - nBddSizeFr = Cudd_DagSize( p->bCurrent ); - nBddSizeTo = Cudd_DagSize( bAux ); - nBddSizeTo2 = Cudd_DagSize( p->bNext ); - } - Cudd_RecursiveDeref( p->dd, p->bCurrent ); p->bCurrent = NULL; - - // derive new states - p->bCurrent = Cudd_bddAnd( p->dd, p->bNext, Cudd_Not(p->bReached) ); - if ( p->bCurrent == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - return -1; - } - Cudd_Ref( p->bCurrent ); - Cudd_RecursiveDeref( p->dd, p->bNext ); p->bNext = NULL; - if ( Cudd_IsConstant(p->bCurrent) ) - break; -/* - // reduce BDD size using constrain // Cudd_bddRestrict - p->bCurrent = Cudd_bddRestrict( p->dd, bAux = p->bCurrent, Cudd_Not(p->bReached) ); - Cudd_Ref( p->bCurrent ); -printf( "Before = %d. After = %d.\n", Cudd_DagSize(bAux), Cudd_DagSize(p->bCurrent) ); - Cudd_RecursiveDeref( p->dd, bAux ); -*/ - - // add to the reached set - p->bReached = Cudd_bddOr( p->dd, bAux = p->bReached, p->bCurrent ); - if ( p->bReached == NULL ) - { - if ( !p->pPars->fSilent ) - printf( "Reached timeout (%d seconds) during image computation in transfer 1.\n", p->pPars->TimeLimit ); - p->pPars->iFrame = nIters - 1; - Cudd_RecursiveDeref( p->dd, bAux ); - return -1; - } - Cudd_Ref( p->bReached ); - Cudd_RecursiveDeref( p->dd, bAux ); - - - // report the results - if ( p->pPars->fVerbose ) - { - printf( "I =%5d : ", nIters ); - printf( "Fr =%7d ", nBddSizeFr ); - printf( "ImNs =%7d ", nBddSizeTo ); - printf( "ImCs =%7d ", nBddSizeTo2 ); - printf( "Rea =%7d ", Cudd_DagSize(p->bReached) ); - printf( "(%4d %4d) ", Cudd_ReadReorderings(p->dd), Cudd_ReadGarbageCollections(p->dd) ); - Abc_PrintTime( 1, "T", Abc_Clock() - clkIter ); - } -/* - if ( pPars->fVerbose ) - { - double nMints = Cudd_CountMinterm(p->dd, bReached, Saig_ManRegNum(p->pAig) ); -// Extra_bddPrint( p->dd, bReached );printf( "\n" ); - printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); - fflush( stdout ); - } -*/ - if ( nIters == p->pPars->nIterMax - 1 ) - { - if ( !p->pPars->fSilent ) - printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nIterMax ); - p->pPars->iFrame = nIters; - return -1; - } - } - - // report the stats - if ( p->pPars->fVerbose ) - { - double nMints = Cudd_CountMinterm(p->dd, p->bReached, Saig_ManRegNum(p->pAig) ); - if ( p->bCurrent && Cudd_IsConstant(p->bCurrent) ) - printf( "Reachability analysis completed after %d frames.\n", nIters ); - else - printf( "Reachability analysis is stopped after %d frames.\n", nIters ); - printf( "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Saig_ManRegNum(p->pAig)) ); - fflush( stdout ); - } - if ( p->bCurrent == NULL || !Cudd_IsConstant(p->bCurrent) ) - { - if ( !p->pPars->fSilent ) - printf( "Verified only for states reachable in %d frames. ", nIters ); - p->pPars->iFrame = p->pPars->nIterMax; - return -1; // undecided - } - // report - if ( !p->pPars->fSilent ) - printf( "The miter is proved unreachable after %d iterations. ", nIters ); - if ( !p->pPars->fSilent ) - Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); - p->pPars->iFrame = nIters - 1; - return 1; // unreachable -} - -/**Function************************************************************* - - Synopsis [Reorders BDDs in the working manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4Reorder( DdManager * dd, int fTwice, int fVerbose ) -{ - abctime clk = Abc_Clock(); - if ( fVerbose ) - Abc_Print( 1, "Reordering... Before =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); - Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); - if ( fVerbose ) - Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); - if ( fTwice ) - { - Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); - if ( fVerbose ) - Abc_Print( 1, "After =%5d. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); - } - if ( fVerbose ) - Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Llb_Mnx_t * Llb_MnxStart( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) -{ - Llb_Mnx_t * p; - - p = ABC_CALLOC( Llb_Mnx_t, 1 ); - p->pAig = pAig; - p->pPars = pPars; - - // compute time to stop - p->pPars->TimeTarget = p->pPars->TimeLimit ? p->pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0; - - if ( pPars->fCluster ) - { -// Llb_Nonlin4Cluster( p->pAig, &p->dd, &p->vOrder, &p->vRoots, pPars->nBddMax, pPars->fVerbose ); -// Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); - Llb4_Nonlin4Sweep( p->pAig, pPars->nBddMax, pPars->nClusterMax, &p->dd, &p->vOrder, &p->vRoots, pPars->fVerbose ); - // set the stop time parameter - p->dd->TimeStop = p->pPars->TimeTarget; - } - else - { -// p->vOrder = Llb_Nonlin4CreateOrderSimple( pAig ); - p->vOrder = Llb_Nonlin4CreateOrder( pAig ); - p->dd = Cudd_Init( Vec_IntCountPositive(p->vOrder) + 1, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); - Cudd_SetMaxGrowth( p->dd, 1.05 ); - // set the stop time parameter - p->dd->TimeStop = p->pPars->TimeTarget; - p->vRoots = Llb_Nonlin4DerivePartitions( p->dd, pAig, p->vOrder ); - } - - Llb_Nonlin4SetupVarMap( p->dd, pAig, p->vOrder ); - p->vVars2Q = Llb_Nonlin4CreateVars2Q( p->dd, pAig, p->vOrder, p->pPars->fBackward ); - p->vRings = Vec_PtrAlloc( 100 ); - - if ( pPars->fReorder ) - Llb_Nonlin4Reorder( p->dd, 0, 1 ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MnxStop( Llb_Mnx_t * p ) -{ - DdNode * bTemp; - int i; - if ( p->pPars->fVerbose ) - { - p->timeReo = Cudd_ReadReorderingTime(p->dd); - p->timeOther = p->timeTotal - p->timeImage - p->timeRemap; - ABC_PRTP( "Image ", p->timeImage, p->timeTotal ); - ABC_PRTP( "Remap ", p->timeRemap, p->timeTotal ); - ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); - ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); - ABC_PRTP( " reo ", p->timeReo, p->timeTotal ); - } - // remove BDDs - if ( p->bBad ) - Cudd_RecursiveDeref( p->dd, p->bBad ); - if ( p->bReached ) - Cudd_RecursiveDeref( p->dd, p->bReached ); - if ( p->bCurrent ) - Cudd_RecursiveDeref( p->dd, p->bCurrent ); - if ( p->bNext ) - Cudd_RecursiveDeref( p->dd, p->bNext ); - if ( p->vRings ) - Vec_PtrForEachEntry( DdNode *, p->vRings, bTemp, i ) - Cudd_RecursiveDeref( p->dd, bTemp ); - if ( p->vRoots ) - Vec_PtrForEachEntry( DdNode *, p->vRoots, bTemp, i ) - Cudd_RecursiveDeref( p->dd, bTemp ); - // remove arrays - Vec_PtrFreeP( &p->vRings ); - Vec_PtrFreeP( &p->vRoots ); -//Cudd_PrintInfo( p->dd, stdout ); - Extra_StopManager( p->dd ); - Vec_IntFreeP( &p->vOrder ); - Vec_IntFreeP( &p->vVars2Q ); - ABC_FREE( p ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_MnxCheckNextStateVars( Llb_Mnx_t * p ) -{ - Aig_Obj_t * pObj; - int i, Counter0 = 0, Counter1 = 0; - Saig_ManForEachLi( p->pAig, pObj, i ) - if ( Saig_ObjIsLo(p->pAig, Aig_ObjFanin0(pObj)) ) - { - if ( Aig_ObjFaninC0(pObj) ) - Counter0++; - else - Counter1++; - } - printf( "Total = %d. Direct LO = %d. Compl LO = %d.\n", Aig_ManRegNum(p->pAig), Counter1, Counter0 ); -} - -/**Function************************************************************* - - Synopsis [Finds balanced cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ) -{ - Llb_Mnx_t * pMnn; - int RetValue = -1; - if ( pPars->fVerbose ) - Aig_ManPrintStats( pAig ); - if ( pPars->fCluster && Aig_ManObjNum(pAig) >= (1 << 15) ) - { - printf( "The number of objects is more than 2^15. Clustering cannot be used.\n" ); - return RetValue; - } - { - abctime clk = Abc_Clock(); - pMnn = Llb_MnxStart( pAig, pPars ); -//Llb_MnxCheckNextStateVars( pMnn ); - if ( !pPars->fSkipReach ) - RetValue = Llb_Nonlin4Reachability( pMnn ); - pMnn->timeTotal = Abc_Clock() - clk; - Llb_MnxStop( pMnn ); - } - return RetValue; -} - - -/**Function************************************************************* - - Synopsis [Takes an AIG and returns an AIG representing reachable states.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Llb_ReachableStates( Aig_Man_t * pAig ) -{ - extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); - Vec_Int_t * vPermute; - Vec_Ptr_t * vNames; - Gia_ParLlb_t Pars, * pPars = &Pars; - DdManager * dd; - DdNode * bReached; - Llb_Mnx_t * pMnn; - Abc_Ntk_t * pNtk, * pNtkMuxes; - Aig_Obj_t * pObj; - int i, RetValue; - abctime clk = Abc_Clock(); - - // create parameters - Llb_ManSetDefaultParams( pPars ); - pPars->fSkipOutCheck = 1; - pPars->fCluster = 0; - pPars->fReorder = 0; - pPars->fSilent = 1; - pPars->nBddMax = 100; - pPars->nClusterMax = 500; - - // run reachability - pMnn = Llb_MnxStart( pAig, pPars ); - RetValue = Llb_Nonlin4Reachability( pMnn ); - assert( RetValue == 1 ); - - // print BDD -// Extra_bddPrint( pMnn->dd, pMnn->bReached ); -// Extra_bddPrintSupport( pMnn->dd, pMnn->bReached ); -// printf( "\n" ); - - // collect flop output variables - vPermute = Vec_IntStartFull( Cudd_ReadSize(pMnn->dd) ); - Saig_ManForEachLo( pAig, pObj, i ) - Vec_IntWriteEntry( vPermute, Llb_ObjBddVar(pMnn->vOrder, pObj), i ); - - // transfer the reached state BDD into the new manager - dd = Cudd_Init( Saig_ManRegNum(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - bReached = Extra_TransferPermute( pMnn->dd, dd, pMnn->bReached, Vec_IntArray(vPermute) ); Cudd_Ref( bReached ); - Vec_IntFree( vPermute ); - assert( Cudd_ReadSize(dd) == Saig_ManRegNum(pAig) ); - - // quit reachability engine - pMnn->timeTotal = Abc_Clock() - clk; - Llb_MnxStop( pMnn ); - - // derive the network - vNames = Abc_NodeGetFakeNames( Saig_ManRegNum(pAig) ); - pNtk = Abc_NtkDeriveFromBdd( dd, bReached, "reached", vNames ); - Abc_NodeFreeNames( vNames ); - Cudd_RecursiveDeref( dd, bReached ); - Cudd_Quit( dd ); - - // convert - pNtkMuxes = Abc_NtkBddToMuxes( pNtk ); - Abc_NtkDelete( pNtk ); - pNtk = Abc_NtkStrash( pNtkMuxes, 0, 1, 0 ); - Abc_NtkDelete( pNtkMuxes ); - pAig = Abc_NtkToDar( pNtk, 0, 0 ); - Abc_NtkDelete( pNtk ); - return pAig; -} -Gia_Man_t * Llb_ReachableStatesGia( Gia_Man_t * p ) -{ - Gia_Man_t * pNew; - Aig_Man_t * pAig, * pReached; - pAig = Gia_ManToAigSimple( p ); - pReached = Llb_ReachableStates( pAig ); - Aig_ManStop( pAig ); - pNew = Gia_ManFromAigSimple( pReached ); - Aig_ManStop( pReached ); - return pNew; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/llb/llb4Sweep.c b/src/proof/llb/llb4Sweep.c deleted file mode 100644 index 6b318572..00000000 --- a/src/proof/llb/llb4Sweep.c +++ /dev/null @@ -1,589 +0,0 @@ -/**CFile**************************************************************** - - FileName [llb2Sweep.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD based reachability.] - - Synopsis [Non-linear quantification scheduling.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: llb2Sweep.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "llbInt.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Find good static variable ordering.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4SweepOrder_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vOrder, int * pCounter, int fSaveAll ) -{ - Aig_Obj_t * pFanin0, * pFanin1; - if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) - return; - Aig_ObjSetTravIdCurrent( pAig, pObj ); - assert( Llb_ObjBddVar(vOrder, pObj) < 0 ); - if ( Aig_ObjIsCi(pObj) ) - { - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); - return; - } - // try fanins with higher level first - pFanin0 = Aig_ObjFanin0(pObj); - pFanin1 = Aig_ObjFanin1(pObj); -// if ( pFanin0->Level > pFanin1->Level || (pFanin0->Level == pFanin1->Level && pFanin0->Id < pFanin1->Id) ) - if ( pFanin0->Level > pFanin1->Level ) - { - Llb_Nonlin4SweepOrder_rec( pAig, pFanin0, vOrder, pCounter, fSaveAll ); - Llb_Nonlin4SweepOrder_rec( pAig, pFanin1, vOrder, pCounter, fSaveAll ); - } - else - { - Llb_Nonlin4SweepOrder_rec( pAig, pFanin1, vOrder, pCounter, fSaveAll ); - Llb_Nonlin4SweepOrder_rec( pAig, pFanin0, vOrder, pCounter, fSaveAll ); - } - if ( fSaveAll || pObj->fMarkA ) - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), (*pCounter)++ ); -} - -/**Function************************************************************* - - Synopsis [Find good static variable ordering.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_Nonlin4SweepOrder( Aig_Man_t * pAig, int * pCounter, int fSaveAll ) -{ - Vec_Int_t * vOrder; - Aig_Obj_t * pObj; - int i, Counter = 0; - // collect nodes in the order - vOrder = Vec_IntStartFull( Aig_ManObjNumMax(pAig) ); - Aig_ManIncrementTravId( pAig ); - Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); - Aig_ManForEachCo( pAig, pObj, i ) - { - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); - Llb_Nonlin4SweepOrder_rec( pAig, Aig_ObjFanin0(pObj), vOrder, &Counter, fSaveAll ); - } - Aig_ManForEachCi( pAig, pObj, i ) - if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), Counter++ ); -// assert( Counter == Aig_ManObjNum(pAig) - 1 ); // no dangling nodes - if ( pCounter ) - *pCounter = Counter - Aig_ManCiNum(pAig) - Aig_ManCoNum(pAig); - return vOrder; -} - - -/**Function************************************************************* - - Synopsis [Performs BDD sweep on the netlist.] - - Description [Returns AIG with internal cut points labeled with fMarkA.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Llb4_Nonlin4SweepCutpoints( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nBddLimit, int fVerbose ) -{ - DdManager * dd; - DdNode * bFunc0, * bFunc1, * bFunc; - Aig_Obj_t * pObj; - int i, Counter = 0, Counter1 = 0; - dd = Cudd_Init( Aig_ManObjNumMax(pAig), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - // assign elementary variables - Aig_ManCleanData( pAig ); - Aig_ManForEachCi( pAig, pObj, i ) - pObj->pData = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); - // sweep internal nodes - Aig_ManForEachNode( pAig, pObj, i ) - { -/* - if ( pObj->nRefs >= 4 ) - { - bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); Cudd_Ref( bFunc ); - pObj->pData = bFunc; - Counter1++; - continue; - } -*/ - bFunc0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bFunc1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); - bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); - if ( Cudd_DagSize(bFunc) > nBddLimit ) - { -// if ( fVerbose ) -// printf( "Node %5d : Beg =%5d. ", i, Cudd_DagSize(bFunc) ); - - // add cutpoint at a larger one - Cudd_RecursiveDeref( dd, bFunc ); - if ( Cudd_DagSize(bFunc0) >= Cudd_DagSize(bFunc1) ) - { - Cudd_RecursiveDeref( dd, (DdNode *)Aig_ObjFanin0(pObj)->pData ); - bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, Aig_ObjFanin0(pObj)) ); - Aig_ObjFanin0(pObj)->pData = bFunc; Cudd_Ref( bFunc ); - Aig_ObjFanin0(pObj)->fMarkA = 1; - -// if ( fVerbose ) -// printf( "Ref =%3d ", Aig_ObjFanin0(pObj)->nRefs ); - } - else - { - Cudd_RecursiveDeref( dd, (DdNode *)Aig_ObjFanin1(pObj)->pData ); - bFunc = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, Aig_ObjFanin1(pObj)) ); - Aig_ObjFanin1(pObj)->pData = bFunc; Cudd_Ref( bFunc ); - Aig_ObjFanin1(pObj)->fMarkA = 1; - -// if ( fVerbose ) -// printf( "Ref =%3d ", Aig_ObjFanin1(pObj)->nRefs ); - } - // perform new operation - bFunc0 = Cudd_NotCond( (DdNode *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - bFunc1 = Cudd_NotCond( (DdNode *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); - bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); -// assert( Cudd_DagSize(bFunc) <= nBddLimit ); - -// if ( fVerbose ) -// printf( "End =%5d.\n", Cudd_DagSize(bFunc) ); - Counter++; - } - pObj->pData = bFunc; -//printf( "%d ", Cudd_DagSize(bFunc) ); - } -//printf( "\n" ); - // clean up - Aig_ManForEachNode( pAig, pObj, i ) - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - Extra_StopManager( dd ); -// Aig_ManCleanMarkA( pAig ); - if ( fVerbose ) - printf( "Added %d cut points. Used %d high fanout points.\n", Counter, Counter1 ); - return Counter + Counter1; -} - -/**Function************************************************************* - - Synopsis [Derives BDDs for the partitions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb_Nonlin4SweepPartitions_rec( DdManager * dd, Aig_Obj_t * pObj, Vec_Int_t * vOrder, Vec_Ptr_t * vRoots ) -{ - DdNode * bBdd, * bBdd0, * bBdd1, * bPart, * vVar; - if ( Aig_ObjIsConst1(pObj) ) - return Cudd_ReadOne(dd); - if ( Aig_ObjIsCi(pObj) ) - return Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); - if ( pObj->pData ) - return (DdNode *)pObj->pData; - if ( Aig_ObjIsCo(pObj) ) - { - bBdd0 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) ); - bPart = Cudd_bddXnor( dd, Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ), bBdd0 ); Cudd_Ref( bPart ); - Vec_PtrPush( vRoots, bPart ); - return NULL; - } - bBdd0 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin0(pObj), vOrder, vRoots), Aig_ObjFaninC0(pObj) ); - bBdd1 = Cudd_NotCond( Llb_Nonlin4SweepPartitions_rec(dd, Aig_ObjFanin1(pObj), vOrder, vRoots), Aig_ObjFaninC1(pObj) ); - bBdd = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( bBdd ); - if ( Llb_ObjBddVar(vOrder, pObj) >= 0 ) - { - vVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); - bPart = Cudd_bddXnor( dd, vVar, bBdd ); Cudd_Ref( bPart ); - Vec_PtrPush( vRoots, bPart ); - Cudd_RecursiveDeref( dd, bBdd ); - bBdd = vVar; Cudd_Ref( vVar ); - } - pObj->pData = bBdd; - return bBdd; -} - -/**Function************************************************************* - - Synopsis [Derives BDDs for the partitions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Llb_Nonlin4SweepPartitions( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, int fTransition ) -{ - Vec_Ptr_t * vRoots; - Aig_Obj_t * pObj; - int i; - Aig_ManCleanData( pAig ); - vRoots = Vec_PtrAlloc( 100 ); - if ( fTransition ) - { - Saig_ManForEachLi( pAig, pObj, i ) - Llb_Nonlin4SweepPartitions_rec( dd, pObj, vOrder, vRoots ); - } - else - { - Saig_ManForEachPo( pAig, pObj, i ) - Llb_Nonlin4SweepPartitions_rec( dd, pObj, vOrder, vRoots ); - } - Aig_ManForEachNode( pAig, pObj, i ) - if ( pObj->pData ) - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); - return vRoots; -} - -/**Function************************************************************* - - Synopsis [Get bad state monitor.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Llb4_Nonlin4SweepBadMonitor( Aig_Man_t * pAig, Vec_Int_t * vOrder, DdManager * dd ) -{ - Aig_Obj_t * pObj; - DdNode * bRes, * bVar, * bTemp; - int i; - abctime TimeStop; - TimeStop = dd->TimeStop; dd->TimeStop = 0; - bRes = Cudd_ReadOne( dd ); Cudd_Ref( bRes ); - Saig_ManForEachPo( pAig, pObj, i ) - { - bVar = Cudd_bddIthVar( dd, Llb_ObjBddVar(vOrder, pObj) ); - bRes = Cudd_bddAnd( dd, bTemp = bRes, Cudd_Not(bVar) ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bRes ); - dd->TimeStop = TimeStop; - return Cudd_Not(bRes); -} - -/**Function************************************************************* - - Synopsis [Creates quantifiable variables for both types of traversal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Llb_Nonlin4SweepVars2Q( Aig_Man_t * pAig, Vec_Int_t * vOrder, int fAddLis ) -{ - Vec_Int_t * vVars2Q; - Aig_Obj_t * pObj; - int i; - vVars2Q = Vec_IntAlloc( 0 ); - Vec_IntFill( vVars2Q, Aig_ManObjNumMax(pAig), 1 ); - // add flop outputs - Saig_ManForEachLo( pAig, pObj, i ) - Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 ); - // add flop inputs - if ( fAddLis ) - Saig_ManForEachLi( pAig, pObj, i ) - Vec_IntWriteEntry( vVars2Q, Llb_ObjBddVar(vOrder, pObj), 0 ); - return vVars2Q; -} - -/**Function************************************************************* - - Synopsis [Multiply every partition by the cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4SweepDeref( DdManager * dd, Vec_Ptr_t * vParts ) -{ - DdNode * bFunc; - int i; - Vec_PtrForEachEntry( DdNode *, vParts, bFunc, i ) - Cudd_RecursiveDeref( dd, bFunc ); - Vec_PtrFree( vParts ); -} - -/**Function************************************************************* - - Synopsis [Multiply every partition by the cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4SweepPrint( Vec_Ptr_t * vFuncs ) -{ - DdNode * bFunc; - int i; - printf( "(%d) ", Vec_PtrSize(vFuncs) ); - Vec_PtrForEachEntry( DdNode *, vFuncs, bFunc, i ) - printf( "%d ", Cudd_DagSize(bFunc) ); - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Computes bad states.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdManager * Llb4_Nonlin4SweepBadStates( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nVars ) -{ - DdManager * dd; - Vec_Ptr_t * vParts; - Vec_Int_t * vVars2Q; - DdNode * bMonitor, * bImage; - // get quantifiable variables - vVars2Q = Llb_Nonlin4SweepVars2Q( pAig, vOrder, 0 ); - // start BDD manager and create partitions - dd = Cudd_Init( nVars, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - vParts = Llb_Nonlin4SweepPartitions( dd, pAig, vOrder, 0 ); -//printf( "Outputs: " ); -//Llb_Nonlin4SweepPrint( vParts ); - // compute image of the partitions - bMonitor = Llb4_Nonlin4SweepBadMonitor( pAig, vOrder, dd ); Cudd_Ref( bMonitor ); - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - bImage = Llb_Nonlin4Image( dd, vParts, bMonitor, vVars2Q ); Cudd_Ref( bImage ); - Cudd_RecursiveDeref( dd, bMonitor ); - Llb_Nonlin4SweepDeref( dd, vParts ); - Vec_IntFree( vVars2Q ); - // save image and return - dd->bFunc = bImage; - return dd; -} - -/**Function************************************************************* - - Synopsis [Computes clusters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdManager * Llb4_Nonlin4SweepGroups( Aig_Man_t * pAig, Vec_Int_t * vOrder, int nVars, Vec_Ptr_t ** pvGroups, int nBddLimitClp, int fVerbose ) -{ - DdManager * dd; - Vec_Ptr_t * vParts; - Vec_Int_t * vVars2Q; - // get quantifiable variables - vVars2Q = Llb_Nonlin4SweepVars2Q( pAig, vOrder, 1 ); - // start BDD manager and create partitions - dd = Cudd_Init( nVars, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - vParts = Llb_Nonlin4SweepPartitions( dd, pAig, vOrder, 1 ); -//printf( "Transitions: " ); -//Llb_Nonlin4SweepPrint( vParts ); - // compute image of the partitions - - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - *pvGroups = Llb_Nonlin4Group( dd, vParts, vVars2Q, nBddLimitClp ); - Llb_Nonlin4SweepDeref( dd, vParts ); -// *pvGroups = vParts; - -if ( fVerbose ) -{ -printf( "Groups: " ); -Llb_Nonlin4SweepPrint( *pvGroups ); -} - - Vec_IntFree( vVars2Q ); - return dd; -} - - -/**Function************************************************************* - - Synopsis [Creates quantifiable variables for both types of traversal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb_Nonlin4SweepPrintSuppProfile( DdManager * dd, Aig_Man_t * pAig, Vec_Int_t * vOrder, Vec_Ptr_t * vGroups, int fVerbose ) -{ - Aig_Obj_t * pObj; - int i, * pSupp; - int nSuppAll = 0, nSuppPi = 0, nSuppPo = 0, nSuppLi = 0, nSuppLo = 0, nSuppAnd = 0; - - pSupp = ABC_CALLOC( int, Cudd_ReadSize(dd) ); - Extra_VectorSupportArray( dd, (DdNode **)Vec_PtrArray(vGroups), Vec_PtrSize(vGroups), pSupp ); - - Aig_ManForEachObj( pAig, pObj, i ) - { - if ( Llb_ObjBddVar(vOrder, pObj) < 0 ) - continue; - // remove variables that do not participate - if ( pSupp[Llb_ObjBddVar(vOrder, pObj)] == 0 ) - { - if ( Aig_ObjIsNode(pObj) ) - Vec_IntWriteEntry( vOrder, Aig_ObjId(pObj), -1 ); - continue; - } - nSuppAll++; - if ( Saig_ObjIsPi(pAig, pObj) ) - nSuppPi++; - else if ( Saig_ObjIsLo(pAig, pObj) ) - nSuppLo++; - else if ( Saig_ObjIsPo(pAig, pObj) ) - nSuppPo++; - else if ( Saig_ObjIsLi(pAig, pObj) ) - nSuppLi++; - else - nSuppAnd++; - } - ABC_FREE( pSupp ); - - if ( fVerbose ) - { - printf( "Groups =%3d ", Vec_PtrSize(vGroups) ); - printf( "Variables: all =%4d ", nSuppAll ); - printf( "pi =%4d ", nSuppPi ); - printf( "po =%4d ", nSuppPo ); - printf( "lo =%4d ", nSuppLo ); - printf( "li =%4d ", nSuppLi ); - printf( "and =%4d", nSuppAnd ); - printf( "\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Performs BDD sweep on the netlist.] - - Description [Returns BDD manager, ordering, clusters, and bad states - inside dd->bFunc.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb4_Nonlin4Sweep( Aig_Man_t * pAig, int nSweepMax, int nClusterMax, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int fVerbose ) -{ - DdManager * ddBad, * ddWork; - Vec_Ptr_t * vGroups; - Vec_Int_t * vOrder; - int Counter, nCutPoints; - - // get the original ordering - Aig_ManCleanMarkA( pAig ); - vOrder = Llb_Nonlin4SweepOrder( pAig, &Counter, 1 ); - assert( Counter == Aig_ManNodeNum(pAig) ); - // mark the nodes - nCutPoints = Llb4_Nonlin4SweepCutpoints( pAig, vOrder, nSweepMax, fVerbose ); - Vec_IntFree( vOrder ); - // get better ordering - vOrder = Llb_Nonlin4SweepOrder( pAig, &Counter, 0 ); - assert( Counter == nCutPoints ); - Aig_ManCleanMarkA( pAig ); - // compute the BAD states - ddBad = Llb4_Nonlin4SweepBadStates( pAig, vOrder, nCutPoints + Aig_ManCiNum(pAig) + Aig_ManCoNum(pAig) ); - // compute the clusters - ddWork = Llb4_Nonlin4SweepGroups( pAig, vOrder, nCutPoints + Aig_ManCiNum(pAig) + Aig_ManCoNum(pAig), &vGroups, nClusterMax, fVerbose ); - // transfer the result from the Bad manager -//printf( "Bad before = %d.\n", Cudd_DagSize(ddBad->bFunc) ); - ddWork->bFunc = Cudd_bddTransfer( ddBad, ddWork, ddBad->bFunc ); Cudd_Ref( ddWork->bFunc ); - Cudd_RecursiveDeref( ddBad, ddBad->bFunc ); ddBad->bFunc = NULL; - Extra_StopManager( ddBad ); - // update ordering to exclude quantified variables -//printf( "Bad after = %d.\n", Cudd_DagSize(ddWork->bFunc) ); - - Llb_Nonlin4SweepPrintSuppProfile( ddWork, pAig, vOrder, vGroups, fVerbose ); - - // return the result - *pdd = ddWork; - *pvOrder = vOrder; - *pvGroups = vGroups; -} - -/**Function************************************************************* - - Synopsis [Performs BDD sweep on the netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Llb4_Nonlin4SweepExperiment( Aig_Man_t * pAig ) -{ - DdManager * dd; - Vec_Int_t * vOrder; - Vec_Ptr_t * vGroups; - Llb4_Nonlin4Sweep( pAig, 100, 500, &dd, &vOrder, &vGroups, 1 ); - - Llb_Nonlin4SweepDeref( dd, vGroups ); - - Cudd_RecursiveDeref( dd, dd->bFunc ); - Extra_StopManager( dd ); - Vec_IntFree( vOrder ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/proof/llb/llbInt.h b/src/proof/llb/llbInt.h deleted file mode 100644 index e2afe59a..00000000 --- a/src/proof/llb/llbInt.h +++ /dev/null @@ -1,212 +0,0 @@ -/**CFile**************************************************************** - - FileName [llbInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [BDD-based reachability.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 8, 2010.] - - Revision [$Id: llbInt.h,v 1.00 2010/05/08 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef ABC__aig__llb__llbInt_h -#define ABC__aig__llb__llbInt_h - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include "aig/aig/aig.h" -#include "aig/saig/saig.h" -#include "proof/ssw/ssw.h" -#include "llb.h" - -#include "misc/extra/extraBdd.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -ABC_NAMESPACE_HEADER_START - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Llb_Man_t_ Llb_Man_t; -typedef struct Llb_Mtr_t_ Llb_Mtr_t; -typedef struct Llb_Grp_t_ Llb_Grp_t; - -struct Llb_Man_t_ -{ - Gia_ParLlb_t * pPars; // parameters - Aig_Man_t * pAigGlo; // initial AIG manager (owned by the caller) - Aig_Man_t * pAig; // derived AIG manager (created in this package) - DdManager * dd; // BDD manager - DdManager * ddG; // BDD manager - DdManager * ddR; // BDD manager - Vec_Int_t * vObj2Var; // mapping AIG ObjId into BDD var index - Vec_Int_t * vVar2Obj; // mapping BDD var index into AIG ObjId - Vec_Ptr_t * vGroups; // group Id into group pointer - Llb_Mtr_t * pMatrix; // dependency matrix - // image computation - Vec_Ptr_t * vRings; // onion rings - Vec_Int_t * vVarBegs; // the first group where the var appears - Vec_Int_t * vVarEnds; // the last group where the var appears - // variable mapping - Vec_Int_t * vNs2Glo; // next state variables into global variables - Vec_Int_t * vCs2Glo; // next state variables into global variables - Vec_Int_t * vGlo2Cs; // global variables into current state variables - Vec_Int_t * vGlo2Ns; // global variables into current state variables - // flow computation -// Vec_Int_t * vMem; -// Vec_Ptr_t * vTops; -// Vec_Ptr_t * vBots; -// Vec_Ptr_t * vCuts; -}; - -struct Llb_Mtr_t_ -{ - int nPis; // number of primary inputs - int nFfs; // number of flip-flops - int nRows; // number of rows - int nCols; // number of columns - int * pColSums; // sum of values in a column - Llb_Grp_t ** pColGrps; // group structure for each col - int * pRowSums; // sum of values in a row - char ** pMatrix; // dependency matrix - Llb_Man_t * pMan; // manager - // partial product - char * pProdVars; // variables in the partial product - int * pProdNums; // var counts in the remaining partitions -}; - -struct Llb_Grp_t_ -{ - int Id; // group ID - Vec_Ptr_t * vIns; // input AIG objs - Vec_Ptr_t * vOuts; // output AIG objs - Vec_Ptr_t * vNodes; // internal AIG objs - Llb_Man_t * pMan; // manager - Llb_Grp_t * pPrev; // previous group - Llb_Grp_t * pNext; // next group -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline int Llb_ObjBddVar( Vec_Int_t * vOrder, Aig_Obj_t * pObj ) { return Vec_IntEntry(vOrder, Aig_ObjId(pObj)); } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== llbConstr.c ======================================================*/ -extern Vec_Int_t * Llb_ManDeriveConstraints( Aig_Man_t * p ); -extern void Llb_ManPrintEntries( Aig_Man_t * p, Vec_Int_t * vCands ); -/*=== llbCore.c ======================================================*/ -extern int Llb_ManModelCheckAig( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars, Vec_Int_t * vHints, DdManager ** pddGlo ); -/*=== llbCluster.c ======================================================*/ -extern void Llb_ManCluster( Llb_Mtr_t * p ); -/*=== llbDump.c ======================================================*/ -extern void Llb_ManDumpReached( DdManager * ddG, DdNode * bReached, char * pModel, char * pFileName ); -/*=== llbFlow.c ======================================================*/ -extern Vec_Ptr_t * Llb_ManFlow( Aig_Man_t * p, Vec_Ptr_t * vSources, int * pnFlow ); -/*=== llbHint.c ======================================================*/ -extern int Llb_ManReachabilityWithHints( Llb_Man_t * p ); -extern int Llb_ManModelCheckAigWithHints( Aig_Man_t * pAigGlo, Gia_ParLlb_t * pPars ); -/*=== llbMan.c =======================================================*/ -extern void Llb_ManPrepareVarMap( Llb_Man_t * p ); -extern Llb_Man_t * Llb_ManStart( Aig_Man_t * pAigGlo, Aig_Man_t * pAig, Gia_ParLlb_t * pPars ); -extern void Llb_ManStop( Llb_Man_t * p ); -/*=== llbMatrix.c ====================================================*/ -extern void Llb_MtrVerifyMatrix( Llb_Mtr_t * p ); -extern Llb_Mtr_t * Llb_MtrCreate( Llb_Man_t * p ); -extern void Llb_MtrFree( Llb_Mtr_t * p ); -extern void Llb_MtrPrint( Llb_Mtr_t * p, int fOrder ); -extern void Llb_MtrPrintMatrixStats( Llb_Mtr_t * p ); -/*=== llbPart.c ======================================================*/ -extern Llb_Grp_t * Llb_ManGroupAlloc( Llb_Man_t * pMan ); -extern void Llb_ManGroupStop( Llb_Grp_t * p ); -extern void Llb_ManPrepareGroups( Llb_Man_t * pMan ); -extern Llb_Grp_t * Llb_ManGroupsCombine( Llb_Grp_t * p1, Llb_Grp_t * p2 ); -extern Llb_Grp_t * Llb_ManGroupCreateFromCuts( Llb_Man_t * pMan, Vec_Int_t * vCut1, Vec_Int_t * vCut2 ); -extern void Llb_ManPrepareVarLimits( Llb_Man_t * p ); -/*=== llbPivot.c =====================================================*/ -extern int Llb_ManTracePaths( Aig_Man_t * p, Aig_Obj_t * pPivot ); -extern Vec_Int_t * Llb_ManMarkPivotNodes( Aig_Man_t * p, int fUseInternal ); -/*=== llbReach.c =====================================================*/ -extern int Llb_ManReachability( Llb_Man_t * p, Vec_Int_t * vHints, DdManager ** pddGlo ); -/*=== llbSched.c =====================================================*/ -extern void Llb_MtrSchedule( Llb_Mtr_t * p ); - -/*=== llb2Bad.c ======================================================*/ -extern DdNode * Llb_BddComputeBad( Aig_Man_t * pInit, DdManager * dd, abctime TimeOut ); -extern DdNode * Llb_BddQuantifyPis( Aig_Man_t * pInit, DdManager * dd, DdNode * bFunc ); -/*=== llb2Core.c ======================================================*/ -extern DdNode * Llb_CoreComputeCube( DdManager * dd, Vec_Int_t * vVars, int fUseVarIndex, char * pValues ); -extern int Llb_CoreExperiment( Aig_Man_t * pInit, Aig_Man_t * pAig, Gia_ParLlb_t * pPars, Vec_Ptr_t * vResult, abctime TimeTarget ); -/*=== llb2Driver.c ======================================================*/ -extern Vec_Int_t * Llb_DriverCountRefs( Aig_Man_t * p ); -extern Vec_Int_t * Llb_DriverCollectNs( Aig_Man_t * pAig, Vec_Int_t * vDriRefs ); -extern Vec_Int_t * Llb_DriverCollectCs( Aig_Man_t * pAig ); -extern DdNode * Llb_DriverPhaseCube( Aig_Man_t * pAig, Vec_Int_t * vDriRefs, DdManager * dd ); -extern DdManager * Llb_DriverLastPartition( Aig_Man_t * p, Vec_Int_t * vVarsNs, abctime TimeTarget ); -/*=== llb2Image.c ======================================================*/ -extern Vec_Ptr_t * Llb_ImgSupports( Aig_Man_t * p, Vec_Ptr_t * vDdMans, Vec_Int_t * vStart, Vec_Int_t * vStop, int fAddPis, int fVerbose ); -extern void Llb_ImgSchedule( Vec_Ptr_t * vSupps, Vec_Ptr_t ** pvQuant0, Vec_Ptr_t ** pvQuant1, int fVerbose ); -extern DdManager * Llb_ImgPartition( Aig_Man_t * p, Vec_Ptr_t * vLower, Vec_Ptr_t * vUpper, abctime TimeTarget ); -extern void Llb_ImgQuantifyFirst( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, Vec_Ptr_t * vQuant0, int fVerbose ); -extern void Llb_ImgQuantifyReset( Vec_Ptr_t * vDdMans ); -extern DdNode * Llb_ImgComputeImage( Aig_Man_t * pAig, Vec_Ptr_t * vDdMans, DdManager * dd, DdNode * bInit, - Vec_Ptr_t * vQuant0, Vec_Ptr_t * vQuant1, Vec_Int_t * vDriRefs, - abctime TimeTarget, int fBackward, int fReorder, int fVerbose ); - -extern DdManager * Llb_NonlinImageStart( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, int * pOrder, int fFirst, abctime TimeTarget ); -extern DdNode * Llb_NonlinImageCompute( DdNode * bCurrent, int fReorder, int fDrop, int fVerbose, int * pOrder ); -extern void Llb_NonlinImageQuit(); - -/*=== llb3Image.c =======================================================*/ -extern DdNode * Llb_NonlinImage( Aig_Man_t * pAig, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int * pVars2Q, - DdManager * dd, DdNode * bCurrent, int fReorder, int fVerbose, int * pOrder ); -/*=== llb3Nonlin.c ======================================================*/ -extern DdNode * Llb_NonlinComputeInitState( Aig_Man_t * pAig, DdManager * dd ); - - -/*=== llb4Cex.c =======================================================*/ -extern Abc_Cex_t * Llb4_Nonlin4TransformCex( Aig_Man_t * pAig, Vec_Ptr_t * vStates, int iCexPo, int fVerbose ); -/*=== llb4Cluster.c =======================================================*/ -//extern void Llb_Nonlin4Cluster( Aig_Man_t * pAig, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int nBddMax, int fVerbose ); -/*=== llb4Image.c =======================================================*/ -extern DdNode * Llb_Nonlin4Image( DdManager * dd, Vec_Ptr_t * vParts, DdNode * bCurrent, Vec_Int_t * vVars2Q ); -extern Vec_Ptr_t * Llb_Nonlin4Group( DdManager * dd, Vec_Ptr_t * vParts, Vec_Int_t * vVars2Q, int nSizeMax ); -/*=== llb4Map.c =========================================================*/ -//extern Vec_Int_t * Llb_AigMap( Aig_Man_t * pAig, int nLutSize, int nLutMin ); -/*=== llb4Nonlin.c ======================================================*/ -//extern int Llb_Nonlin4CoreReach( Aig_Man_t * pAig, Gia_ParLlb_t * pPars ); -/*=== llb4Sweep.c ======================================================*/ -extern void Llb4_Nonlin4Sweep( Aig_Man_t * pAig, int nSweepMax, int nClusterMax, DdManager ** pdd, Vec_Int_t ** pvOrder, Vec_Ptr_t ** pvGroups, int fVerbose ); - - -ABC_NAMESPACE_HEADER_END - - - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/proof/llb/module.make b/src/proof/llb/module.make deleted file mode 100644 index b08c42af..00000000 --- a/src/proof/llb/module.make +++ /dev/null @@ -1,22 +0,0 @@ -SRC += src/proof/llb/llb1Cluster.c \ - src/proof/llb/llb1Constr.c \ - src/proof/llb/llb1Core.c \ - src/proof/llb/llb1Group.c \ - src/proof/llb/llb1Hint.c \ - src/proof/llb/llb1Man.c \ - src/proof/llb/llb1Matrix.c \ - src/proof/llb/llb1Pivot.c \ - src/proof/llb/llb1Reach.c \ - src/proof/llb/llb1Sched.c \ - src/proof/llb/llb2Bad.c \ - src/proof/llb/llb2Core.c \ - src/proof/llb/llb2Driver.c \ - src/proof/llb/llb2Dump.c \ - src/proof/llb/llb2Flow.c \ - src/proof/llb/llb2Image.c \ - src/proof/llb/llb3Image.c \ - src/proof/llb/llb3Nonlin.c \ - src/proof/llb/llb4Cex.c \ - src/proof/llb/llb4Image.c \ - src/proof/llb/llb4Nonlin.c \ - src/proof/llb/llb4Sweep.c -- cgit v1.2.3